summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES34
-rw-r--r--CHANGES.ru32
-rw-r--r--auto/lib/pcre/makefile.bcc2
-rw-r--r--auto/lib/zlib/makefile.bcc2
-rw-r--r--auto/make13
-rw-r--r--auto/os/conf2
-rw-r--r--auto/sources1
-rw-r--r--conf/nginx.conf2
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.c8
-rw-r--r--src/core/ngx_conf_file.h1
-rw-r--r--src/core/ngx_connection.c3
-rw-r--r--src/core/ngx_cycle.c14
-rw-r--r--src/core/ngx_hash.c272
-rw-r--r--src/core/ngx_hash.h27
-rw-r--r--src/http/modules/ngx_http_map_module.c61
-rw-r--r--src/http/modules/ngx_http_proxy_module.c2
-rw-r--r--src/http/modules/ngx_http_referer_module.c243
-rw-r--r--src/http/ngx_http.c548
-rw-r--r--src/http/ngx_http.h1
-rw-r--r--src/http/ngx_http_config.c214
-rw-r--r--src/http/ngx_http_config.h21
-rw-r--r--src/http/ngx_http_core_module.c107
-rw-r--r--src/http/ngx_http_core_module.h54
-rw-r--r--src/http/ngx_http_request.c116
-rw-r--r--src/http/ngx_http_request.h14
-rw-r--r--src/http/ngx_http_upstream.c2
27 files changed, 1004 insertions, 794 deletions
diff --git a/CHANGES b/CHANGES
index 0172d25c3..0f3764957 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,33 @@
+Changes with nginx 0.3.18 26 Dec 2005
+
+ *) Feature: the "server_names" directive supports the ".domain.tld"
+ names.
+
+ *) Feature: the "server_names" directive uses the hash for the
+ "*.domain.tld" names and more effective hash for usual names.
+
+ *) Change: the "server_names_hash_max_size" and
+ "server_names_hash_bucket_size" directives.
+
+ *) Change: the "server_names_hash" and "server_names_hash_threshold"
+ directives were canceled.
+
+ *) Feature: the "valid_referers" directive uses the hash site names.
+
+ *) Change: now the "valid_referers" directive checks the site names
+ only without the URI part.
+
+ *) Bugfix: some ".domain.tld" names incorrectly processed by the
+ ngx_http_map_module.
+
+ *) Bugfix: segmentation fault was occurred if configuration file did
+ not exist; bug appeared in 0.3.12.
+
+ *) Bugfix: on 64-bit platforms segmentation fault may occurred on
+ start; bug appeared in 0.3.16.
+
+
Changes with nginx 0.3.17 18 Dec 2005
*) Change: now on Linux configure checks the presence of epoll and
@@ -7,7 +36,8 @@ Changes with nginx 0.3.17 18 Dec 2005
*) Feature: the "map" directive supports domain names in the
".domain.tld" form.
- *) Bugfix: the timeouts were not used in SSL handshake.
+ *) Bugfix: the timeouts were not used in SSL handshake; bug appeared in
+ 0.2.4.
*) Bugfix: in the HTTP protocol in the "proxy_pass" directive.
@@ -597,7 +627,7 @@ Changes with nginx 0.1.36 15 Jun 2005
"Connection", "Content-Length", or "Authorization" lines, then nginx
now returns the 400 error.
- *) Change: The "post_accept_timeout" directive was canceled.
+ *) Change: the "post_accept_timeout" directive was canceled.
*) Feature: the "default", "af=", "bl=", "deferred", and "bind"
parameters of the "listen" directive.
diff --git a/CHANGES.ru b/CHANGES.ru
index 884cfdea6..29b41a0a5 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,33 @@
+Изменения в nginx 0.3.18 26.12.2005
+
+ *) Добавление: директива server_names поддерживает имена вида
+ ".domain.tld".
+
+ *) Добавление: директива server_names использует хэш для имён вида
+ "*.domain.tld" и более эффективный хэш для обычных имён.
+
+ *) Изменение: директивы server_names_hash_max_size и
+ server_names_hash_bucket_size.
+
+ *) Изменение: директивы server_names_hash и server_names_hash_threshold
+ упразднены.
+
+ *) Добавление: директива valid_referers использует хэш для имён сайтов.
+
+ *) Изменение: теперь директива valid_referers проверяет только имена
+ сайтов без учёта URI.
+
+ *) Исправление: некоторые имена вида ".domain.tld" неверно
+ обрабатывались модулем ngx_http_map_module.
+
+ *) Исправление: если конфигурационного файла не было, то происходил
+ segmentation fault; ошибка появилась в 0.3.12.
+
+ *) Исправление: на 64-битных платформах при старте мог произойти
+ segmentation fault; ошибка появилась в 0.3.16.
+
+
Изменения в nginx 0.3.17 18.12.2005
*) Изменение: на Linux configure теперь проверяет наличие epoll и
@@ -7,7 +36,8 @@
*) Добавление: директива map поддерживает доменные имена в формате
".domain.tld".
- *) Исправление: во время SSL handshake не иcпользовались таймауты.
+ *) Исправление: во время SSL handshake не иcпользовались таймауты;
+ ошибка появилась в 0.2.4.
*) Исправление: в использовании протокола HTTPS в директиве proxy_pass.
diff --git a/auto/lib/pcre/makefile.bcc b/auto/lib/pcre/makefile.bcc
index a2dc5fbfc..9fd821d64 100644
--- a/auto/lib/pcre/makefile.bcc
+++ b/auto/lib/pcre/makefile.bcc
@@ -2,7 +2,7 @@
# Copyright (C) Igor Sysoev
-CFLAGS = -q -O2 -tWM $(CPU_OPT)
+CFLAGS = -q -O2 -tWM -w-8004 $(CPU_OPT)
PCREFLAGS = -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
diff --git a/auto/lib/zlib/makefile.bcc b/auto/lib/zlib/makefile.bcc
index 2c764242c..2e7b71991 100644
--- a/auto/lib/zlib/makefile.bcc
+++ b/auto/lib/zlib/makefile.bcc
@@ -2,7 +2,7 @@
# Copyright (C) Igor Sysoev
-CFLAGS = -q -O2 -tWM $(CPU_OPT)
+CFLAGS = -q -O2 -tWM -w-8004 -w-8012 $(CPU_OPT)
zlib.lib:
bcc32 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c \
diff --git a/auto/make b/auto/make
index f7eca87b3..e5c5efb92 100644
--- a/auto/make
+++ b/auto/make
@@ -320,6 +320,19 @@ END
fi
+# the addons config.make
+
+if test -n "$NGX_ADDONS"; then
+
+ for ngx_addon_dir in $NGX_ADDONS
+ do
+ if test -f $ngx_addon_dir/config.make; then
+ . $ngx_addon_dir/config.make
+ fi
+ done
+fi
+
+
# Win32 resource file
if test -n "$NGX_RES"; then
diff --git a/auto/os/conf b/auto/os/conf
index 0ddbacbee..16a3718c9 100644
--- a/auto/os/conf
+++ b/auto/os/conf
@@ -64,7 +64,7 @@ case "$NGX_MACHINE" in
NGX_MACH_CACHE_LINE=32
;;
- amd64)
+ amd64 | x86_64)
have=NGX_HAVE_NONALIGNED . auto/have
NGX_MACH_CACHE_LINE=64
;;
diff --git a/auto/sources b/auto/sources
index 5eacc1ae2..b59808313 100644
--- a/auto/sources
+++ b/auto/sources
@@ -266,7 +266,6 @@ HTTP_DEPS="src/http/ngx_http.h \
HTTP_SRCS="src/http/ngx_http.c \
src/http/ngx_http_core_module.c \
- src/http/ngx_http_config.c \
src/http/ngx_http_special_response.c \
src/http/ngx_http_request.c \
src/http/ngx_http_parse.c \
diff --git a/conf/nginx.conf b/conf/nginx.conf
index 4e3708b1e..7b967d681 100644
--- a/conf/nginx.conf
+++ b/conf/nginx.conf
@@ -18,7 +18,7 @@ http {
include conf/mime.types;
default_type application/octet-stream;
- #log_format main '$remote_addr - $remote_user [$time_gmt] $status '
+ #log_format main '$remote_addr - $remote_user [$time_local] $status '
# '"$request" $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "http_x_forwarded_for"';
diff --git a/src/core/nginx.h b/src/core/nginx.h
index c6c562f17..511a7c9fb 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.17"
+#define NGINX_VER "nginx/0.3.18"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 377cad5bc..589eb0e00 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -78,7 +78,8 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
if (fd == NGX_INVALID_FILE) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
- ngx_open_file_n " \"%s\" failed", filename->data);
+ ngx_open_file_n " \"%s\" failed",
+ filename->data);
return NGX_CONF_ERROR;
}
@@ -811,6 +812,11 @@ ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
*buf = '\0';
}
+ if (cf->conf_file == NULL) {
+ ngx_log_error(level, cf->log, 0, "%s", errstr);
+ return;
+ }
+
ngx_log_error(level, cf->log, 0, "%s in %s:%ui",
errstr, cf->conf_file->file.name.data, cf->conf_file->line);
}
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index e1859f852..62f365552 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -167,6 +167,7 @@ struct ngx_conf_s {
ngx_cycle_t *cycle;
ngx_pool_t *pool;
+ ngx_pool_t *temp_pool;
ngx_conf_file_t *conf_file;
ngx_log_t *log;
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 0820fede8..93b43c477 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -295,6 +295,9 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
}
}
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+ "bind() %V #%d ", &ls[i].addr_text, s);
+
if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
err = ngx_socket_errno;
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index da4303668..e13bcd8da 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -162,6 +162,12 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
return NULL;
}
+ conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
+ if (conf.temp_pool == NULL) {
+ ngx_destroy_pool(pool);
+ return NULL;
+ }
+
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
@@ -174,6 +180,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
#endif
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
+ ngx_destroy_pool(conf.temp_pool);
ngx_destroy_pool(pool);
return NULL;
}
@@ -194,8 +201,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
if (module->init_conf) {
if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
- == NGX_CONF_ERROR)
+ == NGX_CONF_ERROR)
{
+ ngx_destroy_pool(conf.temp_pool);
ngx_destroy_pool(pool);
return NULL;
}
@@ -421,6 +429,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
if (ngx_test_config) {
+ ngx_destroy_pool(conf.temp_pool);
ngx_destroy_pool(pool);
return NULL;
}
@@ -438,6 +447,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
}
+ ngx_destroy_pool(conf.temp_pool);
ngx_destroy_pool(pool);
return NULL;
}
@@ -521,6 +531,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
}
+ ngx_destroy_pool(conf.temp_pool);
+
if (old_cycle->connections == NULL) {
/* an old cycle is an init cycle */
ngx_destroy_pool(old_cycle->pool);
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
index dab19358a..f43d67533 100644
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -158,7 +158,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
}
}
- test = ngx_alloc(hinit->max_size * sizeof(ngx_uint_t), hinit->pool->log);
+ test = ngx_alloc(hinit->max_size * sizeof(size_t), hinit->pool->log);
if (test == NULL) {
return NGX_ERROR;
}
@@ -170,7 +170,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
for (size = start; size < hinit->max_size; size++) {
- ngx_memzero(test, size * sizeof(ngx_uint_t));
+ ngx_memzero(test, size * sizeof(size_t));
for (n = 0; n < nelts; n++) {
if (names[n].key.data == NULL) {
@@ -347,7 +347,7 @@ ngx_int_t
ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
ngx_uint_t nelts)
{
- size_t len;
+ size_t len, dot_len;
ngx_uint_t i, n, dot;
ngx_array_t curr_names, next_names;
ngx_hash_key_t *name, *next_name;
@@ -396,9 +396,11 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
#if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
- "wc1: \"%V\"", &name->key);
+ "wc1: \"%V\" %ui", &name->key, dot);
#endif
+ dot_len = len + 1;
+
if (dot) {
len++;
}
@@ -427,13 +429,20 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
break;
}
+ if (!dot
+ && names[i].key.len > len
+ && names[i].key.data[len] != '.')
+ {
+ break;
+ }
+
next_name = ngx_array_push(&next_names);
if (next_name == NULL) {
return NGX_ERROR;
}
- next_name->key.len = names[i].key.len - len;
- next_name->key.data = names[i].key.data + len;
+ next_name->key.len = names[i].key.len - dot_len;
+ next_name->key.data = names[i].key.data + dot_len;
next_name->key_hash= 0;
next_name->value = names[i].value;
@@ -444,6 +453,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
}
if (next_names.nelts) {
+
h = *hinit;
h.hash = NULL;
@@ -459,8 +469,8 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
if (names[n].key.len == len) {
wdc->value = names[n].value;
#if 0
- ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
- "wdc: \"%V\"", wdc->value);
+ ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
+ "wdc: \"%V\"", wdc->value);
#endif
}
@@ -681,3 +691,249 @@ ngx_hash0_init(ngx_hash0_t *hash, ngx_pool_t *pool, void *names,
return NGX_OK;
}
+
+
+ngx_int_t
+ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
+{
+ ngx_uint_t asize;
+
+ if (type == NGX_HASH_SMALL) {
+ asize = 4;
+ ha->hsize = 107;
+
+ } else {
+ asize = NGX_HASH_LARGE_ASIZE;
+ ha->hsize = NGX_HASH_LARGE_HSIZE;
+ }
+
+ if (ngx_array_init(&ha->keys, ha->temp_pool, asize, sizeof(ngx_hash_key_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ if (ngx_array_init(&ha->dns_wildcards, ha->temp_pool, asize,
+ sizeof(ngx_hash_key_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ ha->keys_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize);
+ if (ha->keys_hash == NULL) {
+ return NGX_ERROR;
+ }
+
+ ha->dns_wildcards_hash = ngx_pcalloc(ha->temp_pool,
+ sizeof(ngx_array_t) * ha->hsize);
+ if (ha->dns_wildcards_hash == NULL) {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,
+ ngx_uint_t flags)
+{
+ size_t len;
+ ngx_str_t *name;
+ ngx_uint_t i, k, n, skip;
+ ngx_hash_key_t *hk;
+ u_char buf[2048];
+
+ if (!(flags & NGX_HASH_WILDCARD_KEY)) {
+
+ /* exact hash */
+
+ k = 0;
+
+ for (i = 0; i < key->len; i++) {
+ key->data[i] = ngx_tolower(key->data[i]);
+ k = ngx_hash(k, key->data[i]);
+ }
+
+ k %= ha->hsize;
+
+ /* check conflicts in exact hash */
+
+ name = ha->keys_hash[k].elts;
+
+ if (name) {
+ for (i = 0; i < ha->keys_hash[k].nelts; i++) {
+ if (key->len != name[i].len) {
+ continue;
+ }
+
+ if (ngx_strncmp(key->data, name[i].data, key->len) == 0) {
+ return NGX_BUSY;
+ }
+ }
+
+ } else {
+ if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
+ sizeof(ngx_str_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ name = ngx_array_push(&ha->keys_hash[k]);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ *name = *key;
+
+ hk = ngx_array_push(&ha->keys);
+ if (hk == NULL) {
+ return NGX_ERROR;
+ }
+
+ hk->key = *key;
+ hk->key_hash = ngx_hash_key(key->data, key->len);
+ hk->value = value;
+
+ } else {
+
+ /* wildcard hash */
+
+ skip = (key->data[0] == '*') ? 2 : 1;
+ k = 0;
+
+ for (i = skip; i < key->len; i++) {
+ key->data[i] = ngx_tolower(key->data[i]);
+ k = ngx_hash(k, key->data[i]);
+ }
+
+ k %= ha->hsize;
+
+ if (skip == 1) {
+
+ /* check conflicts in exact hash for ".example.com" */
+
+ name = ha->keys_hash[k].elts;
+
+ if (name) {
+ len = key->len - skip;
+
+ for (i = 0; i < ha->keys_hash[k].nelts; i++) {
+ if (len != name[i].len) {
+ continue;
+ }
+
+ if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
+ return NGX_BUSY;
+ }
+ }
+
+ } else {
+ if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
+ sizeof(ngx_str_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ name = ngx_array_push(&ha->keys_hash[k]);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ name->len = key->len - 1;
+ name->data = ngx_palloc(ha->temp_pool, name->len);
+ if (name->data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(name->data, &key->data[1], name->len);
+ }
+
+
+ /*
+ * convert "*.example.com" to "com.example.\0"
+ * and ".example.com" to "com.example\0"
+ */
+
+ len = 0;
+ n = 0;
+
+ for (i = key->len - 1; i; i--) {
+ if (key->data[i] == '.') {
+ ngx_memcpy(&buf[n], &key->data[i + 1], len);
+ n += len;
+ buf[n++] = '.';
+ len = 0;
+ continue;
+ }
+
+ len++;
+ }
+
+ if (len) {
+ ngx_memcpy(&buf[n], &key->data[1], len);
+ n += len;
+ }
+
+ buf[n] = '\0';
+
+
+ /* check conflicts in wildcard hash */
+
+ name = ha->dns_wildcards_hash[k].elts;
+
+ if (name) {
+ len = key->len - skip;
+
+ for (i = 0; i < ha->dns_wildcards_hash[k].nelts; i++) {
+ if (len != name[i].len) {
+ continue;
+ }
+
+ if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
+ return NGX_BUSY;
+ }
+ }
+
+ } else {
+ if (ngx_array_init(&ha->dns_wildcards_hash[k], ha->temp_pool, 4,
+ sizeof(ngx_str_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ name = ngx_array_push(&ha->dns_wildcards_hash[k]);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ name->len = key->len - skip;
+ name->data = ngx_palloc(ha->temp_pool, name->len);
+ if (name->data == NULL) {
+ return NGX_ERROR;
+ }
+ ngx_memcpy(name->data, key->data + skip, name->len);
+
+
+ ngx_memcpy(key->data, buf, key->len);
+ key->len--;
+
+ hk = ngx_array_push(&ha->dns_wildcards);
+ if (hk == NULL) {
+ return NGX_ERROR;
+ }
+
+ hk->key = *key;
+ hk->key_hash = 0;
+ hk->value = value;
+ }
+
+ return NGX_OK;
+}
diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h
index 7449d0571..855dde7c4 100644
--- a/src/core/ngx_hash.h
+++ b/src/core/ngx_hash.h
@@ -54,6 +54,29 @@ typedef struct {
} ngx_hash_init_t;
+#define NGX_HASH_SMALL 1
+#define NGX_HASH_LARGE 2
+
+#define NGX_HASH_LARGE_ASIZE 16384
+#define NGX_HASH_LARGE_HSIZE 10007
+
+#define NGX_HASH_WILDCARD_KEY 1
+
+
+typedef struct {
+ ngx_uint_t hsize;
+
+ ngx_pool_t *pool;
+ ngx_pool_t *temp_pool;
+
+ ngx_array_t keys;
+ ngx_array_t *keys_hash;
+
+ ngx_array_t dns_wildcards;
+ ngx_array_t *dns_wildcards_hash;
+} ngx_hash_keys_arrays_t;
+
+
typedef struct {
void **buckets;
ngx_uint_t hash_size;
@@ -86,6 +109,10 @@ ngx_int_t ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
ngx_uint_t ngx_hash_key(u_char *data, size_t len);
ngx_uint_t ngx_hash_key_lc(u_char *data, size_t len);
+ngx_int_t ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type);
+ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key,
+ void *value, ngx_uint_t flags);
+
ngx_int_t ngx_hash0_init(ngx_hash0_t *hash, ngx_pool_t *pool, void *names,
ngx_uint_t nelts);
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index 04e2e0ac7..2cfb443e2 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -16,7 +16,7 @@ typedef struct {
typedef struct {
- ngx_http_hash_conf_t hash;
+ ngx_hash_keys_arrays_t keys;
ngx_array_t *values_hash;
@@ -245,44 +245,20 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (ngx_array_init(&ctx.hash.keys, pool, 16384, sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
- if (ngx_array_init(&ctx.hash.dns_wildcards, pool, 16384,
- sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
+ ctx.keys.pool = cf->pool;
+ ctx.keys.temp_pool = pool;
- ctx.hash.keys_hash = ngx_pcalloc(pool,
- sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
- if (ctx.hash.keys_hash == NULL) {
+ if (ngx_hash_keys_array_init(&ctx.keys, NGX_HASH_LARGE) != NGX_OK) {
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
- ctx.hash.dns_hash = ngx_pcalloc(pool,
- sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
- if (ctx.hash.dns_hash == NULL) {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
- ctx.values_hash = ngx_pcalloc(pool,
- sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
+ ctx.values_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * ctx.keys.hsize);
if (ctx.values_hash == NULL) {
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
- ctx.hash.pool = cf->pool;
- ctx.hash.temp_pool = pool;
ctx.default_value = NULL;
ctx.hostnames = 0;
@@ -298,7 +274,6 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (rv != NGX_CONF_OK) {
ngx_destroy_pool(pool);
-
return rv;
}
@@ -308,13 +283,14 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
hash.name = "map_hash";
hash.pool = cf->pool;
- if (ctx.hash.keys.nelts) {
+ if (ctx.keys.keys.nelts) {
hash.hash = &map->hash;
hash.temp_pool = NULL;
- if (ngx_hash_init(&hash, ctx.hash.keys.elts, ctx.hash.keys.nelts)
+ if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts)
!= NGX_OK)
{
+ ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
}
@@ -322,19 +298,20 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
map->default_value = ctx.default_value ? ctx.default_value:
&ngx_http_variable_null_value;
- if (ctx.hash.dns_wildcards.nelts) {
+ if (ctx.keys.dns_wildcards.nelts) {
- ngx_qsort(ctx.hash.dns_wildcards.elts,
- (size_t) ctx.hash.dns_wildcards.nelts,
+ ngx_qsort(ctx.keys.dns_wildcards.elts,
+ (size_t) ctx.keys.dns_wildcards.nelts,
sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
hash.hash = NULL;
hash.temp_pool = pool;
- if (ngx_hash_wildcard_init(&hash, ctx.hash.dns_wildcards.elts,
- ctx.hash.dns_wildcards.nelts)
+ if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wildcards.elts,
+ ctx.keys.dns_wildcards.nelts)
!= NGX_OK)
{
+ ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
@@ -408,7 +385,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
key = ngx_hash(key, value[1].data[i]);
}
- key %= NGX_HTTP_CONFIG_HASH;
+ key %= ctx->keys.hsize;
vp = ctx->values_hash[key].elts;
@@ -433,13 +410,13 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
}
}
- var = ngx_palloc(ctx->hash.pool, sizeof(ngx_http_variable_value_t));
+ var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t));
if (var == NULL) {
return NGX_CONF_ERROR;
}
var->len = value[1].len;
- var->data = ngx_pstrdup(ctx->hash.pool, &value[1]);
+ var->data = ngx_pstrdup(ctx->keys.pool, &value[1]);
if (var->data == NULL) {
return NGX_CONF_ERROR;
}
@@ -492,10 +469,10 @@ found:
return NGX_CONF_ERROR;
}
- flags = NGX_HTTP_WILDCARD_HASH;
+ flags = NGX_HASH_WILDCARD_KEY;
}
- rc = ngx_http_config_add_hash(&ctx->hash, &value[0], var, flags);
+ rc = ngx_hash_add_key(&ctx->keys, &value[0], var, flags);
if (rc == NGX_OK) {
return NGX_CONF_OK;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index c2be2c44e..f63e28872 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1925,8 +1925,8 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_proxy_loc_conf_t *plcf = conf;
size_t add;
+ u_short port;
ngx_str_t *value, *url;
- ngx_uint_t port;
ngx_inet_upstream_t inet_upstream;
ngx_http_core_loc_conf_t *clcf;
#if (NGX_HTTP_SSL)
diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c
index cd8be7879..622f25710 100644
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -10,15 +10,13 @@
typedef struct {
- ngx_str_t name;
- ngx_uint_t wildcard;
-} ngx_http_referer_t;
+ ngx_hash_t hash;
+ ngx_hash_wildcard_t *dns_wildcards;
-typedef struct {
- ngx_array_t *referers; /* ngx_http_referer_t */
+ ngx_flag_t no_referer;
+ ngx_flag_t blocked_referer;
- ngx_flag_t no_referer;
- ngx_flag_t blocked_referer;
+ ngx_hash_keys_arrays_t *keys;
} ngx_http_referer_conf_t;
@@ -27,6 +25,10 @@ static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
+ ngx_str_t *value);
+static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one,
+ const void *two);
static ngx_command_t ngx_http_referer_commands[] = {
@@ -77,21 +79,22 @@ static ngx_int_t
ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- u_char *ref;
- size_t len;
- ngx_uint_t i, n;
- ngx_http_referer_t *refs;
- ngx_http_referer_conf_t *cf;
+ u_char *p, *ref;
+ size_t len;
+ ngx_http_referer_conf_t *rlcf;
- cf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
+ rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
- if (cf->referers == NULL) {
+ if (rlcf->hash.buckets == NULL
+ && rlcf->dns_wildcards == NULL
+ && rlcf->dns_wildcards->hash.buckets == NULL)
+ {
*v = ngx_http_variable_null_value;
return NGX_OK;
}
if (r->headers_in.referer == NULL) {
- if (cf->no_referer) {
+ if (rlcf->no_referer) {
*v = ngx_http_variable_null_value;
return NGX_OK;
@@ -107,7 +110,7 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
if (len < sizeof("http://i.ru") - 1
|| (ngx_strncasecmp(ref, "http://", 7) != 0))
{
- if (cf->blocked_referer) {
+ if (rlcf->blocked_referer) {
*v = ngx_http_variable_null_value;
return NGX_OK;
@@ -120,37 +123,25 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
len -= 7;
ref += 7;
- refs = cf->referers->elts;
- for (i = 0; i < cf->referers->nelts; i++ ){
-
- if (refs[i].name.len > len) {
- continue;
+ for (p = ref; p < ref + len; p++) {
+ if (*p == '/' || *p == ':') {
+ break;
}
+ }
- if (refs[i].wildcard) {
- for (n = 0; n < len; n++) {
- if (ref[n] == '/' || ref[n] == ':') {
- break;
- }
-
- if (ref[n] != '.') {
- continue;
- }
+ len = p - ref;
- if (ngx_strncmp(&ref[n], refs[i].name.data,
- refs[i].name.len) == 0)
- {
- *v = ngx_http_variable_null_value;
- return NGX_OK;
- }
- }
+ if (rlcf->hash.buckets) {
+ if (ngx_hash_find(&rlcf->hash, ngx_hash_key_lc(ref, len), ref, len)) {
+ *v = ngx_http_variable_null_value;
+ return NGX_OK;
+ }
+ }
- } else {
- if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0)
- {
- *v = ngx_http_variable_null_value;
- return NGX_OK;
- }
+ if (rlcf->dns_wildcards && rlcf->dns_wildcards->hash.buckets) {
+ if (ngx_hash_find_wildcard(rlcf->dns_wildcards, ref, len)) {
+ *v = ngx_http_variable_null_value;
+ return NGX_OK;
}
}
@@ -165,12 +156,11 @@ ngx_http_referer_create_conf(ngx_conf_t *cf)
{
ngx_http_referer_conf_t *conf;
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_referer_conf_t));
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_referer_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
- conf->referers = NULL;
conf->no_referer = NGX_CONF_UNSET;
conf->blocked_referer = NGX_CONF_UNSET;
@@ -184,10 +174,53 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_referer_conf_t *prev = parent;
ngx_http_referer_conf_t *conf = child;
- if (conf->referers == NULL) {
- conf->referers = prev->referers;
+ ngx_hash_init_t hash;
+
+ if (conf->keys == NULL) {
+ conf->hash = prev->hash;
+ conf->dns_wildcards = prev->dns_wildcards;
+
ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
+
+ return NGX_CONF_OK;
+ }
+
+ hash.key = ngx_hash_key_lc;
+ hash.max_size = 2048; /* TODO: referer_hash_max_size; */
+ hash.bucket_size = 64; /* TODO: referer_hash_bucket_size; */
+ hash.name = "referers_hash";
+ hash.pool = cf->pool;
+
+ if (conf->keys->keys.nelts) {
+ hash.hash = &conf->hash;
+ hash.temp_pool = NULL;
+
+ if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ if (conf->keys->dns_wildcards.nelts) {
+
+ ngx_qsort(conf->keys->dns_wildcards.elts,
+ (size_t) conf->keys->dns_wildcards.nelts,
+ sizeof(ngx_hash_key_t),
+ ngx_http_cmp_referer_wildcards);
+
+ hash.hash = NULL;
+ hash.temp_pool = cf->temp_pool;
+
+ if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wildcards.elts,
+ conf->keys->dns_wildcards.nelts)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->dns_wildcards = (ngx_hash_wildcard_t *) hash.hash;
}
if (conf->no_referer == NGX_CONF_UNSET) {
@@ -205,11 +238,11 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
static char *
ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_referer_conf_t *lcf = conf;
+ ngx_http_referer_conf_t *rlcf = conf;
- ngx_uint_t i, server_names;
+ u_char *p;
ngx_str_t *value, name;
- ngx_http_referer_t *ref;
+ ngx_uint_t i, n;
ngx_http_variable_t *var;
ngx_http_server_name_t *sn;
ngx_http_core_srv_conf_t *cscf;
@@ -225,19 +258,21 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
var->handler = ngx_http_referer_variable;
- cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
+ if (rlcf->keys == NULL) {
+ rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t));
+ if (rlcf->keys == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ rlcf->keys->pool = cf->pool;
+ rlcf->keys->temp_pool = cf->pool;
- if (lcf->referers == NULL) {
- lcf->referers = ngx_array_create(cf->pool,
- cf->args->nelts + cscf->server_names.nelts,
- sizeof(ngx_http_referer_t));
- if (lcf->referers == NULL) {
+ if (ngx_hash_keys_array_init(rlcf->keys, NGX_HASH_SMALL) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
value = cf->args->elts;
- server_names = 0;
for (i = 1; i < cf->args->nelts; i++) {
if (value[i].len == 0) {
@@ -247,64 +282,90 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
if (ngx_strcmp(value[i].data, "none") == 0) {
- lcf->no_referer = 1;
+ rlcf->no_referer = 1;
continue;
}
if (ngx_strcmp(value[i].data, "blocked") == 0) {
- lcf->blocked_referer = 1;
+ rlcf->blocked_referer = 1;
continue;
}
if (ngx_strcmp(value[i].data, "server_names") == 0) {
- server_names = 1;
- continue;
- }
- ref = ngx_array_push(lcf->referers);
- if (ref == NULL) {
- return NGX_CONF_ERROR;
- }
+ cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
+
+ sn = cscf->server_names.elts;
+ for (n = 0; n < cscf->server_names.nelts; n++) {
+ if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
- if (value[i].data[0] != '*') {
- ref->name = value[i];
- ref->wildcard = 0;
continue;
}
+ p = (u_char *) ngx_strstr(value[i].data, "/");
- if (value[i].data[1] != '.') {
+ if (p) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid wildcard referer \"%V\"", &value[i]);
+ "URI part \"%s\" is deprecated, ignored", p);
+
+ value[i].len = p - value[i].data;
+ }
+
+ if (ngx_http_add_referer(cf, rlcf->keys, &value[i]) != NGX_OK) {
return NGX_CONF_ERROR;
}
+ }
- ref->name.len = value[i].len - 1;
- ref->name.data = value[i].data + 1;
- ref->wildcard = 1;
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
+ ngx_str_t *value)
+{
+ u_char ch;
+ ngx_int_t rc;
+ ngx_uint_t flags;
+
+ ch = value->data[0];
+
+ if ((ch == '*' && (value->len < 3 || value->data[1] != '.'))
+ || (ch == '.' && value->len < 2))
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid DNS wildcard \"%V\"", value);
+
+ return NGX_CONF_ERROR;
}
- if (!server_names) {
+ flags = (ch == '*' || ch == '.') ? NGX_HASH_WILDCARD_KEY : 0;
+
+ rc = ngx_hash_add_key(keys, value, (void *) 4, flags);
+
+ if (rc == NGX_OK) {
return NGX_CONF_OK;
}
- sn = cscf->server_names.elts;
- for (i = 0; i < cscf->server_names.nelts; i++) {
- ref = ngx_array_push(lcf->referers);
- if (ref == NULL) {
- return NGX_CONF_ERROR;
- }
+ if (rc == NGX_BUSY) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "conflicting parameter \"%V\"", value);
+ }
- ref->name.len = sn[i].name.len + 1;
- ref->name.data = ngx_palloc(cf->pool, ref->name.len);
- if (ref->name.data == NULL) {
- return NGX_CONF_ERROR;
- }
+ return NGX_CONF_ERROR;
+}
- ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len);
- ref->name.data[sn[i].name.len] = '/';
- ref->wildcard = sn[i].wildcard;
- }
- return NGX_CONF_OK;
+static int ngx_libc_cdecl
+ngx_http_cmp_referer_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);
}
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 449a4e9bd..d1d64b8a5 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -14,18 +14,22 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static int ngx_libc_cdecl ngx_cmp_server_names(const void *one,
const void *two);
static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
- ngx_http_in_port_t *in_port, ngx_http_listen_t *lscf,
+ ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf,
ngx_http_core_srv_conf_t *cscf);
static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
- ngx_http_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf);
+ ngx_http_conf_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf);
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 int ngx_libc_cdecl 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;
+ngx_uint_t ngx_http_max_module;
-ngx_uint_t ngx_http_total_requests;
-uint64_t ngx_http_total_sent;
+ngx_uint_t ngx_http_total_requests;
+uint64_t ngx_http_total_sent;
ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
@@ -72,19 +76,24 @@ static char *
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
- ngx_uint_t mi, m, s, l, p, a, n, key;
- ngx_uint_t port_found, addr_found;
- ngx_uint_t virtual_names, separate_binding;
+ u_char ch;
+ ngx_int_t rc;
+ ngx_uint_t mi, m, s, l, p, a, n, i;
+ ngx_uint_t last, bind_all, done;
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_handler_pt *h;
ngx_http_conf_ctx_t *ctx;
- ngx_http_in_port_t *in_port, *inport;
- ngx_http_in_addr_t *in_addr, *inaddr;
- ngx_http_server_name_t *s_name, *name;
+ 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_main_conf_t *cmcf;
@@ -414,7 +423,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
* to quickly find the server core module configuration at run-time
*/
- if (ngx_array_init(&in_ports, cf->pool, 2, sizeof(ngx_http_in_port_t))
+ if (ngx_array_init(&in_ports, cf->temp_pool, 2,
+ sizeof(ngx_http_conf_in_port_t))
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -430,137 +440,85 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
lscf = cscfp[s]->listen.elts;
for (l = 0; l < cscfp[s]->listen.nelts; l++) {
- port_found = 0;
-
/* AF_INET only */
in_port = in_ports.elts;
for (p = 0; p < in_ports.nelts; p++) {
- if (lscf[l].port == in_port[p].port) {
-
- /* the port is already in the port list */
+ if (lscf[l].port != in_port[p].port) {
+ continue;
+ }
- port_found = 1;
- addr_found = 0;
+ /* the port is already in the port list */
- in_addr = in_port[p].addrs.elts;
- for (a = 0; a < in_port[p].addrs.nelts; a++) {
+ 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 (lscf[l].addr != in_addr[a].addr) {
+ continue;
+ }
- /* the address is already in the address list */
+ /* the address is already in the address list */
- if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
- /*
- * check the duplicate "default" server
- * for this address:port
- */
+ /*
+ * check the duplicate "default" server
+ * for this address:port
+ */
- if (lscf[l].conf.default_server) {
+ if (lscf[l].conf.default_server) {
- if (in_addr[a].conf.default_server) {
- ngx_log_error(NGX_LOG_ERR, cf->log, 0,
+ if (in_addr[a].default_server) {
+ ngx_log_error(NGX_LOG_ERR, cf->log, 0,
"the duplicate default server in %V:%d",
&lscf[l].file_name, lscf[l].line);
- return NGX_CONF_ERROR;
- }
-
- in_addr[a].core_srv_conf = cscfp[s];
- in_addr[a].conf.default_server = 1;
- }
-
- addr_found = 1;
-
- break;
-
- } else if (in_addr[a].addr == INADDR_ANY) {
-
- /* the INADDR_ANY is always the last address */
-
- inaddr = ngx_array_push(&in_port[p].addrs);
- if (inaddr == NULL) {
- return NGX_CONF_ERROR;
- }
- in_addr = in_port[p].addrs.elts;
-
- /*
- * the INADDR_ANY must be the last resort
- * so we move it to the end of the address list
- * and put the new address in its place
- */
-
- ngx_memcpy(inaddr, &in_addr[a],
- sizeof(ngx_http_in_addr_t));
-
- in_addr[a].addr = lscf[l].addr;
- in_addr[a].names.elts = NULL;
- in_addr[a].hash = NULL;
- in_addr[a].wildcards.elts = NULL;
- in_addr[a].core_srv_conf = cscfp[s];
- in_addr[a].conf = lscf[l].conf;
-
- if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- addr_found = 1;
-
- break;
- }
- }
-
- if (!addr_found) {
-
- /*
- * add the address to the addresses list that
- * bound to this port
- */
-
- if (ngx_http_add_address(cf, &in_port[p], &lscf[l],
- cscfp[s]) != NGX_OK)
- {
return NGX_CONF_ERROR;
}
+
+ in_addr[a].core_srv_conf = cscfp[s];
+ in_addr[a].default_server = 1;
}
- }
- }
- if (!port_found) {
+ goto found;
+ }
- /* add the port to the in_port list */
+ /*
+ * add the address to the addresses list that
+ * bound to this port
+ */
- in_port = ngx_array_push(&in_ports);
- if (in_port == NULL) {
+ if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s])
+ != NGX_OK)
+ {
return NGX_CONF_ERROR;
}
- in_port->port = lscf[l].port;
- in_port->addrs.elts = NULL;
+ goto found;
+ }
- in_port->port_text.data = ngx_palloc(cf->pool, 7);
- if (in_port->port_text.data == NULL) {
- return NGX_CONF_ERROR;
- }
+ /* add the port to the in_port list */
- in_port->port_text.len = ngx_sprintf(in_port->port_text.data,
- ":%d", in_port->port)
- - in_port->port_text.data;
+ in_port = ngx_array_push(&in_ports);
+ if (in_port == NULL) {
+ return NGX_CONF_ERROR;
+ }
- if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s])
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ in_port->port = lscf[l].port;
+ in_port->addrs.elts = NULL;
+
+ if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
}
+
+ found:
+
+ continue;
}
}
@@ -572,7 +530,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
in_port = in_ports.elts;
for (p = 0; p < in_ports.nelts; p++) {
- separate_binding = 0;
+ ngx_qsort(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
@@ -582,33 +541,13 @@ 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 (in_addr[a].conf.bind) {
- separate_binding = 1;
- }
-
- virtual_names = 0;
-
name = in_addr[a].names.elts;
for (n = 0; n < in_addr[a].names.nelts; n++) {
if (in_addr[a].core_srv_conf != name[n].core_srv_conf
|| name[n].core_srv_conf->restrict_host_names
!= NGX_HTTP_RESTRICT_HOST_OFF)
{
- virtual_names = 1;
- break;
- }
- }
-
- if (!virtual_names) {
- name = in_addr[a].wildcards.elts;
- for (n = 0; n < in_addr[a].wildcards.nelts; n++) {
- if (in_addr[a].core_srv_conf != name[n].core_srv_conf
- || name[n].core_srv_conf->restrict_host_names
- != NGX_HTTP_RESTRICT_HOST_OFF)
- {
- virtual_names = 1;
- break;
- }
+ goto virtual_names;
}
}
@@ -618,65 +557,132 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
* then we do not need to check them at run-time at all
*/
- if (!virtual_names) {
- in_addr[a].names.nelts = 0;
- continue;
+ in_addr[a].names.nelts = 0;
+
+ continue;
+
+ virtual_names:
+
+ ha.temp_pool = ngx_create_pool(16384, cf->log);
+ if (ha.temp_pool == NULL) {
+ return NGX_CONF_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;
}
+ name = in_addr[a].names.elts;
+ for (s = 0; s < in_addr[a].names.nelts; s++) {
- ngx_qsort(in_addr[a].names.elts, in_addr[a].names.nelts,
- sizeof(ngx_http_server_name_t), ngx_cmp_server_names);
+ ch = name[s].name.data[0];
+ if (ch == '*' || ch == '.') {
+ continue;
+ }
- /* create a hash for many names */
+ rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
+ 0);
- if (in_addr[a].names.nelts > cmcf->server_names_hash_threshold) {
- in_addr[a].hash = ngx_palloc(cf->pool,
- cmcf->server_names_hash
- * sizeof(ngx_array_t));
- if (in_addr[a].hash == NULL) {
+ if (rc == NGX_ERROR) {
return NGX_CONF_ERROR;
}
- for (n = 0; n < cmcf->server_names_hash; n++) {
- if (ngx_array_init(&in_addr[a].hash[n], cf->pool, 4,
- sizeof(ngx_http_server_name_t)) != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ if (rc == NGX_BUSY) {
+ ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+ "conflicting server name \"%V\", ignored",
+ &name[s].name);
}
+ }
- name = in_addr[a].names.elts;
- for (s = 0; s < in_addr[a].names.nelts; s++) {
- ngx_http_server_names_hash_key(key, name[s].name.data,
- name[s].name.len,
- cmcf->server_names_hash);
+ for (s = 0; s < in_addr[a].names.nelts; s++) {
- s_name = ngx_array_push(&in_addr[a].hash[key]);
- if (s_name == NULL) {
- return NGX_CONF_ERROR;
- }
- name = in_addr[a].names.elts;
+ ch = name[s].name.data[0];
- *s_name = name[s];
+ if (ch != '*' && ch != '.') {
+ continue;
+ }
+
+ rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
+ NGX_HASH_WILDCARD_KEY);
+
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (rc == NGX_BUSY) {
+ ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+ "conflicting server name \"%V\", ignored",
+ &name[s].name);
}
}
+
+ hash.key = ngx_hash_key_lc;
+ hash.max_size = cmcf->server_names_hash_max_size;
+ hash.bucket_size = cmcf->server_names_hash_bucket_size;
+ hash.name = "server_names_hash";
+ hash.pool = cf->pool;
+
+ if (ha.keys.nelts) {
+ hash.hash = &in_addr[a].hash;
+ hash.temp_pool = NULL;
+
+ if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK)
+ {
+ ngx_destroy_pool(ha.temp_pool);
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ if (ha.dns_wildcards.nelts) {
+
+ ngx_qsort(ha.dns_wildcards.elts,
+ (size_t) ha.dns_wildcards.nelts,
+ sizeof(ngx_hash_key_t),
+ ngx_http_cmp_dns_wildcards);
+
+ hash.hash = NULL;
+ hash.temp_pool = ha.temp_pool;
+
+ if (ngx_hash_wildcard_init(&hash, ha.dns_wildcards.elts,
+ ha.dns_wildcards.nelts)
+ != NGX_OK)
+ {
+ ngx_destroy_pool(ha.temp_pool);
+ return NGX_CONF_ERROR;
+ }
+
+ in_addr[a].dns_wildcards = (ngx_hash_wildcard_t *) hash.hash;
+ }
+
+ ngx_destroy_pool(ha.temp_pool);
}
+ 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[a - 1].addr == INADDR_ANY && !separate_binding) {
- a--;
+ if (in_addr[last - 1].addr == INADDR_ANY) {
+ in_addr[last - 1].bind = 1;
+ bind_all = 0;
} else {
- a = 0;
+ bind_all = 1;
}
- in_addr = in_port[p].addrs.elts;
- while (a < in_port[p].addrs.nelts) {
+ 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);
@@ -705,68 +711,98 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
#endif
- ls->backlog = in_addr[a].conf.backlog;
- ls->rcvbuf = in_addr[a].conf.rcvbuf;
- ls->sndbuf = in_addr[a].conf.sndbuf;
+ 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].conf.accept_filter;
+ ls->accept_filter = in_addr[a].listen_conf->accept_filter;
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
- ls->deferred_accept = in_addr[a].conf.deferred_accept;
+ ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
#endif
ls->ctx = ctx;
- if (in_port[p].addrs.nelts > 1) {
-
- in_addr = in_port[p].addrs.elts;
- if (in_addr[in_port[p].addrs.nelts - 1].addr != INADDR_ANY) {
+ hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
+ if (hip == NULL) {
+ return NGX_CONF_ERROR;
+ }
- /*
- * if this port has not the "*:port" binding then create
- * the separate ngx_http_in_port_t for the all bindings
- */
+ hip->port = in_port[p].port;
- inport = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
- if (inport == NULL) {
- return NGX_CONF_ERROR;
- }
+ hip->port_text.data = ngx_palloc(cf->pool, 7);
+ if (hip->port_text.data == NULL) {
+ return NGX_CONF_ERROR;
+ }
- inport->port = in_port[p].port;
- inport->port_text = in_port[p].port_text;
+ ls->servers = hip;
- /* init list of the addresses ... */
+ hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d",
+ hip->port)
+ - hip->port_text.data;
- if (ngx_array_init(&inport->addrs, cf->pool, 1,
- sizeof(ngx_http_in_addr_t)) != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ in_addr = in_port[p].addrs.elts;
- /* ... and set up it with the first address */
+ if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
+ hip->naddrs = 1;
+ done = 0;
- inport->addrs.nelts = 1;
- inport->addrs.elts = in_port[p].addrs.elts;
+ } else if (in_port[p].addrs.nelts > 1
+ && in_addr[last - 1].addr == INADDR_ANY)
+ {
+ hip->naddrs = last;
+ done = 1;
- ls->servers = inport;
+ } else {
+ hip->naddrs = 1;
+ done = 0;
+ }
- /* prepare for the next cycle */
+#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
- in_port[p].addrs.elts = (char *) in_port[p].addrs.elts
- + in_port[p].addrs.size;
- in_port[p].addrs.nelts--;
+ hip->addrs = ngx_pcalloc(cf->pool,
+ hip->naddrs * sizeof(ngx_http_in_addr_t));
+ if (hip->addrs == NULL) {
+ return NGX_CONF_ERROR;
+ }
- in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
- a = 0;
+ 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].dns_wildcards == NULL
+ || in_addr[i].dns_wildcards->hash.buckets == NULL))
+ {
continue;
}
+
+ vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
+ if (vn == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ hip->addrs[i].virtual_names = vn;
+
+ vn->hash = in_addr[i].hash;
+ vn->dns_wildcards = in_addr[i].dns_wildcards;
}
- ls->servers = &in_port[p];
- a++;
+ if (done) {
+ break;
+ }
+
+ in_addr++;
+ in_port[p].addrs.elts = in_addr;
+ last--;
+
+ a = 0;
}
}
@@ -785,12 +821,12 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0,
"%s:%d %p",
address, in_port[p].port, in_addr[a].core_srv_conf);
- s_name = in_addr[a].names.elts;
+ 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, &s_name[n].name,
- s_name[n].core_srv_conf);
+ address, in_port[p].port, &name[n].name,
+ name[n].core_srv_conf);
}
}
}
@@ -801,30 +837,20 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
-static int ngx_libc_cdecl
-ngx_cmp_server_names(const void *one, const void *two)
-{
- ngx_http_server_name_t *first = (ngx_http_server_name_t *) one;
- ngx_http_server_name_t *second = (ngx_http_server_name_t *) two;
-
- return ngx_strcmp(first->name.data, second->name.data);
-}
-
-
/*
* 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_in_port_t *in_port,
+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_in_addr_t *in_addr;
+ ngx_http_conf_in_addr_t *in_addr;
if (in_port->addrs.elts == NULL) {
- if (ngx_array_init(&in_port->addrs, cf->pool, 4,
- sizeof(ngx_http_in_addr_t)) != NGX_OK)
+ if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
+ sizeof(ngx_http_conf_in_addr_t)) != NGX_OK)
{
return NGX_ERROR;
}
@@ -836,11 +862,14 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_in_port_t *in_port,
}
in_addr->addr = lscf->addr;
+ in_addr->hash.buckets = NULL;
+ in_addr->hash.size = 0;
+ in_addr->dns_wildcards = NULL;
in_addr->names.elts = NULL;
- in_addr->hash = NULL;
- in_addr->wildcards.elts = NULL;
in_addr->core_srv_conf = cscf;
- in_addr->conf = lscf->conf;
+ in_addr->default_server = lscf->conf.default_server;
+ in_addr->bind = lscf->conf.bind;
+ in_addr->listen_conf = &lscf->conf;
#if (NGX_DEBUG)
{
@@ -861,23 +890,14 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_in_port_t *in_port,
*/
static ngx_int_t
-ngx_http_add_names(ngx_conf_t *cf, ngx_http_in_addr_t *in_addr,
+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_array_t *array;
ngx_http_server_name_t *server_names, *name;
if (in_addr->names.elts == NULL) {
- if (ngx_array_init(&in_addr->names, cf->pool, 4,
- sizeof(ngx_http_server_name_t)) != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- if (in_addr->wildcards.elts == NULL) {
- if (ngx_array_init(&in_addr->wildcards, cf->pool, 1,
+ if (ngx_array_init(&in_addr->names, cf->temp_pool, 4,
sizeof(ngx_http_server_name_t)) != NGX_OK)
{
return NGX_ERROR;
@@ -895,17 +915,8 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_in_addr_t *in_addr,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
"name: %V", &server_names[i].name);
- /* TODO: duplicate names can be checked here */
-
-
- if (server_names[i].wildcard) {
- array = &in_addr->wildcards;
-
- } else {
- array = &in_addr->names;
- }
- name = ngx_array_push(array);
+ name = ngx_array_push(&in_addr->names);
if (name == NULL) {
return NGX_ERROR;
}
@@ -926,7 +937,7 @@ ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations,
ngx_uint_t i;
ngx_http_core_loc_conf_t **clcfp;
- clcfp = /* (ngx_http_core_loc_conf_t **) */ locations->elts;
+ clcfp = locations->elts;
for (i = 0; i < locations->nelts; i++) {
rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
@@ -944,3 +955,44 @@ ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations,
return NGX_CONF_OK;
}
+
+
+static int ngx_libc_cdecl
+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);
+}
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index ddcd1be44..b9e124d6a 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -16,7 +16,6 @@
typedef struct ngx_http_request_s ngx_http_request_t;
typedef struct ngx_http_upstream_s ngx_http_upstream_t;
typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t;
-typedef struct ngx_http_in_addr_s ngx_http_in_addr_t;
typedef ngx_int_t (*ngx_http_header_handler_pt)(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
diff --git a/src/http/ngx_http_config.c b/src/http/ngx_http_config.c
deleted file mode 100644
index 965625d64..000000000
--- a/src/http/ngx_http_config.c
+++ /dev/null
@@ -1,214 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-#include <ngx_http.h>
-
-
-ngx_int_t
-ngx_http_config_add_hash(ngx_http_hash_conf_t *h, ngx_str_t *key, void *value,
- ngx_uint_t flags)
-{
- size_t len;
- ngx_str_t *name;
- ngx_uint_t i, k, n, skip;
- ngx_hash_key_t *hk;
- u_char buf[2048];
-
- if (!(flags & NGX_HTTP_WILDCARD_HASH)) {
-
- /* exact hash */
-
- k = 0;
-
- for (i = 0; i < key->len; i++) {
- key->data[i] = ngx_tolower(key->data[i]);
- k = ngx_hash(k, key->data[i]);
- }
-
- k %= NGX_HTTP_CONFIG_HASH;
-
- /* check conflicts in exact hash */
-
- name = h->keys_hash[k].elts;
-
- if (name) {
- for (i = 0; i < h->keys_hash[k].nelts; i++) {
- if (key->len != name[i].len) {
- continue;
- }
-
- if (ngx_strncmp(key->data, name[i].data, key->len) == 0) {
- return NGX_BUSY;
- }
- }
-
- } else {
- if (ngx_array_init(&h->keys_hash[k], h->temp_pool, 4,
- sizeof(ngx_str_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- name = ngx_array_push(&h->keys_hash[k]);
- if (name == NULL) {
- return NGX_ERROR;
- }
-
- *name = *key;
-
- hk = ngx_array_push(&h->keys);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key = *key;
- hk->key_hash = ngx_hash_key(key->data, key->len);
- hk->value = value;
-
- } else {
-
- /* wildcard hash */
-
- skip = (key->data[0] == '*') ? 2 : 1;
- k = 0;
-
- for (i = skip; i < key->len; i++) {
- key->data[i] = ngx_tolower(key->data[i]);
- k = ngx_hash(k, key->data[i]);
- }
-
- k %= NGX_HTTP_CONFIG_HASH;
-
- if (skip == 1) {
-
- /* check conflicts in exact hash for ".example.com" */
-
- name = h->keys_hash[k].elts;
-
- if (name) {
- len = key->len - skip;
-
- for (i = 0; i < h->keys_hash[k].nelts; i++) {
- if (len != name[i].len) {
- continue;
- }
-
- if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
- return NGX_BUSY;
- }
- }
-
- } else {
- if (ngx_array_init(&h->keys_hash[k], h->temp_pool, 4,
- sizeof(ngx_str_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- name = ngx_array_push(&h->keys_hash[k]);
- if (name == NULL) {
- return NGX_ERROR;
- }
-
- name->len = key->len - 1;
- name->data = ngx_palloc(h->temp_pool, name->len);
- if (name->data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(name->data, &key->data[1], name->len);
- }
-
-
- /*
- * convert "*.example.com" to "com.example.\0"
- * and ".example.com" to "com.example\0"
- */
-
- len = 0;
- n = 0;
-
- for (i = key->len - 1; i; i--) {
- if (key->data[i] == '.') {
- ngx_memcpy(&buf[n], &key->data[i + 1], len);
- n += len;
- buf[n++] = '.';
- len = 0;
- continue;
- }
-
- len++;
- }
-
- if (len) {
- ngx_memcpy(&buf[n], &key->data[1], len);
- n += len;
- }
-
- buf[n] = '\0';
-
-
- /* check conflicts in wildcard hash */
-
- name = h->dns_hash[k].elts;
-
- if (name) {
- len = key->len - skip;
-
- for (i = 0; i < h->dns_hash[k].nelts; i++) {
- if (len != name[i].len) {
- continue;
- }
-
- if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
- return NGX_BUSY;
- }
- }
-
- } else {
- if (ngx_array_init(&h->dns_hash[k], h->temp_pool, 4,
- sizeof(ngx_str_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- name = ngx_array_push(&h->dns_hash[k]);
- if (name == NULL) {
- return NGX_ERROR;
- }
-
- name->len = key->len - skip;
- name->data = ngx_palloc(h->temp_pool, name->len);
- if (name->data == NULL) {
- return NGX_ERROR;
- }
- ngx_memcpy(name->data, key->data + skip, name->len);
-
-
- ngx_memcpy(key->data, buf, key->len);
- key->len--;
-
- hk = ngx_array_push(&h->dns_wildcards);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key = *key;
- hk->key_hash = 0;
- hk->value = value;
- }
-
- return NGX_OK;
-}
diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h
index 476808584..84816ae27 100644
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -72,25 +72,4 @@ typedef struct {
cycle->conf_ctx[ngx_http_module.index])->main_conf[module.ctx_index]
-#define NGX_HTTP_CONFIG_HASH 10007
-
-#define NGX_HTTP_WILDCARD_HASH 1
-
-typedef struct {
- ngx_pool_t *pool;
- ngx_pool_t *temp_pool;
-
- ngx_array_t keys;
- ngx_array_t *keys_hash;
-
- ngx_array_t dns_wildcards;
- ngx_array_t *dns_hash;
-} ngx_http_hash_conf_t;
-
-
-ngx_int_t ngx_http_config_add_hash(ngx_http_hash_conf_t *h, ngx_str_t *key,
- void *value, ngx_uint_t flags);
-
-
-
#endif /* _NGX_HTTP_CONFIG_H_INCLUDED_ */
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index e42023b1f..4fa910390 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -73,18 +73,18 @@ static ngx_conf_enum_t ngx_http_restrict_host_names[] = {
static ngx_command_t ngx_http_core_commands[] = {
- { ngx_string("server_names_hash"),
+ { ngx_string("server_names_hash_max_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_core_main_conf_t, server_names_hash),
+ offsetof(ngx_http_core_main_conf_t, server_names_hash_max_size),
NULL },
- { ngx_string("server_names_hash_threshold"),
+ { ngx_string("server_names_hash_bucket_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_core_main_conf_t, server_names_hash_threshold),
+ offsetof(ngx_http_core_main_conf_t, server_names_hash_bucket_size),
NULL },
{ ngx_string("server"),
@@ -1715,8 +1715,8 @@ ngx_http_core_create_main_conf(ngx_conf_t *cf)
return NGX_CONF_ERROR;
}
- cmcf->server_names_hash = NGX_CONF_UNSET_UINT;
- cmcf->server_names_hash_threshold = NGX_CONF_UNSET_UINT;
+ cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
+ cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
return cmcf;
}
@@ -1727,14 +1727,17 @@ ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_core_main_conf_t *cmcf = conf;
- if (cmcf->server_names_hash == NGX_CONF_UNSET_UINT) {
- cmcf->server_names_hash = 1009;
+ if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
+ cmcf->server_names_hash_max_size = 512;
}
- if (cmcf->server_names_hash_threshold == NGX_CONF_UNSET_UINT) {
- cmcf->server_names_hash_threshold = 50;
+ if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
+ cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
}
+ cmcf->server_names_hash_bucket_size =
+ ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
+
return NGX_CONF_OK;
}
@@ -1756,19 +1759,20 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
*/
if (ngx_array_init(&cscf->locations, cf->pool, 4, sizeof(void *))
- == NGX_ERROR)
+ == NGX_ERROR)
{
return NGX_CONF_ERROR;
}
if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t))
- == NGX_ERROR)
+ == NGX_ERROR)
{
return NGX_CONF_ERROR;
}
if (ngx_array_init(&cscf->server_names, cf->pool, 4,
- sizeof(ngx_http_server_name_t)) == NGX_ERROR)
+ sizeof(ngx_http_server_name_t))
+ == NGX_ERROR)
{
return NGX_CONF_ERROR;
}
@@ -1790,9 +1794,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_core_srv_conf_t *prev = parent;
ngx_http_core_srv_conf_t *conf = child;
- ngx_http_listen_t *ls;
- ngx_http_server_name_t *sn;
- ngx_http_core_main_conf_t *cmcf;
+ ngx_http_listen_t *ls;
+ ngx_http_server_name_t *sn;
/* TODO: it does not merge, it inits only */
@@ -1837,13 +1840,6 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
sn->name.len = ngx_strlen(sn->name.data);
sn->core_srv_conf = conf;
- sn->wildcard = 0;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- if (cmcf->max_server_name_len < sn->name.len) {
- cmcf->max_server_name_len = sn->name.len;
- }
}
ngx_conf_merge_size_value(conf->connection_pool_size,
@@ -2279,49 +2275,60 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_core_srv_conf_t *scf = conf;
-
- ngx_uint_t i;
- ngx_str_t *value;
- ngx_http_server_name_t *sn;
- ngx_http_core_main_conf_t *cmcf;
-
- /* TODO: warn about duplicate 'server_name' directives */
+ ngx_http_core_srv_conf_t *cscf = conf;
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+ u_char ch;
+ ngx_str_t *value, name;
+ ngx_uint_t i;
+ ngx_http_server_name_t *sn;
value = cf->args->elts;
- for (i = 1; i < cf->args->nelts; i++) {
- if (value[i].len == 0) {
+ ch = value[1].data[0];
+
+ if (cscf->server_name.data == NULL && value[1].len) {
+ if (ch == '*') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "server name \"%V\" is invalid "
- "in \"%V\" directive",
- &value[i], &cmd->name);
+ "first server name \"%V\" must not be wildcard",
+ &value[1]);
return NGX_CONF_ERROR;
}
- sn = ngx_array_push(&scf->server_names);
- if (sn == NULL) {
+ name = value[1];
+
+ if (ch == '.') {
+ name.len--;
+ name.data++;
+ }
+
+ cscf->server_name.len = name.len;
+ cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
+ if (cscf->server_name.data == NULL) {
return NGX_CONF_ERROR;
}
+ }
- sn->name.len = value[i].len;
- sn->name.data = value[i].data;
- sn->core_srv_conf = scf;
+ for (i = 1; i < cf->args->nelts; i++) {
- if (sn->name.data[0] == '*') {
- sn->name.len--;
- sn->name.data++;
- sn->wildcard = 1;
+ ch = value[i].data[0];
- } else {
- sn->wildcard = 0;
+ if (value[i].len == 0
+ || (ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
+ || (ch == '.' && value[i].len < 2))
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "server name \"%V\" is invalid", &value[i]);
+ return NGX_CONF_ERROR;
}
- if (cmcf->max_server_name_len < sn->name.len) {
- cmcf->max_server_name_len = sn->name.len;
+ sn = ngx_array_push(&cscf->server_names);
+ if (sn == NULL) {
+ return NGX_CONF_ERROR;
}
+
+ sn->name.len = value[i].len;
+ sn->name.data = value[i].data;
+ sn->core_srv_conf = cscf;
}
return NGX_CONF_OK;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 0d8ae74c3..1652f3560 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -73,10 +73,8 @@ typedef struct {
ngx_hash0_t headers_in_hash;
ngx_hash0_t variables_hash;
- ngx_uint_t server_names_hash;
- ngx_uint_t server_names_hash_threshold;
-
- size_t max_server_name_len;
+ ngx_uint_t server_names_hash_max_size;
+ ngx_uint_t server_names_hash_bucket_size;
ngx_array_t variables; /* ngx_http_variable_t */
ngx_array_t all_variables; /* ngx_http_variable_t */
@@ -99,6 +97,8 @@ typedef struct {
/* server ctx */
ngx_http_conf_ctx_t *ctx;
+ ngx_str_t server_name;
+
size_t connection_pool_size;
size_t request_pool_size;
size_t client_header_buffer_size;
@@ -115,45 +115,53 @@ typedef struct {
/* list of structures to find core_srv_conf quickly at run time */
+
+typedef struct {
+ in_addr_t addr;
+ /* the default server configuration for this address:port */
+ ngx_http_core_srv_conf_t *core_srv_conf;
+ ngx_http_virtual_names_t *virtual_names;
+} ngx_http_in_addr_t;
+
+
typedef struct {
in_port_t port;
ngx_str_t port_text;
- ngx_array_t addrs; /* array of ngx_http_in_addr_t */
+ ngx_http_in_addr_t *addrs;
+ ngx_uint_t naddrs;
} ngx_http_in_port_t;
-struct ngx_http_in_addr_s {
+typedef struct {
+ in_port_t port;
+ ngx_array_t addrs; /* array of ngx_http_conf_in_addr_t */
+} ngx_http_conf_in_port_t;
+
+
+typedef struct {
in_addr_t addr;
- ngx_array_t names; /* array of ngx_http_server_name_t */
- ngx_array_t *hash; /* hash of ngx_http_server_name_t */
- ngx_array_t wildcards; /* array of ngx_http_server_name_t */
+ ngx_hash_t hash;
+ ngx_hash_wildcard_t *dns_wildcards;
+
+ ngx_array_t names; /* array of ngx_http_server_name_t */
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *core_srv_conf;
- ngx_http_listen_conf_t conf;
-};
+ unsigned default_server:1;
+ unsigned bind:1;
+
+ ngx_http_listen_conf_t *listen_conf;
+} ngx_http_conf_in_addr_t;
typedef struct {
ngx_str_t name;
ngx_http_core_srv_conf_t *core_srv_conf; /* virtual name server conf */
-
- ngx_uint_t wildcard; /* unsigned wildcard:1 */
} ngx_http_server_name_t;
-#define ngx_http_server_names_hash_key(key, name, len, prime) \
- { \
- ngx_uint_t n0; \
- for (key = 0, n0 = 0; n0 < len; n0++) { \
- key += name[n0]; \
- } \
- key %= prime; \
- }
-
-
typedef struct {
ngx_int_t status;
ngx_int_t overwrite;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index ba93c0df3..f18263315 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -203,11 +203,10 @@ void ngx_http_init_request(ngx_event_t *rev)
struct sockaddr_in sin;
ngx_connection_t *c;
ngx_http_request_t *r;
- ngx_http_in_port_t *in_port;
- ngx_http_in_addr_t *in_addr;
+ ngx_http_in_port_t *hip;
+ ngx_http_in_addr_t *hia;
ngx_http_log_ctx_t *ctx;
ngx_http_connection_t *hc;
- ngx_http_server_name_t *server_name;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_main_conf_t *cmcf;
@@ -269,15 +268,15 @@ void ngx_http_init_request(ngx_event_t *rev)
/* AF_INET only */
- in_port = c->servers;
- in_addr = in_port->addrs.elts;
+ hip = c->servers;
+ hia = hip->addrs;
- r->port = in_port->port;
- r->port_text = &in_port->port_text;
+ r->port = hip->port;
+ r->port_text = &hip->port_text;
i = 0;
- if (in_port->addrs.nelts > 1) {
+ if (hip->naddrs > 1) {
/*
* There are several addresses on this port and one of them
@@ -308,25 +307,27 @@ void ngx_http_init_request(ngx_event_t *rev)
/* the last in_port->addrs address is "*" */
- for ( /* void */ ; i < in_port->addrs.nelts - 1; i++) {
- if (in_addr[i].addr == r->in_addr) {
+ for ( /* void */ ; i < hip->naddrs - 1; i++) {
+ if (hia[i].addr == r->in_addr) {
break;
}
}
} else {
- r->in_addr = in_addr[0].addr;
+ r->in_addr = hia[0].addr;
}
- r->virtual_names = &in_addr[i];
+ r->virtual_names = hia[i].virtual_names;
/* the default server configuration for the address:port */
- cscf = in_addr[i].core_srv_conf;
+ cscf = hia[i].core_srv_conf;
r->main_conf = cscf->ctx->main_conf;
r->srv_conf = cscf->ctx->srv_conf;
r->loc_conf = cscf->ctx->loc_conf;
+ r->server_name = cscf->server_name;
+
rev->handler = ngx_http_process_request_line;
#if (NGX_HTTP_SSL)
@@ -350,9 +351,6 @@ void ngx_http_init_request(ngx_event_t *rev)
#endif
- server_name = cscf->server_names.elts;
- r->server_name = server_name->name;
-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
c->log->file = clcf->err_log->file;
if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
@@ -1321,78 +1319,35 @@ ngx_http_process_request_header(ngx_http_request_t *r)
static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t *r)
{
- ngx_int_t rc;
- ngx_uint_t i, n, key;
- ngx_http_server_name_t *name;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_srv_conf_t *cscf;
- ngx_http_core_main_conf_t *cmcf;
-
- if (r->virtual_names->hash) {
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- ngx_http_server_names_hash_key(key,
- r->headers_in.host->value.data,
- r->headers_in.host_name_len,
- cmcf->server_names_hash);
+ size_t len;
+ u_char *host;
+ ngx_http_virtual_names_t *vn;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_core_srv_conf_t *cscf;
- name = r->virtual_names->hash[key].elts;
- n = r->virtual_names->hash[key].nelts;
+ vn = r->virtual_names;
- } else {
- name = r->virtual_names->names.elts;
- n = r->virtual_names->names.nelts;
+ if (vn == NULL) {
+ return NGX_OK;
}
- for (i = 0; i < n; i++) {
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "server name: %V", &name[i].name);
-
- if (r->headers_in.host_name_len != name[i].name.len) {
- continue;
- }
+ host = r->headers_in.host->value.data;
+ len = r->headers_in.host_name_len;
- rc = ngx_strncmp(r->headers_in.host->value.data,
- name[i].name.data, name[i].name.len);
+ /* STUB: ngx_hash_key() here is STUB */
- if (rc == 0) {
- r->server_name = name[i].name;
+ if (vn->hash.buckets) {
+ cscf = ngx_hash_find(&vn->hash, ngx_hash_key(host, len), host, len);
+ if (cscf) {
goto found;
}
-
- if (rc < 0) {
- /* the server names are lexicographically sorted */
- break;
- }
}
- if (r->virtual_names->wildcards.nelts) {
-
- name = r->virtual_names->wildcards.elts;
- for (i = 0; i < r->virtual_names->wildcards.nelts; i++) {
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "server name: %V", &name[i].name);
-
- if (r->headers_in.host_name_len <= name[i].name.len) {
- continue;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "server name: %s",
- r->headers_in.host->value.data
- + (r->headers_in.host_name_len - name[i].name.len));
+ if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
+ cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
- if (ngx_strncmp(r->headers_in.host->value.data
- + (r->headers_in.host_name_len - name[i].name.len),
- name[i].name.data, name[i].name.len) == 0)
- {
- r->server_name.len = r->headers_in.host_name_len;
- r->server_name.data = r->headers_in.host->value.data;
-
- goto found;
- }
+ if (cscf) {
+ goto found;
}
}
@@ -1406,8 +1361,11 @@ ngx_http_find_virtual_server(ngx_http_request_t *r)
found:
- r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
- r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
+ r->server_name.len = len;
+ r->server_name.data = host;
+
+ r->srv_conf = cscf->ctx->srv_conf;
+ r->loc_conf = cscf->ctx->loc_conf;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
r->connection->log->file = clcf->err_log->file;
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 9e6fd15e0..dce919f13 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -250,14 +250,20 @@ typedef struct {
} ngx_http_connection_t;
+typedef struct {
+ ngx_hash_t hash;
+ ngx_hash_wildcard_t *dns_wildcards;
+} ngx_http_virtual_names_t;
+
+
typedef void (*ngx_http_cleanup_pt)(void *data);
typedef struct ngx_http_cleanup_s ngx_http_cleanup_t;
struct ngx_http_cleanup_s {
- ngx_http_cleanup_pt handler;
- void *data;
- ngx_http_cleanup_t *next;
+ ngx_http_cleanup_pt handler;
+ void *data;
+ ngx_http_cleanup_t *next;
};
@@ -325,7 +331,7 @@ struct ngx_http_request_s {
ngx_uint_t port;
ngx_str_t *port_text; /* ":80" */
ngx_str_t server_name;
- ngx_http_in_addr_t *virtual_names;
+ ngx_http_virtual_names_t *virtual_names;
ngx_uint_t phase;
ngx_int_t phase_handler;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 5711b4abf..cdf9a07f9 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -344,7 +344,7 @@ ngx_http_upstream_init(ngx_http_request_t *r)
u->state->response_time = tp->sec * 1000 + tp->msec;
- cln = ngx_http_cleanup_add(r, sizeof(void *));
+ cln = ngx_http_cleanup_add(r, 0);
if (cln == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;