nginx-0.3.18-RELEASE import

*) 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; the bug had appeared in 0.3.12.

    *) Bugfix: on 64-bit platforms segmentation fault may occurred on
       start; the bug had appeared in 0.3.16.
This commit is contained in:
Igor Sysoev 2005-12-26 17:07:48 +00:00
parent 35e88caa8c
commit 61e066131b
26 changed files with 1069 additions and 822 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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

View File

@ -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
;;

View File

@ -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 \

View File

@ -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"';

View File

@ -9,6 +9,101 @@
<title lang="en">nginx changelog</title>
<changes ver="0.3.18" date="26.12.2005">
<change type="feature">
<para lang="ru">
ÄÉÒÅËÔÉ×Á server_names ÐÏÄÄÅÒÖÉ×ÁÅÔ ÉÍÅÎÁ ×ÉÄÁ ".domain.tld".
</para>
<para lang="en">
the "server_names" directive supports the ".domain.tld" names.
</para>
</change>
<change type="feature">
<para lang="ru">
ÄÉÒÅËÔÉ×Á server_names ÉÓÐÏÌØÚÕÅÔ ÈÜÛ ÄÌÑ ÉͣΠ×ÉÄÁ "*.domain.tld"
É ÂÏÌÅÅ ÜÆÆÅËÔÉ×ÎÙÊ ÈÜÛ ÄÌÑ ÏÂÙÞÎÙÈ ÉÍ£Î.
</para>
<para lang="en">
the "server_names" directive uses the hash for the "*.domain.tld" names
and more effective hash for usual names.
</para>
</change>
<change type="change">
<para lang="ru">
ÄÉÒÅËÔÉ×Ù server_names_hash_max_size É server_names_hash_bucket_size.
</para>
<para lang="en">
the "server_names_hash_max_size" and "server_names_hash_bucket_size" directives.
</para>
</change>
<change type="change">
<para lang="ru">
ÄÉÒÅËÔÉ×Ù server_names_hash É server_names_hash_threshold ÕÐÒÁÚÄÎÅÎÙ.
</para>
<para lang="en">
the "server_names_hash" and "server_names_hash_threshold" directives
were canceled.
</para>
</change>
<change type="feature">
<para lang="ru">
ÄÉÒÅËÔÉ×Á valid_referers ÉÓÐÏÌØÚÕÅÔ ÈÜÛ ÄÌÑ ÉͣΠÓÁÊÔÏ×.
</para>
<para lang="en">
the "valid_referers" directive uses the hash site names.
</para>
</change>
<change type="change">
<para lang="ru">
ÔÅÐÅÒØ ÄÉÒÅËÔÉ×Á valid_referers ÐÒÏ×ÅÒÑÅÔ ÔÏÌØËÏ ÉÍÅÎÁ ÓÁÊÔÏ× ÂÅÚ ÕÞ£ÔÁ URI.
</para>
<para lang="en">
now the "valid_referers" directive checks the site names only without
the URI part.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ÎÅËÏÔÏÒÙÅ ÉÍÅÎÁ ×ÉÄÁ ".domain.tld" ÎÅ×ÅÒÎÏ ÏÂÒÁÂÁÔÙ×ÁÌÉÓØ ÍÏÄÕÌÅÍ
ngx_http_map_module.
</para>
<para lang="en">
some ".domain.tld" names incorrectly processed by the ngx_http_map_module.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ÅÓÌÉ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÇÏ ÆÁÊÌÁ ÎÅ ÂÙÌÏ, ÔÏ ÐÒÏÉÓÈÏÄÉÌ segmentation fault;
ÏÛÉÂËÁ ÐÏÑ×ÉÌÁÓØ × 0.3.12.
</para>
<para lang="en">
segmentation fault was occurred if configuration file did not exist;
bug appeared in 0.3.12.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ÎÁ 64-ÂÉÔÎÙÈ ÐÌÁÔÆÏÒÍÁÈ ÐÒÉ ÓÔÁÒÔÅ ÍÏÇ ÐÒÏÉÚÏÊÔÉ segmentation fault;
ÏÛÉÂËÁ ÐÏÑ×ÉÌÁÓØ × 0.3.16.
</para>
<para lang="en">
on 64-bit platforms segmentation fault may occurred on start;
bug appeared in 0.3.16.
</para>
</change>
</changes>
<changes ver="0.3.17" date="18.12.2005">
<change type="change">
@ -31,10 +126,12 @@ the "map" directive supports domain names in the ".domain.tld" form.
<change type="bugfix">
<para lang="ru">
×Ï ×ÒÅÍÑ SSL handshake ÎÅ ÉcÐÏÌØÚÏ×ÁÌÉÓØ ÔÁÊÍÁÕÔÙ.
×Ï ×ÒÅÍÑ SSL handshake ÎÅ ÉcÐÏÌØÚÏ×ÁÌÉÓØ ÔÁÊÍÁÕÔÙ;
ÏÛÉÂËÁ ÐÏÑ×ÉÌÁÓØ × 0.2.4.
</para>
<para lang="en">
the timeouts were not used in SSL handshake.
the timeouts were not used in SSL handshake;
bug appeared in 0.2.4.
</para>
</change>
@ -1978,7 +2075,7 @@ or "Authorization" lines, then nginx now returns the 400 error.
ÄÉÒÅËÔÉ×Á post_accept_timeout ÕÐÒÁÚÄÎÅÎÁ.
</para>
<para lang="en">
The "post_accept_timeout" directive was canceled.
the "post_accept_timeout" directive was canceled.
</para>
</change>

View File

@ -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"

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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)
{
ctx.keys.pool = cf->pool;
ctx.keys.temp_pool = pool;
if (ngx_hash_keys_array_init(&ctx.keys, NGX_HASH_LARGE) != 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.hash.keys_hash = ngx_pcalloc(pool,
sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
if (ctx.hash.keys_hash == NULL) {
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;

View File

@ -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)

View File

@ -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;
}
len = p - ref;
if (ref[n] != '.') {
continue;
}
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;
}
}
if (ngx_strncmp(&ref[n], refs[i].name.data,
refs[i].name.len) == 0)
{
*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;
}
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) {
rlcf->keys->pool = cf->pool;
rlcf->keys->temp_pool = cf->pool;
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;
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;
}
}
continue;
}
ref = ngx_array_push(lcf->referers);
if (ref == NULL) {
return NGX_CONF_ERROR;
}
p = (u_char *) ngx_strstr(value[i].data, "/");
if (value[i].data[0] != '*') {
ref->name = value[i];
ref->wildcard = 0;
continue;
}
if (value[i].data[1] != '.') {
if (p) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid wildcard referer \"%V\"", &value[i]);
return NGX_CONF_ERROR;
"URI part \"%s\" is deprecated, ignored", p);
value[i].len = p - value[i].data;
}
ref->name.len = value[i].len - 1;
ref->name.data = value[i].data + 1;
ref->wildcard = 1;
}
if (!server_names) {
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) {
if (ngx_http_add_referer(cf, rlcf->keys, &value[i]) != NGX_OK) {
return NGX_CONF_ERROR;
}
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;
}
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 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;
}
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;
}
if (rc == NGX_BUSY) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"conflicting parameter \"%V\"", value);
}
return NGX_CONF_ERROR;
}
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);
}

View File

@ -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) {
if (lscf[l].port != in_port[p].port) {
continue;
}
/* the port is already in the port list */
/* the port is already in the port list */
port_found = 1;
addr_found = 0;
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) {
continue;
}
if (lscf[l].addr == in_addr[a].addr) {
/* 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) {
/* add the port to the in_port list */
in_port = ngx_array_push(&in_ports);
if (in_port == NULL) {
return NGX_CONF_ERROR;
goto found;
}
in_port->port = lscf[l].port;
in_port->addrs.elts = NULL;
/*
* add the address to the addresses list that
* bound to this port
*/
in_port->port_text.data = ngx_palloc(cf->pool, 7);
if (in_port->port_text.data == NULL) {
return NGX_CONF_ERROR;
}
in_port->port_text.len = ngx_sprintf(in_port->port_text.data,
":%d", in_port->port)
- in_port->port_text.data;
if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s])
if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s])
!= NGX_OK)
{
return NGX_CONF_ERROR;
}
goto found;
}
/* add the port to the in_port list */
in_port = ngx_array_push(&in_ports);
if (in_port == NULL) {
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;
ngx_qsort(in_addr[a].names.elts, in_addr[a].names.nelts,
sizeof(ngx_http_server_name_t), ngx_cmp_server_names);
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++) {
/* create a hash for many names */
ch = name[s].name.data[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 (ch == '*' || ch == '.') {
continue;
}
rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
0);
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;
}
}
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);
s_name = ngx_array_push(&in_addr[a].hash[key]);
if (s_name == NULL) {
return NGX_CONF_ERROR;
}
name = in_addr[a].names.elts;
*s_name = name[s];
if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
"conflicting server name \"%V\", ignored",
&name[s].name);
}
}
for (s = 0; s < in_addr[a].names.nelts; s++) {
ch = name[s].name.data[0];
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) {
/*
* if this port has not the "*:port" binding then create
* the separate ngx_http_in_port_t for the all bindings
*/
inport = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
if (inport == NULL) {
return NGX_CONF_ERROR;
}
inport->port = in_port[p].port;
inport->port_text = in_port[p].port_text;
/* init list of the addresses ... */
if (ngx_array_init(&inport->addrs, cf->pool, 1,
sizeof(ngx_http_in_addr_t)) != NGX_OK)
{
return NGX_CONF_ERROR;
}
/* ... and set up it with the first address */
inport->addrs.nelts = 1;
inport->addrs.elts = in_port[p].addrs.elts;
ls->servers = inport;
/* prepare for the next cycle */
in_port[p].addrs.elts = (char *) in_port[p].addrs.elts
+ in_port[p].addrs.size;
in_port[p].addrs.nelts--;
in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
a = 0;
continue;
}
hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
if (hip == NULL) {
return NGX_CONF_ERROR;
}
ls->servers = &in_port[p];
a++;
hip->port = in_port[p].port;
hip->port_text.data = ngx_palloc(cf->pool, 7);
if (hip->port_text.data == NULL) {
return NGX_CONF_ERROR;
}
ls->servers = hip;
hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d",
hip->port)
- hip->port_text.data;
in_addr = in_port[p].addrs.elts;
if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
hip->naddrs = 1;
done = 0;
} else if (in_port[p].addrs.nelts > 1
&& in_addr[last - 1].addr == INADDR_ANY)
{
hip->naddrs = last;
done = 1;
} else {
hip->naddrs = 1;
done = 0;
}
#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;
}
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;
}
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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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_http_core_srv_conf_t *cscf = 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 */
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);
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;
}
}
for (i = 1; i < cf->args->nelts; i++) {
ch = value[i].data[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;
}
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 = scf;
if (sn->name.data[0] == '*') {
sn->name.len--;
sn->name.data++;
sn->wildcard = 1;
} else {
sn->wildcard = 0;
}
if (cmcf->max_server_name_len < sn->name.len) {
cmcf->max_server_name_len = sn->name.len;
}
sn->core_srv_conf = cscf;
}
return NGX_CONF_OK;

View File

@ -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;

View File

@ -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;
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;
if (r->virtual_names->hash) {
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
vn = r->virtual_names;
ngx_http_server_names_hash_key(key,
r->headers_in.host->value.data,
r->headers_in.host_name_len,
cmcf->server_names_hash);
name = r->virtual_names->hash[key].elts;
n = r->virtual_names->hash[key].nelts;
} 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++) {
host = r->headers_in.host->value.data;
len = r->headers_in.host_name_len;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"server name: %V", &name[i].name);
/* STUB: ngx_hash_key() here is STUB */
if (r->headers_in.host_name_len != name[i].name.len) {
continue;
}
rc = ngx_strncmp(r->headers_in.host->value.data,
name[i].name.data, name[i].name.len);
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) {
if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
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 (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;

View File

@ -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;

View File

@ -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;