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);
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index e312533..0c21e72 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -247,6 +247,9 @@
if (ev->deferred_accept) {
rev->ready = 1;
+#if (NGX_HAVE_KQUEUE)
+ rev->available = 1;
+#endif
}
c->ctx = ls->ctx;
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index 96ab81e..ab4418f 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -217,6 +217,16 @@
return ngx_http_autoindex_error(r, &dir, dname.data);
}
+ r->headers_out.status = NGX_HTTP_OK;
+ r->headers_out.content_type.len = sizeof("text/html") - 1;
+ r->headers_out.content_type.data = (u_char *) "text/html";
+
+ rc = ngx_http_send_header(r);
+
+ if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+ return rc;
+ }
+
fname.len = 0;
#if (NGX_SUPPRESS_WARN)
fname.data = NULL;
@@ -334,6 +344,10 @@
+ sizeof(" 28-Sep-1970 12:00 ") - 1
+ 19
+ 2;
+
+ if (r->utf8) {
+ len += entry[i].name.len - ngx_utf_length(&entry[i].name);
+ }
}
b = ngx_create_temp_buf(r->pool, len);
@@ -380,7 +394,11 @@
b->last = ngx_cpystrn(b->last, entry[i].name.data,
NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
- len = entry[i].name.len;
+ if (r->utf8) {
+ len = ngx_utf_length(&entry[i].name);
+ } else {
+ len = entry[i].name.len;
+ }
if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
b->last = ngx_cpymem(b->last - 3, "..></a>",
@@ -426,17 +444,6 @@
b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = b->last - b->pos;
- r->headers_out.content_type.len = sizeof("text/html") - 1;
- r->headers_out.content_type.data = (u_char *) "text/html";
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
if (r->main == NULL) {
b->last_buf = 1;
}
diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
index 0c76a5f..117281c 100644
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -12,15 +12,17 @@
typedef struct {
char **tables;
ngx_str_t name;
- ngx_uint_t server; /* unsigned server:1; */
+
+ unsigned server:1;
+ unsigned utf8:1;
} ngx_http_charset_t;
typedef struct {
- ngx_int_t src;
- ngx_int_t dst;
- char *src2dst;
- char *dst2src;
+ ngx_int_t src;
+ ngx_int_t dst;
+ char *src2dst;
+ char *dst2src;
} ngx_http_charset_tables_t;
@@ -31,17 +33,17 @@
typedef struct {
- ngx_flag_t enable;
- ngx_flag_t autodetect;
+ ngx_flag_t enable;
+ ngx_flag_t autodetect;
- ngx_int_t default_charset;
- ngx_int_t source_charset;
+ ngx_int_t default_charset;
+ ngx_int_t source_charset;
} ngx_http_charset_loc_conf_t;
typedef struct {
- ngx_int_t server;
- ngx_int_t client;
+ ngx_int_t server;
+ ngx_int_t client;
} ngx_http_charset_ctx_t;
@@ -183,6 +185,7 @@
charsets = mcf->charsets.elts;
r->headers_out.charset = charsets[lcf->default_charset].name;
+ r->utf8 = charsets[lcf->default_charset].utf8;
if (lcf->default_charset == lcf->source_charset) {
return ngx_http_next_header_filter(r);
@@ -448,6 +451,10 @@
c->name = *name;
c->server = 0;
+ if (ngx_strcasecmp(name->data, "utf-8") == 0) {
+ c->utf8 = 1;
+ }
+
return i;
}
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 0fb0575..0f6f2f1 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -66,8 +66,9 @@
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;
- ngx_uint_t port_found, addr_found, virtual_names, key;
+ 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;
ngx_conf_t pcf;
ngx_array_t in_ports;
ngx_listening_t *ls;
@@ -408,9 +409,9 @@
* for this address:port
*/
- if (lscf[l].default_server) {
+ if (lscf[l].conf.default_server) {
- if (in_addr[a].default_server) {
+ if (in_addr[a].conf.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);
@@ -419,7 +420,7 @@
}
in_addr[a].core_srv_conf = cscfp[s];
- in_addr[a].default_server = 1;
+ in_addr[a].conf.default_server = 1;
}
addr_found = 1;
@@ -449,8 +450,8 @@
in_addr[a].names.elts = NULL;
in_addr[a].hash = NULL;
in_addr[a].wildcards.elts = NULL;
- in_addr[a].default_server = lscf[l].default_server;
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)
@@ -518,6 +519,8 @@
in_port = in_ports.elts;
for (p = 0; p < in_ports.nelts; p++) {
+ separate_binding = 0;
+
/*
* check whether all name-based servers have the same configuraiton
* as the default server, or some servers restrict the host names
@@ -526,6 +529,10 @@
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;
@@ -608,7 +615,7 @@
* to the "*:port" only and ignore the other bindings
*/
- if (in_addr[a - 1].addr == INADDR_ANY) {
+ if (in_addr[a - 1].addr == INADDR_ANY && !separate_binding) {
a--;
} else {
@@ -624,15 +631,13 @@
return NGX_CONF_ERROR;
}
- ls->backlog = -1;
-
ls->addr_ntop = 1;
ls->handler = ngx_http_init_connection;
cscf = in_addr[a].core_srv_conf;
ls->pool_size = cscf->connection_pool_size;
- ls->post_accept_timeout = cscf->post_accept_timeout;
+ ls->post_accept_timeout = cscf->client_header_timeout;
clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
ls->log = clcf->err_log;
@@ -644,6 +649,16 @@
}
#endif
+ ls->backlog = in_addr[a].conf.backlog;
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ ls->accept_filter = in_addr[a].conf.accept_filter;
+#endif
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ ls->deferred_accept = in_addr[a].conf.deferred_accept;
+#endif
+
ls->ctx = ctx;
if (in_port[p].addrs.nelts > 1) {
@@ -766,8 +781,8 @@
in_addr->names.elts = NULL;
in_addr->hash = NULL;
in_addr->wildcards.elts = NULL;
- in_addr->default_server = lscf->default_server;
in_addr->core_srv_conf = cscf;
+ in_addr->conf = lscf->conf;
#if (NGX_DEBUG)
{
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 0279579..1d39970 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -102,13 +102,6 @@
offsetof(ngx_http_core_srv_conf_t, connection_pool_size),
NULL },
- { ngx_string("post_accept_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_core_srv_conf_t, post_accept_timeout),
- NULL },
-
{ ngx_string("request_pool_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
@@ -160,9 +153,9 @@
{ ngx_string("listen"),
#if 0
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
#else
- NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
+ NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
#endif
ngx_http_core_listen,
NGX_HTTP_SRV_CONF_OFFSET,
@@ -1592,7 +1585,6 @@
}
cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
- cscf->post_accept_timeout = NGX_CONF_UNSET_MSEC;
cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
@@ -1621,6 +1613,8 @@
return NGX_CONF_ERROR;
}
+ ngx_memzero(ls, sizeof(ngx_http_listen_t));
+
ls->addr = INADDR_ANY;
#if (NGX_WIN32)
ls->port = 80;
@@ -1629,7 +1623,6 @@
ls->port = (getuid() == 0) ? 80 : 8000;
#endif
ls->family = AF_INET;
- ls->default_server = 0;
}
if (conf->server_names.nelts == 0) {
@@ -1662,8 +1655,6 @@
ngx_conf_merge_size_value(conf->connection_pool_size,
prev->connection_pool_size, 256);
- ngx_conf_merge_msec_value(conf->post_accept_timeout,
- prev->post_accept_timeout, 60000);
ngx_conf_merge_size_value(conf->request_pool_size,
prev->request_pool_size, 4096);
ngx_conf_merge_msec_value(conf->client_header_timeout,
@@ -1859,89 +1850,145 @@
}
+/* AF_INET only */
+
static char *
ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_srv_conf_t *scf = conf;
- u_char *addr;
- ngx_int_t port;
- ngx_uint_t p;
- ngx_str_t *args;
- struct hostent *h;
- ngx_http_listen_t *ls;
+ char *err;
+ ngx_str_t *value;
+ ngx_uint_t n;
+ struct hostent *h;
+ ngx_http_listen_t *ls;
+ ngx_inet_upstream_t inet_upstream;
/*
* TODO: check duplicate 'listen' directives,
* add resolved name to server names ???
*/
+ value = cf->args->elts;
+
+ ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
+
+ inet_upstream.url = value[1];
+ inet_upstream.port_only = 1;
+
+ err = ngx_inet_parse_host_port(&inet_upstream);
+
+ if (err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%s in \"%V\" of the \"listen\" directive",
+ err, &inet_upstream.url);
+ return NGX_CONF_ERROR;
+ }
+
ls = ngx_array_push(&scf->listen);
if (ls == NULL) {
return NGX_CONF_ERROR;
}
- /* AF_INET only */
+ ngx_memzero(ls, sizeof(ngx_http_listen_t));
ls->family = AF_INET;
+ ls->port = (in_port_t) (inet_upstream.default_port ?
+ 80 : inet_upstream.port);
ls->file_name = cf->conf_file->file.name;
ls->line = cf->conf_file->line;
- ls->default_server = 0;
+ ls->conf.backlog = -1;
- args = cf->args->elts;
- addr = args[1].data;
+ if (inet_upstream.host.len) {
+ inet_upstream.host.data[inet_upstream.host.len] = '\0';
- for (p = 0; p < args[1].len; p++) {
- if (addr[p] == ':') {
- addr[p++] = '\0';
- break;
+ ls->addr = inet_addr((const char *) inet_upstream.host.data);
+
+ if (ls->addr == INADDR_NONE) {
+ h = gethostbyname((const char *) inet_upstream.host.data);
+
+ if (h == NULL || h->h_addr_list[0] == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "can not resolve host \"%s\" "
+ "in the \"listen\" directive",
+ inet_upstream.host.data);
+ return NGX_CONF_ERROR;
+ }
+
+ ls->addr = *(in_addr_t *)(h->h_addr_list[0]);
}
- }
-
- if (p == args[1].len) {
- /* no ":" in the "listen" */
- p = 0;
- }
-
- port = ngx_atoi(&addr[p], args[1].len - p);
-
- if (port == NGX_ERROR && p == 0) {
-
- /* "listen host" */
- ls->port = 80;
-
- } else if ((port == NGX_ERROR && p != 0) /* "listen host:NONNUMBER" */
- || (port < 1 || port > 65536)) { /* "listen 99999" */
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid port \"%s\" in \"%V\" directive, "
- "it must be a number between 1 and 65535",
- &addr[p], &cmd->name);
-
- return NGX_CONF_ERROR;
-
- } else if (p == 0) {
- ls->addr = INADDR_ANY;
- ls->port = (in_port_t) port;
- return NGX_CONF_OK;
} else {
- ls->port = (in_port_t) port;
+ ls->addr = INADDR_ANY;
}
- ls->addr = inet_addr((const char *) addr);
+ if (cf->args->nelts == 2) {
+ return NGX_CONF_OK;
+ }
- if (ls->addr == INADDR_NONE) {
- h = gethostbyname((const char *) addr);
+ if (ngx_strcmp(value[2].data, "default") == 0) {
+ ls->conf.default_server = 1;
+ n = 3;
+ } else {
+ n = 2;
+ }
- if (h == NULL || h->h_addr_list[0] == NULL) {
+ for ( /* void */ ; n < cf->args->nelts; n++) {
+
+ if (ls->conf.default_server == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "can not resolve host \"%s\" "
- "in \"%V\" directive", addr, &cmd->name);
+ "\"%V\" parameter can be specified for "
+ "the default \"listen\" directive only",
+ &value[n]);
return NGX_CONF_ERROR;
}
- ls->addr = *(in_addr_t *)(h->h_addr_list[0]);
+ if (ngx_strcmp(value[n].data, "bind") == 0) {
+ ls->conf.bind = 1;
+ continue;
+ }
+
+ if (ngx_strncmp(value[n].data, "bl=", 3) == 0) {
+ ls->conf.backlog = ngx_atoi(value[n].data + 3, value[n].len - 3);
+ ls->conf.bind = 1;
+
+ if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid backlog \"%V\"", &value[n]);
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+
+ if (ngx_strncmp(value[n].data, "af=", 3) == 0) {
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ ls->conf.accept_filter = (char *) &value[n].data[3];
+ ls->conf.bind = 1;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "accept filters \"%V\" are not supported "
+ "on this platform, ignored",
+ &value[n]);
+#endif
+ continue;
+ }
+
+ if (ngx_strcmp(value[n].data, "deferred") == 0) {
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ ls->conf.deferred_accept = 1;
+ ls->conf.bind = 1;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the deferred accept is not supported "
+ "on this platform, ignored");
+#endif
+ continue;
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the invalid \"%V\" parameter", &value[n]);
+ return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 14090b9..1164046 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -14,13 +14,30 @@
typedef struct {
+ unsigned default_server:1;
+ unsigned bind:1;
+
+ int backlog;
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ char *accept_filter;
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ ngx_uint_t deferred_accept;
+#endif
+
+} ngx_http_listen_conf_t;
+
+
+typedef struct {
in_addr_t addr;
in_port_t port;
int family;
+
ngx_str_t file_name;
ngx_int_t line;
- ngx_uint_t default_server; /* unsigned default_server:1; */
+ ngx_http_listen_conf_t conf;
} ngx_http_listen_t;
@@ -83,7 +100,6 @@
ngx_bufs_t large_client_header_buffers;
- ngx_msec_t post_accept_timeout;
ngx_msec_t client_header_timeout;
ngx_uint_t restrict_host_names;
@@ -111,7 +127,7 @@
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *core_srv_conf;
- ngx_uint_t default_server; /* unsigned default_server:1; */
+ ngx_http_listen_conf_t conf;
};
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index f04c17f..c3e1ab7 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -22,6 +22,8 @@
static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
@@ -62,10 +64,10 @@
ngx_http_header_t ngx_http_headers_in[] = {
{ ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
- ngx_http_process_header_line },
+ ngx_http_process_unique_header_line },
{ ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
- ngx_http_process_header_line },
+ ngx_http_process_unique_header_line },
{ ngx_string("If-Modified-Since"),
offsetof(ngx_http_headers_in_t, if_modified_since),
@@ -79,7 +81,7 @@
{ ngx_string("Content-Length"),
offsetof(ngx_http_headers_in_t, content_length),
- ngx_http_process_header_line },
+ ngx_http_process_unique_header_line },
{ ngx_string("Content-Type"),
offsetof(ngx_http_headers_in_t, content_type),
@@ -104,7 +106,7 @@
{ ngx_string("Authorization"),
offsetof(ngx_http_headers_in_t, authorization),
- ngx_http_process_header_line },
+ ngx_http_process_unique_header_line },
{ ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
ngx_http_process_header_line },
@@ -113,12 +115,6 @@
{ ngx_string("X-Forwarded-For"),
offsetof(ngx_http_headers_in_t, x_forwarded_for),
ngx_http_process_header_line },
-
- { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip),
- ngx_http_process_header_line },
-
- { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t, x_url),
- ngx_http_process_header_line },
#endif
#if (NGX_HTTP_HEADERS)
@@ -906,13 +902,13 @@
return n;
}
- if (!rev->ready) {
- return NGX_AGAIN;
+ if (rev->ready) {
+ n = r->connection->recv(r->connection, r->header_in->last,
+ r->header_in->end - r->header_in->last);
+ } else {
+ n = NGX_AGAIN;
}
- n = r->connection->recv(r->connection, r->header_in->last,
- r->header_in->end - r->header_in->last);
-
if (n == NGX_AGAIN) {
if (!r->header_timeout_set) {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
@@ -1107,21 +1103,44 @@
static ngx_int_t
+ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t **ph;
+
+ ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
+
+ if (*ph == NULL) {
+ *ph = h;
+ return NGX_OK;
+ }
+
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client sent duplicate header line: \"%V: %V\"",
+ &h->key, &h->value);
+
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
ngx_table_elt_t **cookie;
cookie = ngx_array_push(&r->headers_in.cookies);
- if (cookie == NULL) {
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- ngx_http_close_connection(r->connection);
- return NGX_ERROR;
+ if (cookie) {
+ *cookie = h;
+ return NGX_OK;
}
- *cookie = h;
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ ngx_http_close_connection(r->connection);
- return NGX_OK;
+ return NGX_ERROR;
}
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index e2f3033..470f584 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -152,8 +152,6 @@
#if (NGX_HTTP_PROXY)
ngx_table_elt_t *x_forwarded_for;
- ngx_table_elt_t *x_real_ip;
- ngx_table_elt_t *x_url;
#endif
#if (NGX_HTTP_HEADERS)
@@ -365,6 +363,7 @@
unsigned internal:1;
unsigned closed:1;
unsigned done:1;
+ unsigned utf8:1;
unsigned main_filter_need_in_memory:1;
unsigned filter_need_in_memory:1;
diff --git a/src/imap/ngx_imap_core_module.c b/src/imap/ngx_imap_core_module.c
index 3e775f3..b4bde52 100644
--- a/src/imap/ngx_imap_core_module.c
+++ b/src/imap/ngx_imap_core_module.c
@@ -249,7 +249,8 @@
if (err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%s in \"%V\" of the \"listen\" directive", err);
+ "%s in \"%V\" of the \"listen\" directive",
+ err, &inet_upstream.url);
return NGX_CONF_ERROR;
}
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index 8d0e983..7b34590 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -76,7 +76,7 @@
#endif
-#if defined SO_ACCEPTFILTER && !defined NGX_HAVE_DEFERRED_ACCEPT
+#if (defined SO_ACCEPTFILTER && !defined NGX_HAVE_DEFERRED_ACCEPT)
#define NGX_HAVE_DEFERRED_ACCEPT 1
#endif
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 2a165bf..d3c92a1 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -839,7 +839,7 @@
#endif
if (ccf->working_directory.len) {
- if (chdir(ccf->working_directory.data) == -1) {
+ if (chdir((char *) ccf->working_directory.data) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"chdir(\"%s\") failed", ccf->working_directory.data);
/* fatal */