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