summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2010-06-30 15:11:51 +0000
committerJonathan Kolb <jon@b0g.us>2010-06-30 15:11:51 +0000
commitb7854e35967b1aa6241be5b85b9722efc8c94a3f (patch)
tree671c538e66dd04e236a03cd812a7e8de063b90b2
parent2a3f501450d6c2b9f48c2d64d3d350241c013125 (diff)
downloadnginx-b7854e35967b1aa6241be5b85b9722efc8c94a3f.tar.gz
Changes with nginx 0.8.43 30 Jun 2010v0.8.43
*) Feature: large geo ranges base loading speed-up. *) Bugfix: an error_page redirection to "location /zero { return 204; }" without changing status code kept the error body; the bug had appeared in 0.8.42. *) Bugfix: nginx might close IPv6 listen socket during reconfiguration. Thanks to Maxim Dounin. *) Bugfix: the $uid_set variable may be used at any request processing stage.
-rw-r--r--CHANGES16
-rw-r--r--CHANGES.ru16
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_conf_file.c3
-rw-r--r--src/core/ngx_cycle.c2
-rw-r--r--src/core/ngx_resolver.c2
-rw-r--r--src/core/ngx_string.c83
-rw-r--r--src/core/ngx_string.h15
-rw-r--r--src/http/modules/ngx_http_geo_module.c566
-rw-r--r--src/http/modules/ngx_http_map_module.c2
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_sub_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_userid_filter_module.c229
-rw-r--r--src/http/modules/ngx_http_xslt_filter_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_core_module.c1
-rw-r--r--src/http/ngx_http_header_filter_module.c4
-rw-r--r--src/http/ngx_http_parse.c2
-rw-r--r--src/http/ngx_http_request.h1
-rw-r--r--src/http/ngx_http_special_response.c37
-rw-r--r--src/http/ngx_http_variables.c84
-rw-r--r--src/http/ngx_http_variables.h13
-rw-r--r--src/mail/ngx_mail_handler.c8
-rw-r--r--src/os/unix/ngx_files.c56
-rw-r--r--src/os/unix/ngx_files.h13
-rw-r--r--src/os/unix/ngx_readv_chain.c4
-rw-r--r--src/os/unix/ngx_recv.c4
-rw-r--r--src/os/unix/ngx_udp_recv.c4
28 files changed, 840 insertions, 337 deletions
diff --git a/CHANGES b/CHANGES
index fce793d38..d06fc474f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,20 @@
+Changes with nginx 0.8.43 30 Jun 2010
+
+ *) Feature: large geo ranges base loading speed-up.
+
+ *) Bugfix: an error_page redirection to "location /zero { return 204;
+ }" without changing status code kept the error body; the bug had
+ appeared in 0.8.42.
+
+ *) Bugfix: nginx might close IPv6 listen socket during
+ reconfiguration.
+ Thanks to Maxim Dounin.
+
+ *) Bugfix: the $uid_set variable may be used at any request processing
+ stage.
+
+
Changes with nginx 0.8.42 21 Jun 2010
*) Change: now nginx tests locations given by regular expressions, if
diff --git a/CHANGES.ru b/CHANGES.ru
index 90d3cf8e8..d6997b9d7 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,20 @@
+Изменения в nginx 0.8.43 30.06.2010
+
+ *) Добавление: ускорение загрузки больших баз geo-диапазонов.
+
+ *) Исправление: перенаправление ошибки в "location /zero { return 204;
+ }" без изменения кода ответа оставляло тело ошибки; ошибка появилась
+ в 0.8.42.
+
+ *) Исправление: nginx мог закрывать IPv6 listen сокет во время
+ переконфигурации.
+ Спасибо Максиму Дунину.
+
+ *) Исправление: переменную $uid_set можно использовать на любой стадии
+ обработки запроса.
+
+
Изменения в nginx 0.8.42 21.06.2010
*) Изменение: теперь nginx проверяет location'ы, заданные регулярными
diff --git a/src/core/nginx.h b/src/core/nginx.h
index e59b54878..0ae989dc8 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 8042
-#define NGINX_VERSION "0.8.42"
+#define nginx_version 8043
+#define NGINX_VERSION "0.8.43"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 20d9af9e4..83c107329 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -671,7 +671,8 @@ ngx_conf_read_token(ngx_conf_t *cf)
}
} else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
- || ch == ';' || ch == '{') {
+ || ch == ';' || ch == '{')
+ {
last_space = 1;
found = 1;
}
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index a4e00b9d4..5973fbe23 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -868,7 +868,7 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2)
sin61 = (struct sockaddr_in6 *) sa1;
sin62 = (struct sockaddr_in6 *) sa2;
- if (sin61->sin6_port != sin61->sin6_port) {
+ if (sin61->sin6_port != sin62->sin6_port) {
return NGX_DECLINED;
}
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index a2b557062..1df86fa95 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -1836,7 +1836,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
p += sizeof(ngx_resolver_query_t);
- for (n = 0; n < 32; n += 8){
+ for (n = 0; n < 32; n += 8) {
d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
*p = (u_char) (d - &p[1]);
p = d;
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 95ac9cbff..9681111e7 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1638,6 +1638,89 @@ ngx_escape_html(u_char *dst, u_char *src, size_t size)
}
+void
+ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
+{
+ ngx_str_node_t *n, *t;
+ ngx_rbtree_node_t **p;
+
+ for ( ;; ) {
+
+ n = (ngx_str_node_t *) node;
+ t = (ngx_str_node_t *) temp;
+
+ if (node->key != temp->key) {
+
+ p = (node->key < temp->key) ? &temp->left : &temp->right;
+
+ } else if (n->str.len != t->str.len) {
+
+ p = (n->str.len < t->str.len) ? &temp->left : &temp->right;
+
+ } else {
+ p = (ngx_memcmp(n->str.data, t->str.data, n->str.len) < 0)
+ ? &temp->left : &temp->right;
+ }
+
+ if (*p == sentinel) {
+ break;
+ }
+
+ temp = *p;
+ }
+
+ *p = node;
+ node->parent = temp;
+ node->left = sentinel;
+ node->right = sentinel;
+ ngx_rbt_red(node);
+}
+
+
+ngx_str_node_t *
+ngx_str_rbtree_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val, uint32_t hash)
+{
+ ngx_int_t rc;
+ ngx_str_node_t *n;
+ ngx_rbtree_node_t *node, *sentinel;
+
+ node = rbtree->root;
+ sentinel = rbtree->sentinel;
+
+ while (node != sentinel) {
+
+ n = (ngx_str_node_t *) node;
+
+ if (hash != node->key) {
+ node = (hash < node->key) ? node->left : node->right;
+ continue;
+ }
+
+ if (val->len != n->str.len) {
+ node = (val->len < n->str.len) ? node->left : node->right;
+ continue;
+ }
+
+ rc = ngx_memcmp(val->data, n->str.data, val->len);
+
+ if (rc < 0) {
+ node = node->left;
+ continue;
+ }
+
+ if (rc > 0) {
+ node = node->right;
+ continue;
+ }
+
+ return n;
+ }
+
+ return NULL;
+}
+
+
/* ngx_sort() is implemented as insertion sort because we need stable sort */
void
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 53b942297..821871470 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -89,7 +89,7 @@ ngx_strlchr(u_char *p, u_char *last, u_char c)
#if (NGX_MEMCPY_LIMIT)
void *ngx_memcpy(void *dst, void *src, size_t n);
-#define ngx_cpymem(dst, src, n) ((u_char *) ngx_memcpy(dst, src, n)) + (n)
+#define ngx_cpymem(dst, src, n) (((u_char *) ngx_memcpy(dst, src, n)) + (n))
#else
@@ -99,7 +99,7 @@ void *ngx_memcpy(void *dst, void *src, size_t n);
* icc8 compile memcpy(d, s, 4) to the inline "mov"es or XMM moves.
*/
#define ngx_memcpy(dst, src, n) (void) memcpy(dst, src, n)
-#define ngx_cpymem(dst, src, n) ((u_char *) memcpy(dst, src, n)) + (n)
+#define ngx_cpymem(dst, src, n) (((u_char *) memcpy(dst, src, n)) + (n))
#endif
@@ -200,6 +200,17 @@ void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size);
+typedef struct {
+ ngx_rbtree_node_t node;
+ ngx_str_t str;
+} ngx_str_node_t;
+
+
+void ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
+ngx_str_node_t *ngx_str_rbtree_lookup(ngx_rbtree_t *rbtree, ngx_str_t *name,
+ uint32_t hash);
+
void ngx_sort(void *base, size_t n, size_t size,
ngx_int_t (*cmp)(const void *, const void *));
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index a184a7ae3..6ad08b9b2 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -10,41 +10,53 @@
typedef struct {
+ ngx_http_variable_value_t *value;
u_short start;
u_short end;
- ngx_http_variable_value_t *value;
} ngx_http_geo_range_t;
typedef struct {
- ngx_http_geo_range_t *ranges;
- ngx_uint_t n;
-} ngx_http_geo_low_ranges_t;
+ ngx_http_geo_range_t **low;
+ ngx_http_variable_value_t *default_value;
+} ngx_http_geo_high_ranges_t;
typedef struct {
- ngx_http_geo_low_ranges_t low[0x10000];
- ngx_http_variable_value_t *default_value;
-} ngx_http_geo_high_ranges_t;
+ ngx_str_node_t sn;
+ ngx_http_variable_value_t *value;
+ size_t offset;
+} ngx_http_geo_variable_value_node_t;
typedef struct {
ngx_http_variable_value_t *value;
ngx_str_t *net;
- ngx_http_geo_high_ranges_t *high;
+ ngx_http_geo_high_ranges_t high;
ngx_radix_tree_t *tree;
ngx_rbtree_t rbtree;
ngx_rbtree_node_t sentinel;
ngx_array_t *proxies;
ngx_pool_t *pool;
ngx_pool_t *temp_pool;
+
+ size_t data_size;
+
+ ngx_str_t include_name;
+ ngx_uint_t includes;
+ ngx_uint_t entries;
+
+ unsigned ranges:1;
+ unsigned outside_entries:1;
+ unsigned allow_binary_include:1;
+ unsigned binary_include:1;
} ngx_http_geo_conf_ctx_t;
typedef struct {
union {
ngx_radix_tree_t *tree;
- ngx_http_geo_high_ranges_t *high;
+ ngx_http_geo_high_ranges_t high;
} u;
ngx_array_t *proxies;
@@ -73,6 +85,13 @@ static char *ngx_http_geo_add_proxy(ngx_conf_t *cf,
ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr);
static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
ngx_cidr_t *cidr);
+static char *ngx_http_geo_include(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
+ ngx_str_t *name);
+static ngx_int_t ngx_http_geo_include_binary_base(ngx_conf_t *cf,
+ ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *name);
+static void ngx_http_geo_create_binary_base(ngx_http_geo_conf_ctx_t *ctx);
+static u_char *ngx_http_geo_copy_values(u_char *base, u_char *p,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
static ngx_command_t ngx_http_geo_commands[] = {
@@ -119,6 +138,20 @@ ngx_module_t ngx_http_geo_module = {
};
+typedef struct {
+ u_char GEORNG[6];
+ u_char version;
+ u_char ptr_size;
+ uint32_t endianess;
+ uint32_t crc32;
+} ngx_http_geo_header_t;
+
+
+static ngx_http_geo_header_t ngx_http_geo_header = {
+ { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0
+};
+
+
/* AF_INET only */
static ngx_int_t
@@ -148,23 +181,24 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
in_addr_t addr;
- ngx_uint_t i, n;
+ ngx_uint_t n;
ngx_http_geo_range_t *range;
- *v = *ctx->u.high->default_value;
+ *v = *ctx->u.high.default_value;
addr = ngx_http_geo_addr(r, ctx);
- range = ctx->u.high->low[addr >> 16].ranges;
-
- n = addr & 0xffff;
+ range = ctx->u.high.low[addr >> 16];
- for (i = 0; i < ctx->u.high->low[addr >> 16].n; i++) {
- if (n >= (ngx_uint_t) range[i].start
- && n <= (ngx_uint_t) range[i].end)
- {
- *v = *range[i].value;
- }
+ if (range) {
+ n = addr & 0xffff;
+ do {
+ if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end)
+ {
+ *v = *range->value;
+ break;
+ }
+ } while ((++range)->value);
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -256,6 +290,7 @@ static char *
ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
+ void **p;
size_t len;
ngx_str_t *value, name;
ngx_uint_t i;
@@ -302,18 +337,20 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+ ngx_memzero(&ctx, sizeof(ngx_http_geo_conf_ctx_t));
+
ctx.temp_pool = ngx_create_pool(16384, cf->log);
if (ctx.temp_pool == NULL) {
return NGX_CONF_ERROR;
}
- ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel,
- ngx_http_variable_value_rbtree_insert);
+ ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, ngx_str_rbtree_insert_value);
- ctx.high = NULL;
- ctx.tree = NULL;
- ctx.proxies = NULL;
ctx.pool = cf->pool;
+ ctx.data_size = sizeof(ngx_http_geo_header_t)
+ + sizeof(ngx_http_variable_value_t)
+ + 0x10000 * sizeof(ngx_http_geo_range_t *);
+ ctx.allow_binary_include = 1;
save = *cf;
cf->pool = pool;
@@ -327,25 +364,35 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
geo->proxies = ctx.proxies;
- if (ctx.high) {
+ if (ctx.high.low) {
- for (i = 0; i < 0x10000; i++) {
- a = (ngx_array_t *) ctx.high->low[i].ranges;
+ if (!ctx.binary_include) {
+ for (i = 0; i < 0x10000; i++) {
+ a = (ngx_array_t *) ctx.high.low[i];
- if (a == NULL || a->nelts == 0) {
- continue;
- }
+ if (a == NULL || a->nelts == 0) {
+ continue;
+ }
- ctx.high->low[i].n = a->nelts;
+ len = a->nelts * sizeof(ngx_http_geo_range_t);
- len = a->nelts * sizeof(ngx_http_geo_range_t);
+ ctx.high.low[i] = ngx_palloc(cf->pool, len + sizeof(void *));
+ if (ctx.high.low[i] == NULL) {
+ return NGX_CONF_ERROR;
+ }
- ctx.high->low[i].ranges = ngx_palloc(cf->pool, len);
- if (ctx.high->low[i].ranges == NULL ){
- return NGX_CONF_ERROR;
+ p = (void **) ngx_cpymem(ctx.high.low[i], a->elts, len);
+ *p = NULL;
+ ctx.data_size += len + sizeof(void *);
}
- ngx_memcpy(ctx.high->low[i].ranges, a->elts, len);
+ if (ctx.allow_binary_include
+ && !ctx.outside_entries
+ && ctx.entries > 100000
+ && ctx.includes == 1)
+ {
+ ngx_http_geo_create_binary_base(&ctx);
+ }
}
geo->u.high = ctx.high;
@@ -353,13 +400,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
var->get_handler = ngx_http_geo_range_variable;
var->data = (uintptr_t) geo;
+ if (ctx.high.default_value == NULL) {
+ ctx.high.default_value = &ngx_http_variable_null_value;
+ }
+
ngx_destroy_pool(ctx.temp_pool);
ngx_destroy_pool(pool);
- if (ctx.high->default_value == NULL) {
- ctx.high->default_value = &ngx_http_variable_null_value;
- }
-
} else {
if (ctx.tree == NULL) {
ctx.tree = ngx_radix_tree_create(cf->pool, -1);
@@ -396,7 +443,7 @@ static char *
ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
{
char *rv;
- ngx_str_t *value, file;
+ ngx_str_t *value;
ngx_cidr_t cidr;
ngx_http_geo_conf_ctx_t *ctx;
@@ -415,11 +462,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
goto failed;
}
- ctx->high = ngx_pcalloc(ctx->pool,
- sizeof(ngx_http_geo_high_ranges_t));
- if (ctx->high == NULL) {
- goto failed;
- }
+ ctx->ranges = 1;
rv = NGX_CONF_OK;
@@ -435,20 +478,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
if (ngx_strcmp(value[0].data, "include") == 0) {
- file.len = value[1].len++;
-
- file.data = ngx_pstrdup(ctx->temp_pool, &value[1]);
- if (file.data == NULL) {
- goto failed;
- }
-
- if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK){
- goto failed;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
-
- rv = ngx_conf_parse(cf, &file);
+ rv = ngx_http_geo_include(cf, ctx, &value[1]);
goto done;
@@ -463,7 +493,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
goto done;
}
- if (ctx->high) {
+ if (ctx->ranges) {
rv = ngx_http_geo_range(cf, ctx, value);
} else {
@@ -488,30 +518,45 @@ static char *
ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_str_t *value)
{
- u_char *p, *last;
- in_addr_t start, end;
- ngx_str_t *net;
- ngx_uint_t del;
- ngx_http_variable_value_t *old;
+ u_char *p, *last;
+ in_addr_t start, end;
+ ngx_str_t *net;
+ ngx_uint_t del;
if (ngx_strcmp(value[0].data, "default") == 0) {
- old = ctx->high->default_value;
-
- ctx->high->default_value = ngx_http_geo_value(cf, ctx, &value[1]);
- if (ctx->high->default_value == NULL) {
- return NGX_CONF_ERROR;
+ if (ctx->high.default_value) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "duplicate default geo range value: \"%V\", old value: \"%v\"",
+ &value[1], ctx->high.default_value);
}
- if (old) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate range \"%V\", value: \"%v\", old value: \"%v\"",
- &value[0], ctx->high->default_value, old);
+ ctx->high.default_value = ngx_http_geo_value(cf, ctx, &value[1]);
+ if (ctx->high.default_value == NULL) {
+ return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
+ if (ctx->binary_include) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "binary geo range base \"%s\" may not be mixed with usual entries",
+ ctx->include_name.data);
+ return NGX_CONF_ERROR;
+ }
+
+ if (ctx->high.low == NULL) {
+ ctx->high.low = ngx_pcalloc(ctx->pool,
+ 0x10000 * sizeof(ngx_http_geo_range_t *));
+ if (ctx->high.low == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ ctx->entries++;
+ ctx->outside_entries = 1;
+
if (ngx_strcmp(value[0].data, "delete") == 0) {
net = &value[1];
del = 1;
@@ -606,7 +651,7 @@ ngx_http_geo_add_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
e = 0xffff;
}
- a = (ngx_array_t *) ctx->high->low[h].ranges;
+ a = (ngx_array_t *) ctx->high.low[h];
if (a == NULL) {
a = ngx_array_create(ctx->temp_pool, 64,
@@ -615,7 +660,7 @@ ngx_http_geo_add_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR;
}
- ctx->high->low[h].ranges = (ngx_http_geo_range_t *) a;
+ ctx->high.low[h] = (ngx_http_geo_range_t *) a;
}
i = a->nelts;
@@ -803,7 +848,7 @@ ngx_http_geo_delete_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
e = 0xffff;
}
- a = (ngx_array_t *) ctx->high->low[h].ranges;
+ a = (ngx_array_t *) ctx->high.low[h];
if (a == NULL) {
warn = 1;
@@ -929,16 +974,17 @@ static ngx_http_variable_value_t *
ngx_http_geo_value(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_str_t *value)
{
- uint32_t hash;
- ngx_http_variable_value_t *val;
- ngx_http_variable_value_node_t *vvn;
+ uint32_t hash;
+ ngx_http_variable_value_t *val;
+ ngx_http_geo_variable_value_node_t *gvvn;
hash = ngx_crc32_long(value->data, value->len);
- val = ngx_http_variable_value_lookup(&ctx->rbtree, value, hash);
+ gvvn = (ngx_http_geo_variable_value_node_t *)
+ ngx_str_rbtree_lookup(&ctx->rbtree, value, hash);
- if (val) {
- return val;
+ if (gvvn) {
+ return gvvn->value;
}
val = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t));
@@ -956,16 +1002,22 @@ ngx_http_geo_value(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
val->no_cacheable = 0;
val->not_found = 0;
- vvn = ngx_palloc(ctx->temp_pool, sizeof(ngx_http_variable_value_node_t));
- if (vvn == NULL) {
+ gvvn = ngx_palloc(ctx->temp_pool,
+ sizeof(ngx_http_geo_variable_value_node_t));
+ if (gvvn == NULL) {
return NULL;
}
- vvn->node.key = hash;
- vvn->len = val->len;
- vvn->value = val;
+ gvvn->sn.node.key = hash;
+ gvvn->sn.str.len = val->len;
+ gvvn->sn.str.data = val->data;
+ gvvn->value = val;
+ gvvn->offset = 0;
- ngx_rbtree_insert(&ctx->rbtree, &vvn->node);
+ ngx_rbtree_insert(&ctx->rbtree, &gvvn->sn.node);
+
+ ctx->data_size += ngx_align(sizeof(ngx_http_variable_value_t) + value->len,
+ sizeof(void *));
return val;
}
@@ -1030,3 +1082,335 @@ ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
return NGX_OK;
}
+
+
+static char *
+ngx_http_geo_include(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
+ ngx_str_t *name)
+{
+ char *rv;
+ ngx_str_t file;
+
+ file.len = name->len + 4;
+ file.data = ngx_pnalloc(ctx->temp_pool, name->len + 5);
+ if (file.data == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_sprintf(file.data, "%V.bin%Z", name);
+
+ if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ctx->ranges) {
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+
+ switch (ngx_http_geo_include_binary_base(cf, ctx, &file)) {
+ case NGX_OK:
+ return NGX_CONF_OK;
+ case NGX_ERROR:
+ return NGX_CONF_ERROR;
+ default:
+ break;
+ }
+ }
+
+ file.len -= 4;
+ file.data[file.len] = '\0';
+
+ ctx->include_name = file;
+
+ if (ctx->outside_entries) {
+ ctx->allow_binary_include = 0;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+
+ rv = ngx_conf_parse(cf, &file);
+
+ ctx->includes++;
+ ctx->outside_entries = 0;
+
+ return rv;
+}
+
+
+static ngx_int_t
+ngx_http_geo_include_binary_base(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
+ ngx_str_t *name)
+{
+ u_char *base, ch;
+ time_t mtime;
+ size_t size, len;
+ ssize_t n;
+ uint32_t crc32;
+ ngx_err_t err;
+ ngx_int_t rc;
+ ngx_uint_t i;
+ ngx_file_t file;
+ ngx_file_info_t fi;
+ ngx_http_geo_range_t *range, **ranges;
+ ngx_http_geo_header_t *header;
+ ngx_http_variable_value_t *vv;
+
+ ngx_memzero(&file, sizeof(ngx_file_t));
+ file.name = *name;
+ file.log = cf->log;
+
+ file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0);
+ if (file.fd == NGX_INVALID_FILE) {
+ err = ngx_errno;
+ if (err != NGX_ENOENT) {
+ ngx_conf_log_error(NGX_LOG_CRIT, cf, err,
+ ngx_open_file_n " \"%s\" failed", name->data);
+ }
+ return NGX_DECLINED;
+ }
+
+ if (ctx->outside_entries) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "binary geo range base \"%s\" may not be mixed with usual entries",
+ name->data);
+ rc = NGX_ERROR;
+ goto done;
+ }
+
+ if (ctx->binary_include) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "second binary geo range base \"%s\" may not be mixed with \"%s\"",
+ name->data, ctx->include_name.data);
+ rc = NGX_ERROR;
+ goto done;
+ }
+
+ if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
+ ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
+ ngx_fd_info_n " \"%s\" failed", name->data);
+ goto failed;
+ }
+
+ size = (size_t) ngx_file_size(&fi);
+ mtime = ngx_file_mtime(&fi);
+
+ ch = name->data[name->len - 4];
+ name->data[name->len - 4] = '\0';
+
+ if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
+ ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
+ ngx_file_info_n " \"%s\" failed", name->data);
+ goto failed;
+ }
+
+ name->data[name->len - 4] = ch;
+
+ if (mtime < ngx_file_mtime(&fi)) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "stale binary geo range base \"%s\"", name->data);
+ goto failed;
+ }
+
+ base = ngx_palloc(ctx->pool, size);
+ if (base == NULL) {
+ goto failed;
+ }
+
+ n = ngx_read_file(&file, base, size, 0);
+
+ if (n == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
+ ngx_read_file_n " \"%s\" failed", name->data);
+ goto failed;
+ }
+
+ if ((size_t) n != size) {
+ ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
+ ngx_read_file_n " \"%s\" returned only %z bytes instead of %z",
+ name->data, n, size);
+ goto failed;
+ }
+
+ header = (ngx_http_geo_header_t *) base;
+
+ if (size < 16 || ngx_memcmp(&ngx_http_geo_header, header, 12) != 0) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "incompatible binary geo range base \"%s\"", name->data);
+ goto failed;
+ }
+
+ ngx_crc32_init(crc32);
+
+ vv = (ngx_http_variable_value_t *) (base + sizeof(ngx_http_geo_header_t));
+
+ while(vv->data) {
+ len = ngx_align(sizeof(ngx_http_variable_value_t) + vv->len,
+ sizeof(void *));
+ ngx_crc32_update(&crc32, (u_char *) vv, len);
+ vv->data += (size_t) base;
+ vv = (ngx_http_variable_value_t *) ((u_char *) vv + len);
+ }
+ ngx_crc32_update(&crc32, (u_char *) vv, sizeof(ngx_http_variable_value_t));
+ vv++;
+
+ ranges = (ngx_http_geo_range_t **) vv;
+
+ for (i = 0; i < 0x10000; i++) {
+ ngx_crc32_update(&crc32, (u_char *) &ranges[i], sizeof(void *));
+ if (ranges[i]) {
+ ranges[i] = (ngx_http_geo_range_t *)
+ ((u_char *) ranges[i] + (size_t) base);
+ }
+ }
+
+ range = (ngx_http_geo_range_t *) &ranges[0x10000];
+
+ while ((u_char *) range < base + size) {
+ while (range->value) {
+ ngx_crc32_update(&crc32, (u_char *) range,
+ sizeof(ngx_http_geo_range_t));
+ range->value = (ngx_http_variable_value_t *)
+ ((u_char *) range->value + (size_t) base);
+ range++;
+ }
+ ngx_crc32_update(&crc32, (u_char *) range, sizeof(void *));
+ range = (ngx_http_geo_range_t *) ((u_char *) range + sizeof(void *));
+ }
+
+ ngx_crc32_final(crc32);
+
+ if (crc32 != header->crc32) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "CRC32 mismatch in binary geo range base \"%s\"", name->data);
+ goto failed;
+ }
+
+ ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
+ "using binary geo range base \"%s\"", name->data);
+
+ ctx->include_name = *name;
+ ctx->binary_include = 1;
+ ctx->high.low = ranges;
+ rc = NGX_OK;
+
+ goto done;
+
+failed:
+
+ rc = NGX_DECLINED;
+
+done:
+
+ if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", name->data);
+ }
+
+ return rc;
+}
+
+
+static void
+ngx_http_geo_create_binary_base(ngx_http_geo_conf_ctx_t *ctx)
+{
+ u_char *p;
+ uint32_t hash;
+ ngx_str_t s;
+ ngx_uint_t i;
+ ngx_file_mapping_t fm;
+ ngx_http_geo_range_t *r, *range, **ranges;
+ ngx_http_geo_header_t *header;
+ ngx_http_geo_variable_value_node_t *gvvn;
+
+ fm.name = ngx_pnalloc(ctx->temp_pool, ctx->include_name.len + 5);
+ if (fm.name == NULL) {
+ return;
+ }
+
+ ngx_sprintf(fm.name, "%V.bin%Z", &ctx->include_name);
+
+ fm.size = ctx->data_size;
+ fm.log = ctx->pool->log;
+
+ ngx_log_error(NGX_LOG_NOTICE, fm.log, 0,
+ "creating binary geo range base \"%s\"", fm.name);
+
+ if (ngx_create_file_mapping(&fm) != NGX_OK) {
+ return;
+ }
+
+ p = ngx_cpymem(fm.addr, &ngx_http_geo_header,
+ sizeof(ngx_http_geo_header_t));
+
+ p = ngx_http_geo_copy_values(fm.addr, p, ctx->rbtree.root,
+ ctx->rbtree.sentinel);
+
+ p += sizeof(ngx_http_variable_value_t);
+
+ ranges = (ngx_http_geo_range_t **) p;
+
+ p += 0x10000 * sizeof(ngx_http_geo_range_t *);
+
+ for (i = 0; i < 0x10000; i++) {
+ r = ctx->high.low[i];
+ if (r == NULL) {
+ continue;
+ }
+
+ range = (ngx_http_geo_range_t *) p;
+ ranges[i] = (ngx_http_geo_range_t *) (p - (u_char *) fm.addr);
+
+ do {
+ s.len = r->value->len;
+ s.data = r->value->data;
+ hash = ngx_crc32_long(s.data, s.len);
+ gvvn = (ngx_http_geo_variable_value_node_t *)
+ ngx_str_rbtree_lookup(&ctx->rbtree, &s, hash);
+
+ range->value = (ngx_http_variable_value_t *) gvvn->offset;
+ range->start = r->start;
+ range->end = r->end;
+ range++;
+
+ } while ((++r)->value);
+
+ range->value = NULL;
+
+ p = (u_char *) range + sizeof(void *);
+ }
+
+ header = fm.addr;
+ header->crc32 = ngx_crc32_long((u_char *) fm.addr
+ + sizeof(ngx_http_geo_header_t),
+ fm.size - sizeof(ngx_http_geo_header_t));
+
+ ngx_close_file_mapping(&fm);
+}
+
+
+static u_char *
+ngx_http_geo_copy_values(u_char *base, u_char *p, ngx_rbtree_node_t *node,
+ ngx_rbtree_node_t *sentinel)
+{
+ ngx_http_variable_value_t *vv;
+ ngx_http_geo_variable_value_node_t *gvvn;
+
+ if (node == sentinel) {
+ return p;
+ }
+
+ gvvn = (ngx_http_geo_variable_value_node_t *) node;
+ gvvn->offset = p - base;
+
+ vv = (ngx_http_variable_value_t *) p;
+ *vv = *gvvn->value;
+ p += sizeof(ngx_http_variable_value_t);
+ vv->data = (u_char *) (p - base);
+
+ p = ngx_cpymem(p, gvvn->sn.str.data, gvvn->sn.str.len);
+
+ p = ngx_align_ptr(p, sizeof(void *));
+
+ p = ngx_http_geo_copy_values(base, p, node->left, sentinel);
+
+ return ngx_http_geo_copy_values(base, p, node->right, sentinel);
+}
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index abdae0d3b..fe3fa7751 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -374,7 +374,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
if (ngx_strcmp(value[0].data, "include") == 0) {
file = value[1];
- if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK){
+ if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index b994711e7..45626c6b0 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -431,7 +431,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
while (ctx->in || ctx->buf) {
- if (ctx->buf == NULL ){
+ if (ctx->buf == NULL) {
ctx->buf = ctx->in->buf;
ctx->in = ctx->in->next;
ctx->pos = ctx->buf->pos;
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
index fe4d92717..d12ed8fe2 100644
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -210,7 +210,7 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
while (ctx->in || ctx->buf) {
- if (ctx->buf == NULL ){
+ if (ctx->buf == NULL) {
ctx->buf = ctx->in->buf;
ctx->in = ctx->in->next;
ctx->pos = ctx->buf->pos;
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index 17f0193f1..64811e41e 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -47,6 +47,8 @@ static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, ngx_str_t *name, uint32_t *uid);
static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
+static ngx_int_t ngx_http_userid_create_uid(ngx_http_request_t *r,
+ ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf);
static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf);
@@ -199,7 +201,7 @@ ngx_http_userid_filter(ngx_http_request_t *r)
conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
- if (conf->enable <= NGX_HTTP_USERID_LOG) {
+ if (conf->enable < NGX_HTTP_USERID_V1) {
return ngx_http_next_header_filter(r);
}
@@ -209,23 +211,6 @@ ngx_http_userid_filter(ngx_http_request_t *r)
return NGX_ERROR;
}
- if (ctx->uid_got[3] != 0) {
-
- if (conf->mark == '\0') {
- return ngx_http_next_header_filter(r);
-
- } else {
- if (ctx->cookie.len > 23
- && ctx->cookie.data[22] == conf->mark
- && ctx->cookie.data[23] == '=')
- {
- return ngx_http_next_header_filter(r);
- }
- }
- }
-
- /* ctx->status == NGX_DECLINED */
-
if (ngx_http_userid_set_uid(r, ctx, conf) == NGX_OK) {
return ngx_http_next_header_filter(r);
}
@@ -248,18 +233,16 @@ ngx_http_userid_got_variable(ngx_http_request_t *r,
return NGX_OK;
}
- ctx = ngx_http_userid_get_uid(r, conf);
+ ctx = ngx_http_userid_get_uid(r->main, conf);
if (ctx == NULL) {
return NGX_ERROR;
}
if (ctx->uid_got[3] != 0) {
- return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_got);
+ return ngx_http_userid_variable(r->main, v, &conf->name, ctx->uid_got);
}
- /* ctx->status == NGX_DECLINED */
-
v->not_found = 1;
return NGX_OK;
@@ -273,16 +256,29 @@ ngx_http_userid_set_variable(ngx_http_request_t *r,
ngx_http_userid_ctx_t *ctx;
ngx_http_userid_conf_t *conf;
- ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
+ conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module);
- if (ctx == NULL || ctx->uid_set[3] == 0) {
+ if (conf->enable < NGX_HTTP_USERID_V1) {
v->not_found = 1;
return NGX_OK;
}
- conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
+ ctx = ngx_http_userid_get_uid(r->main, conf);
+
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_http_userid_create_uid(r->main, ctx, conf) != NGX_OK) {
+ return NGX_ERROR;
+ }
- return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_set);
+ if (ctx->uid_set[3] == 0) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ return ngx_http_userid_variable(r->main, v, &conf->name, ctx->uid_set);
}
@@ -360,82 +356,17 @@ static ngx_int_t
ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
ngx_http_userid_conf_t *conf)
{
- u_char *cookie, *p;
- size_t len;
- ngx_str_t src, dst;
- ngx_table_elt_t *set_cookie, *p3p;
- ngx_connection_t *c;
- struct sockaddr_in *sin;
-#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin6;
-#endif
-
- /*
- * TODO: in the threaded mode the sequencers should be in TLS and their
- * ranges should be divided between threads
- */
-
- if (ctx->uid_got[3] == 0) {
-
- if (conf->enable == NGX_HTTP_USERID_V1) {
- if (conf->service == NGX_CONF_UNSET) {
- ctx->uid_set[0] = 0;
- } else {
- ctx->uid_set[0] = conf->service;
- }
- ctx->uid_set[1] = (uint32_t) ngx_time();
- ctx->uid_set[2] = start_value;
- ctx->uid_set[3] = sequencer_v1;
- sequencer_v1 += 0x100;
-
- } else {
- if (conf->service == NGX_CONF_UNSET) {
-
- c = r->connection;
-
- if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
- return NGX_ERROR;
- }
+ u_char *cookie, *p;
+ size_t len;
+ ngx_str_t src, dst;
+ ngx_table_elt_t *set_cookie, *p3p;
- switch (c->local_sockaddr->sa_family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
-
- p = (u_char *) &ctx->uid_set[0];
-
- *p++ = sin6->sin6_addr.s6_addr[12];
- *p++ = sin6->sin6_addr.s6_addr[13];
- *p++ = sin6->sin6_addr.s6_addr[14];
- *p = sin6->sin6_addr.s6_addr[15];
-
- break;
-#endif
- default: /* AF_INET */
- sin = (struct sockaddr_in *) c->local_sockaddr;
- ctx->uid_set[0] = sin->sin_addr.s_addr;
- break;
- }
-
- } else {
- ctx->uid_set[0] = htonl(conf->service);
- }
-
- ctx->uid_set[1] = htonl((uint32_t) ngx_time());
- ctx->uid_set[2] = htonl(start_value);
- ctx->uid_set[3] = htonl(sequencer_v2);
- sequencer_v2 += 0x100;
- if (sequencer_v2 < 0x03030302) {
- sequencer_v2 = 0x03030302;
- }
- }
+ if (ngx_http_userid_create_uid(r, ctx, conf) != NGX_OK) {
+ return NGX_ERROR;
+ }
- } else {
- ctx->uid_set[0] = ctx->uid_got[0];
- ctx->uid_set[1] = ctx->uid_got[1];
- ctx->uid_set[2] = ctx->uid_got[2];
- ctx->uid_set[3] = ctx->uid_got[3];
+ if (ctx->uid_set[3] == 0) {
+ return NGX_OK;
}
len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
@@ -518,6 +449,102 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
static ngx_int_t
+ngx_http_userid_create_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
+ ngx_http_userid_conf_t *conf)
+{
+ ngx_connection_t *c;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ struct sockaddr_in6 *sin6;
+#endif
+
+ if (ctx->uid_set[3] != 0) {
+ return NGX_OK;
+ }
+
+ if (ctx->uid_got[3] != 0) {
+
+ if (conf->mark == '\0'
+ || (ctx->cookie.len > 23
+ && ctx->cookie.data[22] == conf->mark
+ && ctx->cookie.data[23] == '='))
+ {
+ return NGX_OK;
+ }
+
+ ctx->uid_set[0] = ctx->uid_got[0];
+ ctx->uid_set[1] = ctx->uid_got[1];
+ ctx->uid_set[2] = ctx->uid_got[2];
+ ctx->uid_set[3] = ctx->uid_got[3];
+
+ return NGX_OK;
+ }
+
+ /*
+ * TODO: in the threaded mode the sequencers should be in TLS and their
+ * ranges should be divided between threads
+ */
+
+ if (conf->enable == NGX_HTTP_USERID_V1) {
+ if (conf->service == NGX_CONF_UNSET) {
+ ctx->uid_set[0] = 0;
+ } else {
+ ctx->uid_set[0] = conf->service;
+ }
+ ctx->uid_set[1] = (uint32_t) ngx_time();
+ ctx->uid_set[2] = start_value;
+ ctx->uid_set[3] = sequencer_v1;
+ sequencer_v1 += 0x100;
+
+ } else {
+ if (conf->service == NGX_CONF_UNSET) {
+
+ c = r->connection;
+
+ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ switch (c->local_sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
+
+ p = (u_char *) &ctx->uid_set[0];
+
+ *p++ = sin6->sin6_addr.s6_addr[12];
+ *p++ = sin6->sin6_addr.s6_addr[13];
+ *p++ = sin6->sin6_addr.s6_addr[14];
+ *p = sin6->sin6_addr.s6_addr[15];
+
+ break;
+#endif
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) c->local_sockaddr;
+ ctx->uid_set[0] = sin->sin_addr.s_addr;
+ break;
+ }
+
+ } else {
+ ctx->uid_set[0] = htonl(conf->service);
+ }
+
+ ctx->uid_set[1] = htonl((uint32_t) ngx_time());
+ ctx->uid_set[2] = htonl(start_value);
+ ctx->uid_set[3] = htonl(sequencer_v2);
+ sequencer_v2 += 0x100;
+ if (sequencer_v2 < 0x03030302) {
+ sequencer_v2 = 0x03030302;
+ }
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
ngx_str_t *name, uint32_t *uid)
{
@@ -550,7 +577,7 @@ ngx_http_userid_add_variables(ngx_conf_t *cf)
var->get_handler = ngx_http_userid_got_variable;
- var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH);
+ var = ngx_http_add_variable(cf, &ngx_http_userid_set, 0);
if (var == NULL) {
return NGX_ERROR;
}
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
index a06b26c28..a5c3da4c7 100644
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -268,7 +268,7 @@ ngx_http_xslt_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
if (ngx_http_xslt_add_chunk(r, ctx, cl->buf) != NGX_OK) {
- if (ctx->ctxt->myDoc){
+ if (ctx->ctxt->myDoc) {
#if (NGX_HTTP_XSLT_REUSE_DTD)
ctx->ctxt->myDoc->extSubset = NULL;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 0d2e349b6..500840249 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.8.42';
+our $VERSION = '0.8.43';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 984d30617..1654510be 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1748,6 +1748,7 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
r->headers_out.status = status;
if (status == NGX_HTTP_NO_CONTENT) {
+ r->header_only = 1;
return ngx_http_send_header(r);
}
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index a8687d0a6..bccf63624 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -170,6 +170,10 @@ ngx_http_header_filter(ngx_http_request_t *r)
#endif
u_char addr[NGX_SOCKADDR_STRLEN];
+ if (r->header_sent) {
+ return NGX_OK;
+ }
+
r->header_sent = 1;
if (r != r->main) {
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index f5be2f0e2..949006b47 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -272,7 +272,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
/* space* before URI */
case sw_spaces_before_uri:
- if (ch == '/' ){
+ if (ch == '/') {
r->uri_start = p;
state = sw_after_slash_in_uri;
break;
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index ec2405b96..01826668c 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -489,7 +489,6 @@ struct ngx_http_request_s {
unsigned plain_http:1;
unsigned chunked:1;
unsigned header_only:1;
- unsigned zero_body:1;
unsigned keepalive:1;
unsigned lingering_close:1;
unsigned discard_body:1;
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 7718d19a7..1b7eacec6 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -598,31 +598,24 @@ ngx_http_send_special_response(ngx_http_request_t *r,
msie_padding = 0;
- if (!r->zero_body) {
- if (ngx_http_error_pages[err].len) {
- r->headers_out.content_length_n = ngx_http_error_pages[err].len
- + len;
- if (clcf->msie_padding
- && (r->headers_in.msie || r->headers_in.chrome)
- && r->http_version >= NGX_HTTP_VERSION_10
- && err >= NGX_HTTP_LEVEL_300)
- {
- r->headers_out.content_length_n +=
- sizeof(ngx_http_msie_padding) - 1;
- msie_padding = 1;
- }
-
- r->headers_out.content_type_len = sizeof("text/html") - 1;
- ngx_str_set(&r->headers_out.content_type, "text/html");
- r->headers_out.content_type_lowcase = NULL;
-
- } else {
- r->headers_out.content_length_n = -1;
+ if (ngx_http_error_pages[err].len) {
+ r->headers_out.content_length_n = ngx_http_error_pages[err].len + len;
+ if (clcf->msie_padding
+ && (r->headers_in.msie || r->headers_in.chrome)
+ && r->http_version >= NGX_HTTP_VERSION_10
+ && err >= NGX_HTTP_LEVEL_300)
+ {
+ r->headers_out.content_length_n +=
+ sizeof(ngx_http_msie_padding) - 1;
+ msie_padding = 1;
}
+ r->headers_out.content_type_len = sizeof("text/html") - 1;
+ ngx_str_set(&r->headers_out.content_type, "text/html");
+ r->headers_out.content_type_lowcase = NULL;
+
} else {
- r->headers_out.content_length_n = 0;
- err = 0;
+ r->headers_out.content_length_n = -1;
}
if (r->headers_out.content_length) {
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 0bba28128..00d9d5eb4 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -1973,87 +1973,3 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
return NGX_OK;
}
-
-
-void
-ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t *temp,
- ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
-{
- ngx_rbtree_node_t **p;
- ngx_http_variable_value_node_t *vvn, *vvt;
-
- for ( ;; ) {
-
- vvn = (ngx_http_variable_value_node_t *) node;
- vvt = (ngx_http_variable_value_node_t *) temp;
-
- if (node->key != temp->key) {
-
- p = (node->key < temp->key) ? &temp->left : &temp->right;
-
- } else if (vvn->len != vvt->len) {
-
- p = (vvn->len < vvt->len) ? &temp->left : &temp->right;
-
- } else {
- p = (ngx_memcmp(vvn->value->data, vvt->value->data, vvn->len) < 0)
- ? &temp->left : &temp->right;
- }
-
- if (*p == sentinel) {
- break;
- }
-
- temp = *p;
- }
-
- *p = node;
- node->parent = temp;
- node->left = sentinel;
- node->right = sentinel;
- ngx_rbt_red(node);
-}
-
-
-ngx_http_variable_value_t *
-ngx_http_variable_value_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val,
- uint32_t hash)
-{
- ngx_int_t rc;
- ngx_rbtree_node_t *node, *sentinel;
- ngx_http_variable_value_node_t *vvn;
-
- node = rbtree->root;
- sentinel = rbtree->sentinel;
-
- while (node != sentinel) {
-
- vvn = (ngx_http_variable_value_node_t *) node;
-
- if (hash != node->key) {
- node = (hash < node->key) ? node->left : node->right;
- continue;
- }
-
- if (val->len != vvn->len) {
- node = (val->len < vvn->len) ? node->left : node->right;
- continue;
- }
-
- rc = ngx_memcmp(val->data, vvn->value->data, val->len);
-
- if (rc < 0) {
- node = node->left;
- continue;
- }
-
- if (rc > 0) {
- node = node->right;
- continue;
- }
-
- return vvn->value;
- }
-
- return NULL;
-}
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
index 9d4b29e08..588f5caf5 100644
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -88,19 +88,6 @@ ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf);
ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf);
-typedef struct {
- ngx_rbtree_node_t node;
- size_t len;
- ngx_http_variable_value_t *value;
-} ngx_http_variable_value_node_t;
-
-
-void ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t *temp,
- ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
-ngx_http_variable_value_t *ngx_http_variable_value_lookup(ngx_rbtree_t *rbtree,
- ngx_str_t *name, uint32_t hash);
-
-
extern ngx_http_variable_value_t ngx_http_variable_null_value;
extern ngx_http_variable_value_t ngx_http_variable_true_value;
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 9cc6a0787..0e37daf48 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -346,7 +346,7 @@ ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
#endif
plain.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
- if (plain.data == NULL){
+ if (plain.data == NULL) {
return NGX_ERROR;
}
@@ -403,7 +403,7 @@ ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c,
"mail auth login username: \"%V\"", &arg[n]);
s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
- if (s->login.data == NULL){
+ if (s->login.data == NULL) {
return NGX_ERROR;
}
@@ -434,7 +434,7 @@ ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c)
s->passwd.data = ngx_pnalloc(c->pool,
ngx_base64_decoded_length(arg[0].len));
- if (s->passwd.data == NULL){
+ if (s->passwd.data == NULL) {
return NGX_ERROR;
}
@@ -494,7 +494,7 @@ ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c)
"mail auth cram-md5: \"%V\"", &arg[0]);
s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len));
- if (s->login.data == NULL){
+ if (s->login.data == NULL) {
return NGX_ERROR;
}
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
index 0ef083824..c50e2014b 100644
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -76,7 +76,7 @@ ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
#if (NGX_HAVE_PWRITE)
for ( ;; ) {
- n = pwrite(file->fd, buf, size, offset);
+ n = pwrite(file->fd, buf + written, size, offset);
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
@@ -108,7 +108,7 @@ ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
}
for ( ;; ) {
- n = write(file->fd, buf, size);
+ n = write(file->fd, buf + written, size);
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
@@ -259,6 +259,58 @@ ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
ngx_int_t
+ngx_create_file_mapping(ngx_file_mapping_t *fm)
+{
+ fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
+ NGX_FILE_DEFAULT_ACCESS);
+ if (fm->fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
+ ngx_open_file_n " \"%s\" failed", fm->name);
+ return NGX_ERROR;
+ }
+
+ if (ftruncate(fm->fd, fm->size) == -1) {
+ ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
+ "ftruncate() \"%s\" failed", fm->name);
+ goto failed;
+ }
+
+ fm->addr = mmap(NULL, fm->size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ fm->fd, 0);
+ if (fm->addr != MAP_FAILED) {
+ return NGX_OK;
+ }
+
+ ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
+ "mmap(%uz) \"%s\" failed", fm->size, fm->name);
+
+failed:
+
+ if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", fm->name);
+ }
+
+ return NGX_ERROR;
+}
+
+
+void
+ngx_close_file_mapping(ngx_file_mapping_t *fm)
+{
+ if (munmap(fm->addr, fm->size) == -1) {
+ ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
+ "munmap(%uz) \"%s\" failed", fm->size, fm->name);
+ }
+
+ if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", fm->name);
+ }
+}
+
+
+ngx_int_t
ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
{
dir->dir = opendir((const char *) name->data);
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
index c40cfe2ea..b7bfff100 100644
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -18,6 +18,15 @@ typedef ino_t ngx_file_uniq_t;
typedef struct {
+ u_char *name;
+ size_t size;
+ void *addr;
+ ngx_fd_t fd;
+ ngx_log_t *log;
+} ngx_file_mapping_t;
+
+
+typedef struct {
DIR *dir;
struct dirent *de;
struct stat info;
@@ -152,6 +161,10 @@ ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
#define ngx_file_uniq(sb) (sb)->st_ino
+ngx_int_t ngx_create_file_mapping(ngx_file_mapping_t *fm);
+void ngx_close_file_mapping(ngx_file_mapping_t *fm);
+
+
#if (NGX_HAVE_CASELESS_FILESYSTEM)
#define ngx_filename_cmp(s1, s2, n) strncasecmp((char *) s1, (char *) s2, n)
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index f2dd82c89..b65a0d7b8 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -158,7 +158,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
rev->ready = 0;
- if (n == NGX_ERROR){
+ if (n == NGX_ERROR) {
c->read->error = 1;
}
@@ -247,7 +247,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
rev->ready = 0;
- if (n == NGX_ERROR){
+ if (n == NGX_ERROR) {
c->read->error = 1;
}
diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c
index f4d6a2bcc..316e0516d 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -113,7 +113,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
rev->ready = 0;
- if (n == NGX_ERROR){
+ if (n == NGX_ERROR) {
rev->error = 1;
}
@@ -169,7 +169,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
rev->ready = 0;
- if (n == NGX_ERROR){
+ if (n == NGX_ERROR) {
rev->error = 1;
}
diff --git a/src/os/unix/ngx_udp_recv.c b/src/os/unix/ngx_udp_recv.c
index 25f0738ac..fdcd7fa79 100644
--- a/src/os/unix/ngx_udp_recv.c
+++ b/src/os/unix/ngx_udp_recv.c
@@ -60,7 +60,7 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
rev->ready = 0;
- if (n == NGX_ERROR){
+ if (n == NGX_ERROR) {
rev->error = 1;
}
@@ -104,7 +104,7 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
rev->ready = 0;
- if (n == NGX_ERROR){
+ if (n == NGX_ERROR) {
rev->error = 1;
}