nginx-0.1.36-RELEASE import
*) Change: if the request header has duplicate the "Host",
"Connection", "Content-Length", or "Authorization" lines, then nginx
now returns the 400 error.
*) Change: the "post_accept_timeout" directive was canceled.
*) Feature: the "default", "af=", "bl=", "deferred", and "bind"
parameters of the "listen" directive.
*) Feature: the FreeBSD accept filters support.
*) Feature: the Linux TCP_DEFER_ACCEPT support.
*) Bugfix: the ngx_http_autoindex_module did not support the file names
in UTF-8.
*) Bugfix: the new log file can be rotated by the -USR1 signal only if
the reconfiguration by the -HUP signal was made twice.
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 4a01acd..d04d954 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -301,6 +301,8 @@
return NGX_ERROR;
}
+ ngx_memzero(ls, sizeof(ngx_listening_t));
+
ls->fd = (ngx_socket_t) s;
}
}
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 94b6da3..4e9ff79 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.1.35"
+#define NGINX_VER "nginx/0.1.36"
#define NGINX_VAR "NGINX"
#define NGX_NEWPID_EXT ".newbin"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index ff9c164..b873db2 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -62,10 +62,18 @@
ngx_int_t
ngx_set_inherited_sockets(ngx_cycle_t *cycle)
{
- size_t len;
- ngx_uint_t i;
- ngx_listening_t *ls;
- struct sockaddr_in *sin;
+ size_t len;
+ ngx_uint_t i;
+ ngx_listening_t *ls;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ socklen_t aflen;
+ struct accept_filter_arg af;
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ socklen_t tlen;
+ int timeout;
+#endif
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
@@ -98,7 +106,6 @@
ls[i].addr_text_max_len = INET_ADDRSTRLEN;
-
ls[i].addr_text.data = ngx_palloc(cycle->pool, INET_ADDRSTRLEN - 1
+ sizeof(":65535") - 1);
if (ls[i].addr_text.data == NULL) {
@@ -115,6 +122,54 @@
ls[i].addr_text.len = ngx_sprintf(ls[i].addr_text.data + len, ":%d",
ntohs(sin->sin_port))
- ls[i].addr_text.data;
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+
+ ngx_memzero(&af, sizeof(struct accept_filter_arg));
+ aflen = sizeof(struct accept_filter_arg);
+
+ if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &aflen)
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
+ "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
+ &ls[i].addr_text);
+ continue;
+ }
+
+ if (aflen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
+ continue;
+ }
+
+ ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
+ if (ls[i].accept_filter == NULL) {
+ return NGX_ERROR;
+ }
+
+ (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
+ (u_char *) af.af_name, 16);
+#endif
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+
+ timeout = 0;
+ tlen = sizeof(int);
+
+ if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &tlen)
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
+ "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
+ &ls[i].addr_text);
+ continue;
+ }
+
+ if (tlen < sizeof(int) || timeout == 0) {
+ continue;
+ }
+
+ ls[i].deferred_accept = 1;
+#endif
}
return NGX_OK;
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 8fb6705..0224d98 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -47,11 +47,17 @@
unsigned nonblocking_accept:1;
unsigned nonblocking:1;
unsigned shared:1; /* shared between threads or processes */
+ unsigned addr_ntop:1;
+
#if (NGX_HAVE_DEFERRED_ACCEPT)
unsigned deferred_accept:1;
+ unsigned delete_deferred:1;
+ unsigned add_deferred:1;
+#ifdef SO_ACCEPTFILTER
+ char *accept_filter;
+#endif
#endif
- unsigned addr_ntop:1;
} ngx_listening_t;
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 3a1c00e..5780643 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -39,18 +39,24 @@
ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
{
- void *rv;
- ngx_uint_t i, n, failed;
- ngx_log_t *log;
- ngx_conf_t conf;
- ngx_pool_t *pool;
- ngx_cycle_t *cycle, **old;
- ngx_socket_t fd;
- ngx_list_part_t *part;
- ngx_open_file_t *file;
- ngx_listening_t *ls, *nls;
- ngx_core_conf_t *ccf;
- ngx_core_module_t *module;
+ void *rv;
+ ngx_uint_t i, n, failed;
+ ngx_log_t *log;
+ ngx_conf_t conf;
+ ngx_pool_t *pool;
+ ngx_cycle_t *cycle, **old;
+ ngx_socket_t fd;
+ ngx_list_part_t *part;
+ ngx_open_file_t *file;
+ ngx_listening_t *ls, *nls;
+ ngx_core_conf_t *ccf;
+ ngx_core_module_t *module;
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ struct accept_filter_arg af;
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ int timeout;
+#endif
log = old_cycle->log;
@@ -307,7 +313,7 @@
}
if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr)
- == NGX_OK)
+ == NGX_OK)
{
fd = ls[i].fd;
#if (NGX_WIN32)
@@ -330,8 +336,44 @@
}
nls[n].fd = ls[i].fd;
- nls[i].remain = 1;
+ nls[n].remain = 1;
ls[i].remain = 1;
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+
+ /*
+ * FreeBSD, except the most recent versions,
+ * can not remove accept filter
+ */
+ nls[n].deferred_accept = ls[i].deferred_accept;
+
+ if (ls[i].accept_filter && nls[n].accept_filter) {
+ if (ngx_strcmp(ls[i].accept_filter,
+ nls[n].accept_filter) != 0)
+ {
+ nls[n].delete_deferred = 1;
+ nls[n].add_deferred = 1;
+ }
+
+ } else if (ls[i].accept_filter) {
+ nls[n].delete_deferred = 1;
+
+ } else if (nls[n].accept_filter) {
+ nls[n].add_deferred = 1;
+ }
+#endif
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+
+ if (ls[n].deferred_accept && !nls[n].deferred_accept) {
+ nls[n].delete_deferred = 1;
+
+ } else if (ls[i].deferred_accept
+ != nls[n].deferred_accept)
+ {
+ nls[n].add_deferred = 1;
+ }
+#endif
break;
}
}
@@ -345,6 +387,16 @@
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
ls[i].open = 1;
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ if (ls[i].accept_filter) {
+ ls[i].add_deferred = 1;
+ }
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ if (ls[i].deferred_accept) {
+ ls[i].add_deferred = 1;
+ }
+#endif
}
}
@@ -352,6 +404,81 @@
if (ngx_open_listening_sockets(cycle) == NGX_ERROR) {
failed = 1;
}
+
+#if (NGX_HAVE_DEFERRED_ACCEPT)
+
+ if (!failed) {
+ ls = cycle->listening.elts;
+ for (i = 0; i < cycle->listening.nelts; i++) {
+
+#ifdef SO_ACCEPTFILTER
+ if (ls[i].delete_deferred) {
+ if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
+ NULL, 0) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ "setsockopt(SO_ACCEPTFILTER, NULL) "
+ "for %V failed, ignored",
+ &ls[i].addr_text);
+
+ if (ls[i].accept_filter) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "could not change the accept filter "
+ "to \"%s\" for %V, ignored",
+ ls[i].accept_filter, &ls[i].addr_text);
+ }
+
+ continue;
+ }
+
+ ls[i].deferred_accept = 0;
+ }
+
+ if (ls[i].add_deferred) {
+ ngx_memzero(&af, sizeof(struct accept_filter_arg));
+ (void) ngx_cpystrn((u_char *) af.af_name,
+ (u_char *) ls[i].accept_filter, 16);
+
+ if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
+ &af, sizeof(struct accept_filter_arg)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ "setsockopt(SO_ACCEPTFILTER, \"%s\") "
+ "for %V failed, ignored",
+ ls[i].accept_filter, &ls[i].addr_text);
+ continue;
+ }
+
+ ls[i].deferred_accept = 1;
+ }
+#endif
+
+#ifdef TCP_DEFER_ACCEPT
+ if (ls[i].add_deferred || ls[i].delete_deferred) {
+ timeout = 0;
+
+ if (ls[i].add_deferred) {
+ timeout = (int) (ls[i].post_accept_timeout / 1000);
+ }
+
+ if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
+ &timeout, sizeof(int)) == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ "setsockopt(TCP_DEFER_ACCEPT, %d) "
+ "for %V failed, ignored",
+ timeout, &ls[i].addr_text);
+ continue;
+ }
+ }
+
+ if (ls[i].add_deferred) {
+ ls[i].deferred_accept = 1;
+ }
+#endif
+ }
+ }
+#endif
}
}
@@ -682,6 +809,7 @@
break;
}
part = part->next;
+ file = part->elts;
i = 0;
}
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index acc4bd3..9cbf3c9 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -728,6 +728,35 @@
}
+size_t
+ngx_utf_length(ngx_str_t *utf)
+{
+ u_char c;
+ size_t len;
+ ngx_uint_t i;
+
+ for (len = 0, i = 0; i < utf->len; len++, i++) {
+
+ c = utf->data[i];
+
+ if (c < 0x80) {
+ continue;
+ }
+
+ if (c < 0xC0) {
+ /* invalid utf */
+ return utf->len;
+ }
+
+ for (c <<= 1; c & 0x80; c <<= 1) {
+ i++;
+ }
+ }
+
+ return len;
+}
+
+
uintptr_t
ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
{
@@ -792,30 +821,8 @@
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ };
- /* " ", """, "%", "'", %00-%1F, %7F-%FF */
-
- static uint32_t utf[] =
- { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
-
- /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x800000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */
-
- /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
-
- /* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
-
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
- 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
- 0x00000000 /* 0000 0000 0000 0000 0000 0000 0000 0000 */ };
-
switch (type) {
- case NGX_ESCAPE_UTF:
- escape = utf;
- break;
case NGX_ESCAPE_HTML:
escape = html;
break;
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index e2e20e1..ff21619 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -96,11 +96,11 @@
void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
+size_t ngx_utf_length(ngx_str_t *utf);
#define NGX_ESCAPE_URI 0
#define NGX_ESCAPE_ARGS 1
#define NGX_ESCAPE_HTML 2
-#define NGX_ESCAPE_UTF 3
uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
ngx_uint_t type);