summaryrefslogtreecommitdiff
path: root/src/http/ngx_http.c
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-05-26 09:32:48 +0000
committerJonathan Kolb <jon@b0g.us>2008-05-26 09:32:48 +0000
commit97647a9b9023a209f1c33a092722ddcc100dfc1a (patch)
tree97b01690fdeba47c65deb1cb541b691c83e92f6d /src/http/ngx_http.c
parent013f90472501bd911bd82c90e6aa1879d3d4c4fe (diff)
downloadnginx-97647a9b9023a209f1c33a092722ddcc100dfc1a.tar.gz
Changes with nginx 0.7.1 26 May 2008v0.7.1
*) Change: now locations are searched in a tree. *) Change: the "optimize_server_names" directive was canceled due to the "server_name_in_redirect" directive introduction. *) Change: some long deprecated directives are not supported anymore. *) Change: the "none" parameter in the "ssl_session_cache" directive; now this is default parameter. Thanks to Rob Mueller. *) Bugfix: worker processes might not catch reconfiguration and log rotation signals. *) Bugfix: nginx could not be built on latest Fedora 9 Linux. Thanks to Roxis.
Diffstat (limited to 'src/http/ngx_http.c')
-rw-r--r--src/http/ngx_http.c1410
1 files changed, 984 insertions, 426 deletions
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 3ef1dcbc8..a1c4c9892 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -11,22 +11,48 @@
static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
+ ngx_http_core_main_conf_t *cmcf);
+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_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
ngx_uint_t ctx_index);
+static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
+ ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
+static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
+ ngx_http_core_loc_conf_t *pclcf);
+static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
+ const ngx_queue_t *two);
+static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
+ ngx_queue_t *locations);
+static void ngx_http_create_locations_list(ngx_queue_t *locations,
+ ngx_queue_t *q);
+static ngx_http_location_tree_node_t *
+ ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
+ size_t prefix);
+
+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);
-ngx_uint_t ngx_http_max_module;
+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_total_requests;
-uint64_t ngx_http_total_sent;
+ngx_uint_t ngx_http_max_module;
ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
@@ -73,34 +99,14 @@ static char *
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
- ngx_int_t rc, j;
- ngx_uint_t mi, m, s, l, p, a, i, n;
- ngx_uint_t find_config_index, use_rewrite, use_access;
- ngx_uint_t last, bind_all, done;
+ ngx_uint_t mi, m, s;
ngx_conf_t pcf;
- ngx_array_t headers_in, in_ports;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_listening_t *ls;
- ngx_http_listen_t *lscf;
+ ngx_array_t in_ports;
ngx_http_module_t *module;
- ngx_http_header_t *header;
- ngx_http_in_port_t *hip;
- ngx_http_handler_pt *h;
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_phase_handler_t *ph;
- ngx_http_virtual_names_t *vn;
- ngx_http_core_srv_conf_t **cscfp, *cscf;
ngx_http_core_loc_conf_t *clcf;
- ngx_http_phase_handler_pt checker;
+ 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 */
@@ -199,7 +205,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
module = ngx_modules[m]->ctx;
- mi = ngx_modules[m]->ctx_index;
if (module->preconfiguration) {
if (module->preconfiguration(cf) != NGX_OK) {
@@ -215,8 +220,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
rv = ngx_conf_parse(cf, NULL);
if (rv != NGX_CONF_OK) {
- *cf = pcf;
- return rv;
+ goto failed;
}
/*
@@ -240,8 +244,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (module->init_main_conf) {
rv = module->init_main_conf(cf, ctx->main_conf[mi]);
if (rv != NGX_CONF_OK) {
- *cf = pcf;
- return rv;
+ goto failed;
}
}
@@ -250,12 +253,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
/* merge the server{}s' srv_conf's */
if (module->merge_srv_conf) {
- rv = module->merge_srv_conf(cf,
- ctx->srv_conf[mi],
+ rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
cscfp[s]->ctx->srv_conf[mi]);
if (rv != NGX_CONF_OK) {
- *cf = pcf;
- return rv;
+ goto failed;
}
}
@@ -263,96 +264,187 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
/* merge the server{}'s loc_conf */
- rv = module->merge_loc_conf(cf,
- ctx->loc_conf[mi],
+ rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
cscfp[s]->ctx->loc_conf[mi]);
if (rv != NGX_CONF_OK) {
- *cf = pcf;
- return rv;
+ goto failed;
}
/* merge the locations{}' loc_conf's */
- rv = ngx_http_merge_locations(cf, &cscfp[s]->locations,
+ clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
+
+ rv = ngx_http_merge_locations(cf, clcf->locations,
cscfp[s]->ctx->loc_conf,
module, mi);
if (rv != NGX_CONF_OK) {
- *cf = pcf;
- return rv;
+ goto failed;
}
}
}
}
- /* init lists of the handlers */
+ /* create location trees */
+
+ for (s = 0; s < cmcf->servers.nelts; s++) {
+
+ clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
+
+ if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+
+ if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+
+ for (m = 0; ngx_modules[m]; m++) {
+ if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
+ continue;
+ }
+
+ module = ngx_modules[m]->ctx;
+
+ if (module->postconfiguration) {
+ if (module->postconfiguration(cf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+ }
+
+ if (ngx_http_variables_init_vars(cf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * http{}'s cf->ctx was needed while the configuration merging
+ * and in postconfiguration process
+ */
+ *cf = pcf;
+
+
+ if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+
+ /*
+ * create the lists of ports, addresses and server names
+ * to find quickly the server core module configuration at run-time
+ */
+
+ /* 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;
+
+failed:
+
+ *cf = pcf;
+
+ return rv;
+}
+
+
+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_CONF_ERROR;
+ 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_CONF_ERROR;
+ 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_CONF_ERROR;
+ 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_CONF_ERROR;
+ 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_CONF_ERROR;
+ 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_CONF_ERROR;
+ 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_CONF_ERROR;
+ 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_CONF_ERROR;
+ return NGX_ERROR;
}
for (header = ngx_http_headers_in; header->name.len; header++) {
hk = ngx_array_push(&headers_in);
if (hk == NULL) {
- return NGX_CONF_ERROR;
+ return NGX_ERROR;
}
hk->key = header->name;
@@ -369,36 +461,22 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
hash.temp_pool = NULL;
if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-
- for (m = 0; ngx_modules[m]; m++) {
- if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
- continue;
- }
-
- module = ngx_modules[m]->ctx;
- mi = ngx_modules[m]->ctx_index;
-
- if (module->postconfiguration) {
- if (module->postconfiguration(cf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
- }
-
- if (ngx_http_variables_init_vars(cf) != NGX_OK) {
- return NGX_CONF_ERROR;
+ return NGX_ERROR;
}
- /*
- * http{}'s cf->ctx was needed while the configuration merging
- * and in postconfiguration process
- */
+ return NGX_OK;
+}
- *cf = pcf;
+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;
@@ -415,7 +493,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ph = ngx_pcalloc(cf->pool,
n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
if (ph == NULL) {
- return NGX_CONF_ERROR;
+ return NGX_ERROR;
}
cmcf->phase_engine.handlers = ph;
@@ -493,35 +571,548 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
+ return NGX_OK;
+}
- /*
- * create the lists of ports, addresses and server names
- * to quickly find the server core module configuration at run-time
- */
- if (ngx_array_init(&in_ports, cf->temp_pool, 2,
+static char *
+ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
+ void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
+{
+ char *rv;
+ ngx_queue_t *q;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_location_queue_t *lq;
+
+ if (locations == NULL) {
+ return NGX_CONF_OK;
+ }
+
+ for (q = ngx_queue_head(locations);
+ q != ngx_queue_sentinel(locations);
+ q = ngx_queue_next(q))
+ {
+ lq = (ngx_http_location_queue_t *) q;
+
+ clcf = lq->exact ? lq->exact : lq->inclusive;
+
+ rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
+ clcf->loc_conf[ctx_index]);
+ if (rv != NGX_CONF_OK) {
+ return rv;
+ }
+
+ rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
+ module, ctx_index);
+ if (rv != NGX_CONF_OK) {
+ return rv;
+ }
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+ ngx_http_core_loc_conf_t *pclcf)
+{
+ ngx_uint_t n;
+ ngx_queue_t *q, *locations, *named, tail;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_location_queue_t *lq;
+ ngx_http_core_loc_conf_t **clcfp;
+#if (NGX_PCRE)
+ ngx_uint_t r;
+ ngx_queue_t *regex;
+#endif
+
+ locations = pclcf->locations;
+
+ if (locations == NULL) {
+ return NGX_OK;
+ }
+
+ ngx_queue_sort(locations, ngx_http_cmp_locations);
+
+ named = NULL;
+ n = 0;
+#if (NGX_PCRE)
+ regex = NULL;
+ r = 0;
+#endif
+
+ for (q = ngx_queue_head(locations);
+ q != ngx_queue_sentinel(locations);
+ q = ngx_queue_next(q))
+ {
+ lq = (ngx_http_location_queue_t *) q;
+
+ clcf = lq->exact ? lq->exact : lq->inclusive;
+
+ if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+#if (NGX_PCRE)
+
+ if (clcf->regex) {
+ r++;
+
+ if (regex == NULL) {
+ regex = q;
+ }
+
+ continue;
+ }
+
+#endif
+
+ if (clcf->named) {
+ n++;
+
+ if (named == NULL) {
+ named = q;
+ }
+
+ continue;
+ }
+
+ if (clcf->noname) {
+ break;
+ }
+ }
+
+ if (q != ngx_queue_sentinel(locations)) {
+ ngx_queue_split(locations, q, &tail);
+ }
+
+ if (named) {
+ clcfp = ngx_palloc(cf->pool,
+ (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
+ if (clcfp == NULL) {
+ return NGX_ERROR;
+ }
+
+ cscf->named_locations = clcfp;
+
+ for (q = named;
+ q != ngx_queue_sentinel(locations);
+ q = ngx_queue_next(q))
+ {
+ lq = (ngx_http_location_queue_t *) q;
+
+ *(clcfp++) = lq->exact;
+ }
+
+ *clcfp = NULL;
+
+ ngx_queue_split(locations, named, &tail);
+ }
+
+#if (NGX_PCRE)
+
+ if (regex) {
+
+ clcfp = ngx_palloc(cf->pool,
+ (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
+ if (clcfp == NULL) {
+ return NGX_ERROR;
+ }
+
+ pclcf->regex_locations = clcfp;
+
+ for (q = regex;
+ q != ngx_queue_sentinel(locations);
+ q = ngx_queue_next(q))
+ {
+ lq = (ngx_http_location_queue_t *) q;
+
+ *(clcfp++) = lq->exact;
+ }
+
+ *clcfp = NULL;
+
+ ngx_queue_split(locations, regex, &tail);
+ }
+
+#endif
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_init_static_location_trees(ngx_conf_t *cf,
+ ngx_http_core_loc_conf_t *pclcf)
+{
+ ngx_queue_t *q, *locations;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_location_queue_t *lq;
+
+ locations = pclcf->locations;
+
+ if (locations == NULL) {
+ return NGX_OK;
+ }
+
+ if (ngx_queue_empty(locations)) {
+ return NGX_OK;
+ }
+
+ for (q = ngx_queue_head(locations);
+ q != ngx_queue_sentinel(locations);
+ q = ngx_queue_next(q))
+ {
+ lq = (ngx_http_location_queue_t *) q;
+
+ clcf = lq->exact ? lq->exact : lq->inclusive;
+
+ if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+
+ if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_create_locations_list(locations, ngx_queue_head(locations));
+
+ pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
+ if (pclcf->static_locations == NULL) {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
+ ngx_http_core_loc_conf_t *clcf)
+{
+ ngx_http_location_queue_t *lq;
+
+ if (*locations == NULL) {
+ *locations = ngx_palloc(cf->temp_pool,
+ sizeof(ngx_http_location_queue_t));
+ if (*locations == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_queue_init(*locations);
+ }
+
+ lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
+ if (lq == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (clcf->exact_match
+#if (NGX_PCRE)
+ || clcf->regex
+#endif
+ || clcf->named || clcf->noname)
+ {
+ lq->exact = clcf;
+ lq->inclusive = NULL;
+
+ } else {
+ lq->exact = NULL;
+ lq->inclusive = clcf;
+ }
+
+ lq->name = &clcf->name;
+ lq->file_name = cf->conf_file->file.name.data;
+ lq->line = cf->conf_file->line;
+
+ ngx_queue_init(&lq->list);
+
+ ngx_queue_insert_tail(*locations, &lq->queue);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
+{
+ ngx_int_t rc;
+ ngx_http_core_loc_conf_t *first, *second;
+ ngx_http_location_queue_t *lq1, *lq2;
+
+ lq1 = (ngx_http_location_queue_t *) one;
+ lq2 = (ngx_http_location_queue_t *) two;
+
+ first = lq1->exact ? lq1->exact : lq1->inclusive;
+ second = lq2->exact ? lq2->exact : lq2->inclusive;
+
+ if (first->noname && !second->noname) {
+ /* shift no named locations to the end */
+ return 1;
+ }
+
+ if (!first->noname && second->noname) {
+ /* shift no named locations to the end */
+ return -1;
+ }
+
+ if (first->noname || second->noname) {
+ /* do not sort no named locations */
+ return 0;
+ }
+
+ if (first->named && !second->named) {
+ /* shift named locations to the end */
+ return 1;
+ }
+
+ if (!first->named && second->named) {
+ /* shift named locations to the end */
+ return -1;
+ }
+
+ if (first->named && second->named) {
+ return ngx_strcmp(first->name.data, second->name.data);
+ }
+
+#if (NGX_PCRE)
+
+ if (first->regex && !second->regex) {
+ /* shift the regex matches to the end */
+ return 1;
+ }
+
+ if (!first->regex && second->regex) {
+ /* shift the regex matches to the end */
+ return -1;
+ }
+
+ if (first->regex || second->regex) {
+ /* do not sort the regex matches */
+ return 0;
+ }
+
+#endif
+
+ rc = ngx_strcmp(first->name.data, second->name.data);
+
+ if (rc == 0 && !first->exact_match && second->exact_match) {
+ /* an exact match must be before the same inclusive one */
+ return 1;
+ }
+
+ return rc;
+}
+
+
+static ngx_int_t
+ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
+{
+ ngx_queue_t *q, *x;
+ ngx_http_location_queue_t *lq, *lx;
+
+ q = ngx_queue_head(locations);
+
+ while (q != ngx_queue_last(locations)) {
+
+ x = ngx_queue_next(q);
+
+ lq = (ngx_http_location_queue_t *) q;
+ lx = (ngx_http_location_queue_t *) x;
+
+ if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
+
+ if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "duplicate location \"%V\" in %s:%ui",
+ lx->name, lx->file_name, lx->line);
+
+ return NGX_ERROR;
+ }
+
+ lq->inclusive = lx->inclusive;
+
+ ngx_queue_remove(x);
+
+ continue;
+ }
+
+ q = ngx_queue_next(q);
+ }
+
+ return NGX_OK;
+}
+
+
+static void
+ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
+{
+ u_char *name;
+ size_t len;
+ ngx_queue_t *x, tail;
+ ngx_http_location_queue_t *lq, *lx;
+
+ if (q == ngx_queue_last(locations)) {
+ return;
+ }
+
+ lq = (ngx_http_location_queue_t *) q;
+
+ if (lq->inclusive == NULL) {
+ ngx_http_create_locations_list(locations, ngx_queue_next(q));
+ return;
+ }
+
+ len = lq->name->len;
+ name = lq->name->data;
+
+ for (x = ngx_queue_next(q);
+ x != ngx_queue_sentinel(locations);
+ x = ngx_queue_next(x))
+ {
+ lx = (ngx_http_location_queue_t *) x;
+
+ if (len > lx->name->len
+ || (ngx_strncmp(name, lx->name->data, len) != 0))
+ {
+ break;
+ }
+ }
+
+ q = ngx_queue_next(q);
+
+ if (q == x) {
+ ngx_http_create_locations_list(locations, x);
+ return;
+ }
+
+ ngx_queue_split(locations, q, &tail);
+ ngx_queue_add(&lq->list, &tail);
+
+ if (x == ngx_queue_sentinel(locations)) {
+ ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
+ return;
+ }
+
+ ngx_queue_split(&lq->list, x, &tail);
+ ngx_queue_add(locations, &tail);
+
+ ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
+
+ ngx_http_create_locations_list(locations, x);
+}
+
+
+/*
+ * to keep cache locality for left leaf nodes, allocate nodes in following
+ * order: node, left subtree, right subtree, inclusive subtree
+ */
+
+static ngx_http_location_tree_node_t *
+ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
+ size_t prefix)
+{
+ size_t len;
+ ngx_queue_t *q, tail;
+ ngx_http_location_queue_t *lq;
+ ngx_http_location_tree_node_t *node;
+
+ q = ngx_queue_middle(locations);
+
+ lq = (ngx_http_location_queue_t *) q;
+ len = lq->name->len - prefix;
+
+ node = ngx_pcalloc(cf->pool,
+ offsetof(ngx_http_location_tree_node_t, name) + len);
+ if (node == NULL) {
+ return NULL;
+ }
+
+ node->exact = lq->exact;
+ node->inclusive = lq->inclusive;
+
+ node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
+ || (lq->inclusive && lq->inclusive->auto_redirect));
+
+ node->len = (u_char) len;
+ ngx_memcpy(node->name, &lq->name->data[prefix], len);
+
+ ngx_queue_split(locations, q, &tail);
+
+ if (ngx_queue_empty(locations)) {
+ /*
+ * ngx_queue_split() insures that if left part is empty,
+ * then right one is empty too
+ */
+ goto inclusive;
+ }
+
+ node->left = ngx_http_create_locations_tree(cf, locations, prefix);
+ if (node->left == NULL) {
+ return NULL;
+ }
+
+ ngx_queue_remove(q);
+
+ if (ngx_queue_empty(&tail)) {
+ goto inclusive;
+ }
+
+ node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
+ if (node->right == NULL) {
+ return NULL;
+ }
+
+inclusive:
+
+ if (ngx_queue_empty(&lq->list)) {
+ return node;
+ }
+
+ node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
+ if (node->tree == NULL) {
+ return NULL;
+ }
+
+ return node;
+}
+
+
+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;
}
@@ -530,15 +1121,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;
}
/*
@@ -546,14 +1137,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];
@@ -568,10 +1159,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;
@@ -579,17 +1170,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:
@@ -598,21 +1190,132 @@ 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)
+ */
+
+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;
+
+ 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);
+}
- in_port = in_ports.elts;
- for (p = 0; p < in_ports.nelts; p++) {
+
+/*
+ * 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 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
- * as the default server,
- * or some servers disable optimizing the server names
+ * check whether all name-based servers have
+ * the same configuraiton as the default server
*/
in_addr = in_port[p].addrs.elts;
@@ -621,18 +1324,15 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
name = in_addr[a].names.elts;
for (s = 0; s < in_addr[a].names.nelts; s++) {
- if (in_addr[a].core_srv_conf != name[s].core_srv_conf
- || name[s].core_srv_conf->optimize_server_names == 0)
- {
+ if (in_addr[a].core_srv_conf != name[s].core_srv_conf) {
goto virtual_names;
}
}
/*
* if all name-based servers have the same configuration
- * as the default server,
- * and no servers disable optimizing the server names
- * then we do not need to check them at run-time at all
+ * as the default server, then we do not need to check
+ * them at run-time at all
*/
in_addr[a].names.nelts = 0;
@@ -645,14 +1345,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)
@@ -674,14 +1373,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) {
@@ -703,8 +1402,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;
}
}
@@ -722,8 +1420,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;
@@ -743,8 +1440,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;
@@ -763,7 +1459,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++) {
@@ -774,357 +1470,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 (in_addr[last - 1].addr == INADDR_ANY) {
- in_addr[last - 1].bind = 1;
- bind_all = 0;
-
- } else {
- bind_all = 1;
+ if (ngx_http_init_listening(cf, &in_port[p]) != NGX_OK) {
+ return NGX_ERROR;
}
+ }
- for (a = 0; a < last; /* void */ ) {
-
- if (!bind_all && !in_addr[a].bind) {
- a++;
- continue;
- }
-
- 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;
-
- ls->handler = ngx_http_init_connection;
-
- cscf = in_addr[a].core_srv_conf;
- ls->pool_size = cscf->connection_pool_size;
- ls->post_accept_timeout = cscf->client_header_timeout;
-
- clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
+ return NGX_OK;
- ls->log = *clcf->err_log;
- ls->log.data = &ls->addr_text;
- ls->log.handler = ngx_accept_log_error;
+failed:
-#if (NGX_WIN32)
- {
- ngx_iocp_conf_t *iocpcf;
+ ngx_destroy_pool(ha.temp_pool);
- 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_ERROR;
+}
- 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_cmp_conf_in_addrs(const void *one, const void *two)
+{
+ ngx_http_conf_in_addr_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_http_conf_in_addr_t *) one;
+ second = (ngx_http_conf_in_addr_t *) two;
- hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
- if (hip == NULL) {
- return NGX_CONF_ERROR;
- }
+ if (first->addr == INADDR_ANY) {
+ /* the INADDR_ANY must be the last resort, shift it to the end */
+ return 1;
+ }
- hip->port = in_port[p].port;
+ if (first->bind && !second->bind) {
+ /* shift explicit bind()ed addresses to the start */
+ return -1;
+ }
- hip->port_text.data = ngx_palloc(cf->pool, 7);
- if (hip->port_text.data == NULL) {
- return NGX_CONF_ERROR;
- }
+ if (!first->bind && second->bind) {
+ /* shift explicit bind()ed addresses to the start */
+ return 1;
+ }
- ls->servers = hip;
+ /* do not sort by default */
- hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d",
- hip->port)
- - hip->port_text.data;
+ return 0;
+}
- in_addr = in_port[p].addrs.elts;
- if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
- hip->naddrs = 1;
- done = 0;
+static int ngx_libc_cdecl
+ngx_http_cmp_dns_wildcards(const void *one, const void *two)
+{
+ ngx_hash_key_t *first, *second;
- } else if (in_port[p].addrs.nelts > 1
- && in_addr[last - 1].addr == INADDR_ANY)
- {
- hip->naddrs = last;
- done = 1;
+ first = (ngx_hash_key_t *) one;
+ second = (ngx_hash_key_t *) two;
- } else {
- hip->naddrs = 1;
- done = 0;
- }
+ return ngx_strcmp(first->key.data, second->key.data);
+}
-#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
- hip->addrs = ngx_pcalloc(cf->pool,
- hip->naddrs * sizeof(ngx_http_in_addr_t));
- if (hip->addrs == 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;
- 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;
+ in_addr = in_port->addrs.elts;
+ last = in_port->addrs.nelts;
- 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;
- }
+ /*
+ * if there is a binding to a "*:port" then we need to bind()
+ * to the "*:port" only and ignore other bindings
+ */
- vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
- if (vn == NULL) {
- return NGX_CONF_ERROR;
- }
- hip->addrs[i].virtual_names = vn;
+ if (in_addr[last - 1].addr == INADDR_ANY) {
+ in_addr[last - 1].bind = 1;
+ bind_all = 0;
- 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
- }
+ } else {
+ bind_all = 1;
+ }
- if (done) {
- break;
- }
+ a = 0;
- in_addr++;
- in_port[p].addrs.elts = in_addr;
- last--;
+ while (a < last) {
- a = 0;
+ if (!bind_all && !in_addr[a].bind) {
+ a++;
+ continue;
}
- }
-#if 0
- {
- u_char address[20];
- ngx_uint_t p, a;
-
- in_port = in_ports.elts;
- for (p = 0; p < in_ports.nelts; p++) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
- "port: %d %p", in_port[p].port, &in_port[p]);
- in_addr = in_port[p].addrs.elts;
- for (a = 0; a < in_port[p].addrs.nelts; a++) {
- ngx_inet_ntop(AF_INET, &in_addr[a].addr, address, 20);
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0,
- "%s:%d %p",
- address, in_port[p].port, in_addr[a].core_srv_conf);
- name = in_addr[a].names.elts;
- for (n = 0; n < in_addr[a].names.nelts; n++) {
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, cf->log, 0,
- "%s:%d %V %p",
- address, in_port[p].port, &name[n].name,
- name[n].core_srv_conf);
- }
+ ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
+ in_port->port);
+ if (ls == NULL) {
+ return NGX_ERROR;
}
- }
- }
-#endif
- return NGX_CONF_OK;
-}
+ ls->addr_ntop = 1;
+ ls->handler = ngx_http_init_connection;
-/*
- * add the server address, the server names and the server core module
- * configurations to the port (in_port)
- */
+ cscf = in_addr[a].core_srv_conf;
+ ls->pool_size = cscf->connection_pool_size;
+ ls->post_accept_timeout = cscf->client_header_timeout;
-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;
+ clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
- 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)
+ ls->log = *clcf->err_log;
+ ls->log.data = &ls->addr_text;
+ ls->log.handler = ngx_accept_log_error;
+
+#if (NGX_WIN32)
{
- return NGX_ERROR;
+ ngx_iocp_conf_t *iocpcf;
+
+ 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
- in_addr = ngx_array_push(&in_port->addrs);
- if (in_addr == NULL) {
- return NGX_ERROR;
- }
+ ls->backlog = in_addr[a].listen_conf->backlog;
+ ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
+ ls->sndbuf = in_addr[a].listen_conf->sndbuf;
- 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;
-#if (NGX_PCRE)
- in_addr->nregex = 0;
- in_addr->regex = NULL;
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ ls->accept_filter = in_addr[a].listen_conf->accept_filter;
#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);
- }
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
#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)
- {
+ hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
+ if (hip == NULL) {
return NGX_ERROR;
}
- }
- server_names = cscf->server_names.elts;
-
- for (i = 0; i < cscf->server_names.nelts; i++) {
+ hip->port = in_port->port;
- 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) {
+ hip->port_text.data = ngx_palloc(cf->pool, 7);
+ if (hip->port_text.data == NULL) {
return NGX_ERROR;
}
- *name = server_names[i];
- }
+ ls->servers = hip;
- return NGX_OK;
-}
+ hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", hip->port)
+ - hip->port_text.data;
+ in_addr = in_port->addrs.elts;
-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;
+ if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
+ hip->naddrs = 1;
+ done = 0;
- 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;
- }
+ } else if (in_port->addrs.nelts > 1
+ && in_addr[last - 1].addr == INADDR_ANY)
+ {
+ hip->naddrs = last;
+ done = 1;
- if (clcfp[i]->locations == NULL) {
- continue;
+ } else {
+ hip->naddrs = 1;
+ done = 0;
}
- rv = ngx_http_merge_locations(cf, clcfp[i]->locations,
- clcfp[i]->loc_conf, module, ctx_index);
- if (rv != NGX_CONF_OK) {
- return rv;
+ hip->addrs = ngx_pcalloc(cf->pool,
+ hip->naddrs * sizeof(ngx_http_in_addr_t));
+ if (hip->addrs == NULL) {
+ return NGX_ERROR;
}
- }
- return NGX_CONF_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;
+ 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;
+ }
-static ngx_int_t
-ngx_http_cmp_conf_in_addrs(const void *one, const void *two)
-{
- ngx_http_conf_in_addr_t *first, *second;
+ vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
+ if (vn == NULL) {
+ return NGX_ERROR;
+ }
+ hip->addrs[i].virtual_names = vn;
- first = (ngx_http_conf_in_addr_t *) one;
- second = (ngx_http_conf_in_addr_t *) two;
+ 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
+ }
- if (first->addr == INADDR_ANY) {
- /* the INADDR_ANY must be the last resort, shift it to the end */
- return 1;
- }
+ if (done) {
+ return NGX_OK;
+ }
- if (first->bind && !second->bind) {
- /* shift explicit bind()ed addresses to the start */
- return -1;
- }
+ in_addr++;
+ in_port->addrs.elts = in_addr;
+ last--;
- if (!first->bind && second->bind) {
- /* shift explicit bind()ed addresses to the start */
- return 1;
+ a = 0;
}
- /* 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);
+ return NGX_OK;
}