nginx-0.1.2-RELEASE import

    *) Feature: the --user=USER, --group=GROUP, and --with-ld-opt=OPTIONS
       options in configure.

    *) Feature: the server_name directive supports *.domain.tld.

    *) Bugfix: the portability improvements.

    *) Bugfix: if configuration file was set in command line, the
       reconfiguration was impossible; the bug had appeared in 0.1.1.

    *) Bugfix: proxy module may get caught in an endless loop when sendfile
       is not used.

    *) Bugfix: with sendfile the response was not recoded according to the
       charset module directives; the bug had appeared in 0.1.1.

    *) Bugfix: very seldom bug in the kqueue processing.

    *) Bugfix: the gzip module compressed the proxied responses that was
       already compressed.
diff --git a/src/http/modules/ngx_http_charset_filter.c b/src/http/modules/ngx_http_charset_filter.c
index d22a86b..f2e85e5 100644
--- a/src/http/modules/ngx_http_charset_filter.c
+++ b/src/http/modules/ngx_http_charset_filter.c
@@ -12,7 +12,7 @@
 typedef struct {
     char       **tables;
     ngx_str_t    name;
-    unsigned     server;
+    ngx_uint_t   server;  /* unsigned     server:1; */
 } ngx_http_charset_t;
 
 
@@ -45,7 +45,7 @@
 } ngx_http_charset_ctx_t;
 
 
-static void ngx_charset_recode(ngx_buf_t *b, char *table);
+static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table);
 
 static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
                                    void *conf);
@@ -232,14 +232,31 @@
 }
 
 
-static void ngx_charset_recode(ngx_buf_t *b, char *table)
+static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table)
 {
-    u_char  *p, c;
+    u_char      *p;
+    ngx_uint_t   change;
+
+    change = 0;
 
     for (p = b->pos; p < b->last; p++) {
-        c = *p;
-        *p = table[c];
+        if (*p != table[*p]) {
+            change = 1;
+            break;
+        }
     }
+
+    if (change) {
+
+        while (p < b->last) {
+            *p = table[*p];
+            p++;
+        }
+
+        b->in_file = 0;
+    }
+
+    return change;
 }
 
 
@@ -419,7 +436,9 @@
         return NGX_ERROR;
     }
 
+    c->tables = NULL;
     c->name = *name;
+    c->server = 0;
 
     return i;
 }
diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c
index 2112461..7881248 100644
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -63,7 +63,7 @@
                                               ngx_chain_t *in)
 {
     u_char       *chunk;
-    size_t        size, len;
+    size_t        size;
     ngx_buf_t    *b;
     ngx_chain_t   out, tail, *cl, *tl, **ll;
 
@@ -98,6 +98,20 @@
     }
 
     if (size) {
+        if (!(b = ngx_calloc_buf(r->pool))) {
+            return NGX_ERROR;
+        }
+
+        if (!(chunk = ngx_palloc(r->pool, 11))) {
+            return NGX_ERROR;
+        }
+
+        b->temporary = 1;
+        b->pos = chunk;
+        b->last = ngx_sprintf(chunk, "%uxS" CRLF, size);
+
+        out.buf = b;
+#if 0
         ngx_test_null(chunk, ngx_palloc(r->pool, 11), NGX_ERROR);
         len = ngx_snprintf((char *) chunk, 11, SIZE_T_X_FMT CRLF, size);
 
@@ -107,6 +121,7 @@
         b->last = chunk + len;
 
         out.buf = b;
+#endif
     }
 
     if (cl->buf->last_buf) {
diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c
index 4089ffb..bb3a1f0 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -837,26 +837,30 @@
         return buf + 1;
     }
 
-#if 0
-    return buf + ngx_snprintf((char *) buf, NGX_INT32_LEN + 4, "%.2f",
-                              (float) ctx->zin / ctx->zout);
-#endif
-
     /* we prefer do not use the FPU */
 
     zint = (ngx_uint_t) (ctx->zin / ctx->zout);
     zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100);
 
-    if ((ctx->zin * 1000 / ctx->zout) %10 > 4) {
-        if (++zfrac > 99) {
+    if ((ctx->zin * 1000 / ctx->zout) % 10 > 4) {
+
+        /* the rounding, e.g., 2.125 to 2.13 */
+
+        zfrac++;
+
+        if (zfrac > 99) {
             zint++;
             zfrac = 0;
         }
     }
 
+    return ngx_sprintf(buf, "%ui.%02ui", zint, zfrac);
+
+#if 0
     return buf + ngx_snprintf((char *) buf, NGX_INT32_LEN + 4,
                               "%" NGX_UINT_T_FMT ".%02" NGX_UINT_T_FMT,
                               zint, zfrac);
+#endif
 }
 
 
diff --git a/src/http/modules/ngx_http_headers_filter.c b/src/http/modules/ngx_http_headers_filter.c
index f7fe52c..faf8192 100644
--- a/src/http/modules/ngx_http_headers_filter.c
+++ b/src/http/modules/ngx_http_headers_filter.c
@@ -134,10 +134,16 @@
                         return NGX_ERROR;
                     }
 
+                    cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T",
+                                                conf->expires)
+                                    - cc->value.data;
+
+#if 0
                     cc->value.len = ngx_snprintf((char *) cc->value.data,
                                                sizeof("max-age=") + TIME_T_LEN,
                                                "max-age=" TIME_T_FMT,
                                                conf->expires);
+#endif
                 }
             }
         }
diff --git a/src/http/modules/ngx_http_range_filter.c b/src/http/modules/ngx_http_range_filter.c
index a08e25f..082fd3c 100644
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -264,9 +264,14 @@
         }
 
         r->headers_out.content_range->value.len =
+                ngx_sprintf(r->headers_out.content_range->value.data,
+                            "bytes */%O", r->headers_out.content_length_n)
+                - r->headers_out.content_range->value.data;
+#if 0
                 ngx_snprintf((char *) r->headers_out.content_range->value.data,
                              8 + 20 + 1, "bytes */" OFF_T_FMT,
                              r->headers_out.content_length_n);
+#endif
 
         r->headers_out.content_length_n = -1;
         if (r->headers_out.content_length) {
@@ -297,12 +302,20 @@
             /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
 
             r->headers_out.content_range->value.len =
+                         ngx_sprintf(r->headers_out.content_range->value.data,
+                                     "bytes %O-%O/%O",
+                                     range->start, range->end - 1,
+                                     r->headers_out.content_length_n)
+                         - r->headers_out.content_range->value.data;
+
+#if 0
                    ngx_snprintf((char *)
                                 r->headers_out.content_range->value.data,
                                 6 + 20 + 1 + 20 + 1 + 20 + 1,
                                 "bytes " OFF_T_FMT "-" OFF_T_FMT "/" OFF_T_FMT,
                                 range->start, range->end - 1,
                                 r->headers_out.content_length_n);
+#endif
 
             r->headers_out.content_length_n = range->end - range->start;
 
@@ -343,6 +356,15 @@
 
             if (r->headers_out.charset.len) {
                 ctx->boundary_header.len =
+                          ngx_sprintf(ctx->boundary_header.data,
+                                      CRLF "--%010ui" CRLF
+                                      "Content-Type: %s; charset=%s" CRLF
+                                      "Content-Range: bytes ",
+                                      boundary,
+                                      r->headers_out.content_type->value.data,
+                                      r->headers_out.charset.data)
+                          - ctx->boundary_header.data;
+#if 0
                          ngx_snprintf((char *) ctx->boundary_header.data, len,
                                       CRLF "--%010" NGX_UINT_T_FMT CRLF
                                       "Content-Type: %s; charset=%s" CRLF
@@ -350,17 +372,29 @@
                                       boundary,
                                       r->headers_out.content_type->value.data,
                                       r->headers_out.charset.data);
+#endif
 
                 r->headers_out.charset.len = 0;
 
             } else {
                 ctx->boundary_header.len =
+                          ngx_sprintf(ctx->boundary_header.data,
+                                      CRLF "--%010ui" CRLF
+                                      "Content-Type: %s" CRLF
+                                      "Content-Range: bytes ",
+                                      boundary,
+                                      r->headers_out.content_type->value.data)
+                          - ctx->boundary_header.data;
+
+#if 0
                          ngx_snprintf((char *) ctx->boundary_header.data, len,
                                       CRLF "--%010" NGX_UINT_T_FMT CRLF
                                       "Content-Type: %s" CRLF
                                       "Content-Range: bytes ",
                                       boundary,
                                       r->headers_out.content_type->value.data);
+
+#endif
             }
 
             ngx_test_null(r->headers_out.content_type->value.data,
@@ -370,12 +404,18 @@
             /* "Content-Type: multipart/byteranges; boundary=0123456789" */
 
             r->headers_out.content_type->value.len =
+                       ngx_sprintf(r->headers_out.content_type->value.data,
+                                   "multipart/byteranges; boundary=%010ui",
+                                   boundary)
+                       - r->headers_out.content_type->value.data;
+#if 0
                       ngx_snprintf((char *)
                                    r->headers_out.content_type->value.data,
                                    31 + 10 + 1,
                                    "multipart/byteranges; boundary=%010"
                                    NGX_UINT_T_FMT,
                                    boundary);
+#endif
 
             /* the size of the last boundary CRLF "--0123456789--" CRLF */
             len = 4 + 10 + 4;
@@ -389,11 +429,18 @@
                 /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
 
                 range[i].content_range.len =
+                                 ngx_sprintf(range[i].content_range.data,
+                                             "%O-%O/%O" CRLF CRLF,
+                                             range[i].start, range[i].end - 1,
+                                             r->headers_out.content_length_n)
+                                 - range[i].content_range.data;
+#if 0
                   ngx_snprintf((char *) range[i].content_range.data,
                                20 + 1 + 20 + 1 + 20 + 5,
                                OFF_T_FMT "-" OFF_T_FMT "/" OFF_T_FMT CRLF CRLF,
                                range[i].start, range[i].end - 1,
                                r->headers_out.content_length_n);
+#endif
 
                 len += ctx->boundary_header.len + range[i].content_range.len
                                     + (size_t) (range[i].end - range[i].start);
diff --git a/src/http/modules/ngx_http_status_handler.c b/src/http/modules/ngx_http_status_handler.c
index 6206ac3..357afff 100644
--- a/src/http/modules/ngx_http_status_handler.c
+++ b/src/http/modules/ngx_http_status_handler.c
@@ -159,6 +159,9 @@
                   + 1 + (r->server_name ? cmcf->max_server_name_len : 1)
                   + 2;                                /* "\r\n" */
 
+            /* BUG: cmcf->max_server_name_len and "*.domain.tld" */
+
+
             if (r->request_line.len) {
                 len += 1 + 1 + r->request_line.len + 1;
             }
diff --git a/src/http/modules/ngx_http_userid_filter.c b/src/http/modules/ngx_http_userid_filter.c
index 5f8e452..bafdea8 100644
--- a/src/http/modules/ngx_http_userid_filter.c
+++ b/src/http/modules/ngx_http_userid_filter.c
@@ -367,7 +367,7 @@
 
     } else if (conf->expires) {
         p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
-        p += ngx_http_cookie_time(p, ngx_time() + conf->expires);
+        p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
     }
 
     if (conf->domain.len > 1) {
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index f0794f3..5d61167 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -289,6 +289,8 @@
                          offsetof(ngx_http_proxy_headers_in_t, content_type) },
     { ngx_string("Content-Length"),
                        offsetof(ngx_http_proxy_headers_in_t, content_length) },
+    { ngx_string("Content-Encoding"),
+                     offsetof(ngx_http_proxy_headers_in_t, content_encoding) },
     { ngx_string("Last-Modified"),
                         offsetof(ngx_http_proxy_headers_in_t, last_modified) },
     { ngx_string("Location"),
@@ -400,7 +402,7 @@
 
 #if (HAVE_KQUEUE)
 
-    if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
 
         if (!ev->pending_eof) {
             return;
@@ -1310,10 +1312,10 @@
 
 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
 {
-#if __FreeBSD__
-
     ssize_t *np = data;
 
+#if (NGX_FREEBSD)
+
     if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "\"proxy_send_lowat\" must be less than %d "
@@ -1323,15 +1325,12 @@
         return NGX_CONF_ERROR;
     }
 
+#elif !(HAVE_SO_SNDLOWAT)
 
-#else
-
-#if 0
     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                        "\"proxy_send_lowat\" is not supported, ignored");
 
     *np = 0;
-#endif
 
 #endif
 
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 728259c..3e721ba 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -130,6 +130,7 @@
     ngx_table_elt_t                 *connection;
     ngx_table_elt_t                 *content_type;
     ngx_table_elt_t                 *content_length;
+    ngx_table_elt_t                 *content_encoding;
     ngx_table_elt_t                 *last_modified;
     ngx_table_elt_t                 *location;
     ngx_table_elt_t                 *accept_ranges;
diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c
index 07722fc..cd5deeb 100644
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ b/src/http/modules/proxy/ngx_http_proxy_header.c
@@ -113,6 +113,11 @@
             continue;
         }
 
+        if (&h[i] == headers_in->content_encoding) {
+            r->headers_out.content_encoding = ho;
+            continue;
+        }
+
         if (&h[i] == headers_in->last_modified) {
             r->headers_out.last_modified = ho;
             /* TODO: update r->headers_out.last_modified_time */
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index be5d69a..88479da 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -692,12 +692,14 @@
 
     /* rc == NGX_OK */
 
-#if 1 /* test only, see below about "post aio operation" */
+#if 0 /* test only, see below about "post aio operation" */
 
     if (c->read->ready) {
         /* post aio operation */
         ngx_http_proxy_process_upstream_status_line(c->read);
+#if 0
         return;
+#endif
     }
 
 #endif
@@ -718,7 +720,7 @@
 
 #if (HAVE_KQUEUE)
 
-    if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)
+    if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT)
         && !p->request_sent
         && c->write->pending_eof)
     {
@@ -776,7 +778,7 @@
 
     ngx_add_timer(c->read, p->lcf->read_timeout);
 
-#if 0
+#if 1
     if (c->read->ready) {
 
         /* post aio operation */
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index a37ffc6..90bbbe2 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -11,6 +11,14 @@
 
 
 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
+                                      ngx_http_in_port_t *in_port,
+                                      ngx_http_listen_t *lscf,
+                                      ngx_http_core_srv_conf_t *cscf);
+static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
+                                    ngx_http_in_addr_t *in_addr,
+                                    ngx_http_core_srv_conf_t *cscf);
+
 static char *ngx_http_merge_locations(ngx_conf_t *cf,
                                       ngx_array_t *locations,
                                       void **loc_conf,
@@ -79,6 +87,11 @@
     ngx_iocp_conf_t             *iocpcf;
 #endif
 
+#if (NGX_SUPPRESS_WARN)
+    /* MSVC thinks 'in_ports' may be used without having been initialized */
+    ngx_memzero(&in_ports, sizeof(ngx_array_t));
+#endif
+
     /* the main http context */
     ngx_test_null(ctx,
                   ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
@@ -274,18 +287,23 @@
 
 
     /*
-     * create the lists of the ports, the addresses and the server names
-     * to allow quickly find the server core module configuration at run-time
+     * create the lists of ports, addresses and server names
+     * to quickly find the server core module configuration at run-time
      */
 
-    ngx_init_array(in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t),
-                   NGX_CONF_ERROR);
+    if (ngx_array_init(&in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t))
+                                                                  == NGX_ERROR)
+    {
+        return NGX_CONF_ERROR;
+    }
 
     /* "server" directives */
+
     cscfp = cmcf->servers.elts;
     for (s = 0; s < cmcf->servers.nelts; s++) {
 
         /* "listen" directives */
+
         lscf = cscfp[s]->listen.elts;
         for (l = 0; l < cscfp[s]->listen.nelts; l++) {
 
@@ -308,38 +326,26 @@
 
                         if (lscf[l].addr == in_addr[a].addr) {
 
-                            /* the address is already bound to this port */
+                            /* the address is already in the address list */
 
-                            /* "server_name" directives */
-                            s_name = cscfp[s]->server_names.elts;
-                            for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
-
-                                /*
-                                 * add the server name and server core module
-                                 * configuration to the address:port
-                                 */
-
-                                /* TODO: duplicate names can be checked here */
-
-                                ngx_test_null(name,
-                                              ngx_push_array(&in_addr[a].names),
-                                              NGX_CONF_ERROR);
-
-                                name->name = s_name[n].name;
-                                name->core_srv_conf = s_name[n].core_srv_conf;
+                            if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
+                                                                  == NGX_ERROR)
+                            {
+                                return NGX_CONF_ERROR;
                             }
 
                             /*
-                             * check duplicate "default" server that
-                             * serves this address:port
+                             * check the duplicate "default" server 
+                             * for this address:port
                              */
 
                             if (lscf[l].default_server) {
+
                                 if (in_addr[a].default_server) {
                                     ngx_log_error(NGX_LOG_ERR, cf->log, 0,
-                                           "duplicate default server in %s:%d",
-                                           lscf[l].file_name.data,
-                                           lscf[l].line);
+                                        "the duplicate default server in %s:%d",
+                                        lscf[l].file_name.data,
+                                        lscf[l].line);
 
                                     return NGX_CONF_ERROR;
                                 }
@@ -354,31 +360,31 @@
 
                         } else if (in_addr[a].addr == INADDR_ANY) {
 
-                            /*
-                             * "*:port" must be the last resort so move it
-                             * to the end of the address list and add
-                             * the new address at its place
-                             */
+                            /* the INADDR_ANY is always the last address */
 
-                            ngx_test_null(inaddr,
-                                          ngx_push_array(&in_port[p].addrs),
-                                          NGX_CONF_ERROR);
+                            if (!(inaddr = ngx_array_push(&in_port[p].addrs))) {
+                                return NGX_CONF_ERROR;
+                            }
+
+                            /*
+                             * the INADDR_ANY must be the last resort
+                             * so we move it to the end of the address list
+                             * and put the new address in its place
+                             */
 
                             ngx_memcpy(inaddr, &in_addr[a],
                                        sizeof(ngx_http_in_addr_t));
 
                             in_addr[a].addr = lscf[l].addr;
+                            in_addr[a].names.elts = NULL;
                             in_addr[a].default_server = lscf[l].default_server;
                             in_addr[a].core_srv_conf = cscfp[s];
 
-                            /*
-                             * create the empty list of the server names that
-                             * can be served on this address:port
-                             */
-
-                            ngx_init_array(inaddr->names, cf->pool, 10,
-                                           sizeof(ngx_http_server_name_t),
-                                           NGX_CONF_ERROR);
+                            if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
+                                                                  == NGX_ERROR)
+                            {
+                                return NGX_CONF_ERROR;
+                            }
 
                             addr_found = 1;
 
@@ -393,22 +399,11 @@
                          * bound to this port
                          */
 
-                        ngx_test_null(inaddr,
-                                      ngx_push_array(&in_port[p].addrs),
-                                      NGX_CONF_ERROR);
-
-                        inaddr->addr = lscf[l].addr;
-                        inaddr->default_server = lscf[l].default_server;
-                        inaddr->core_srv_conf = cscfp[s];
-
-                        /*
-                         * create the empty list of the server names that
-                         * can be served on this address:port
-                         */
-
-                        ngx_init_array(inaddr->names, cf->pool, 10,
-                                       sizeof(ngx_http_server_name_t),
-                                       NGX_CONF_ERROR);
+                        if (ngx_http_add_address(cf, &in_port[p], &lscf[l],
+                                                        cscfp[s]) == NGX_ERROR)
+                        {
+                            return NGX_CONF_ERROR;
+                        }
                     }
                 }
             }
@@ -417,54 +412,42 @@
 
                 /* add the port to the in_port list */
 
-                ngx_test_null(in_port,
-                              ngx_push_array(&in_ports),
-                              NGX_CONF_ERROR);
+                if (!(in_port = ngx_array_push(&in_ports))) {
+                    return NGX_CONF_ERROR;
+                }
 
                 in_port->port = lscf[l].port;
+                in_port->addrs.elts = NULL;
 
-                ngx_test_null(in_port->port_text.data, ngx_palloc(cf->pool, 7),
-                              NGX_CONF_ERROR);
-                in_port->port_text.len = ngx_snprintf((char *)
-                                                      in_port->port_text.data,
-                                                      7, ":%d",
-                                                      in_port->port);
+                if (!(in_port->port_text.data = ngx_palloc(cf->pool, 7))) {
+                    return NGX_CONF_ERROR;
+                }
 
-                /* create list of the addresses that bound to this port ... */
+                in_port->port_text.len = ngx_sprintf(in_port->port_text.data,
+                                                     ":%d", in_port->port)
+                                         - in_port->port_text.data;
 
-                ngx_init_array(in_port->addrs, cf->pool, 10,
-                               sizeof(ngx_http_in_addr_t),
-                               NGX_CONF_ERROR);
-
-                ngx_test_null(inaddr, ngx_push_array(&in_port->addrs),
-                              NGX_CONF_ERROR);
-
-                /* ... and add the address to this list */
-
-                inaddr->addr = lscf[l].addr;
-                inaddr->default_server = lscf[l].default_server;
-                inaddr->core_srv_conf = cscfp[s];
-
-                /*
-                 * create the empty list of the server names that
-                 * can be served on this address:port
-                 */
-
-                ngx_init_array(inaddr->names, cf->pool, 10,
-                               sizeof(ngx_http_server_name_t),
-                               NGX_CONF_ERROR);
+                if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s])
+                                                                  == NGX_ERROR)
+                {
+                    return NGX_CONF_ERROR;
+                }
             }
         }
     }
 
-    /* optimize the lists of the ports, the addresses and the server names */
+
+    /* optimize the lists of ports, addresses and server names */
 
     /* AF_INET only */
 
     in_port = in_ports.elts;
     for (p = 0; p < in_ports.nelts; p++) {
 
-        /* check whether the all server names point to the same server */
+        /*
+         * check whether all name-based servers have the same configuraiton
+         * as the default server, or some servers restrict the host names
+         */
 
         in_addr = in_port[p].addrs.elts;
         for (a = 0; a < in_port[p].addrs.nelts; a++) {
@@ -473,15 +456,19 @@
 
             name = in_addr[a].names.elts;
             for (n = 0; n < in_addr[a].names.nelts; n++) {
-                if (in_addr[a].core_srv_conf != name[n].core_srv_conf) {
+                if (in_addr[a].core_srv_conf != name[n].core_srv_conf
+                    || name[n].core_srv_conf->restrict_host_names
+                                                 != NGX_HTTP_RESTRICT_HOST_OFF)
+                {
                     virtual_names = 1;
                     break;
                 }
             }
 
             /*
-             * if the all server names point to the same server
-             * then we do not need to check them at run-time
+             * if all name-based servers have the same configuration
+             * as the default server, and no servers restrict the host names
+             * then we do not need to check them at run-time at all
              */
 
             if (!virtual_names) {
@@ -588,30 +575,117 @@
     }
 
 #if (NGX_DEBUG)
+    {
+    u_char      address[20];
+    ngx_uint_t  p, a, n;
+
     in_port = in_ports.elts;
     for (p = 0; p < in_ports.nelts; p++) {
         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
                       "port: %d %08x", in_port[p].port, &in_port[p]);
         in_addr = in_port[p].addrs.elts;
         for (a = 0; a < in_port[p].addrs.nelts; a++) {
-            u_char ip[20];
-            ngx_inet_ntop(AF_INET, &in_addr[a].addr, ip, 20);
-            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
-                           "%s %08x", ip, in_addr[a].core_srv_conf);
+            ngx_inet_ntop(AF_INET, &in_addr[a].addr, address, 20);
+            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+                           "%s:%d %08x",
+                           address, in_port[p].port, in_addr[a].core_srv_conf);
             s_name = in_addr[a].names.elts;
             for (n = 0; n < in_addr[a].names.nelts; n++) {
-                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
-                                "%s %08x", s_name[n].name.data,
+                 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+                                "%s:%d %s %08x",
+                                address, in_port[p].port, s_name[n].name.data,
                                 s_name[n].core_srv_conf);
             }
         }
     }
+    }
 #endif
 
     return NGX_CONF_OK;
 }
 
 
+/*
+ * add the server address, the server names and the server core module
+ * configurations to the port (in_port)
+ */
+
+static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
+                                      ngx_http_in_port_t *in_port,
+                                      ngx_http_listen_t *lscf,
+                                      ngx_http_core_srv_conf_t *cscf)
+{
+    ngx_http_in_addr_t  *in_addr;
+
+    if (in_port->addrs.elts == NULL) {
+        if (ngx_array_init(&in_port->addrs, cf->pool, 10,
+                                      sizeof(ngx_http_in_addr_t)) == NGX_ERROR)
+        {
+            return NGX_ERROR;
+        }
+    }
+
+    if (!(in_addr = ngx_array_push(&in_port->addrs))) {
+        return NGX_ERROR;
+    }
+
+    in_addr->addr = lscf->addr;
+    in_addr->names.elts = NULL;
+    in_addr->default_server = lscf->default_server;
+    in_addr->core_srv_conf = cscf;
+
+#if (NGX_DEBUG)
+    {
+    u_char text[20];
+    ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20);
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d",
+                   text, in_port->port);
+    }
+#endif
+
+    return ngx_http_add_names(cf, in_addr, cscf);
+}
+
+
+/*
+ * add the server names and the server core module
+ * configurations to the address:port (in_addr)
+ */
+
+static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
+                                    ngx_http_in_addr_t *in_addr,
+                                    ngx_http_core_srv_conf_t *cscf)
+{
+    ngx_uint_t               i;
+    ngx_http_server_name_t  *server_names, *name;
+
+    if (in_addr->names.elts == NULL) {
+        if (ngx_array_init(&in_addr->names, cf->pool, 10,
+                                  sizeof(ngx_http_server_name_t)) == NGX_ERROR)
+        {
+            return NGX_ERROR;
+        }
+    }
+
+    server_names = cscf->server_names.elts;
+    for (i = 0; i < cscf->server_names.nelts; i++) {
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+                       "name: %s", server_names[i].name.data);
+
+        /* TODO: duplicate names can be checked here */
+
+        if (!(name = ngx_array_push(&in_addr->names))) {
+            return NGX_ERROR;
+        }
+
+        *name = server_names[i];
+    }
+
+    return NGX_OK;
+}
+
+
 static char *ngx_http_merge_locations(ngx_conf_t *cf,
                                       ngx_array_t *locations,
                                       void **loc_conf,
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 58021e8..8544e25 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -36,7 +36,7 @@
                                 void *dummy);
 static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
-static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_http_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_set_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
                                  void *conf);
 static char *ngx_set_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@@ -126,9 +126,9 @@
 #if 0
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
 #else
-      NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+      NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
 #endif
-      ngx_set_listen,
+      ngx_http_listen,
       NGX_HTTP_SRV_CONF_OFFSET,
       0,
       NULL },
@@ -576,7 +576,7 @@
     clcfp = locations->elts;
     for (i = 0; i < locations->nelts; i++) {
 
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
         if (clcfp[i]->regex) {
             break;
         }
@@ -638,7 +638,7 @@
         }
     }
 
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
 
     /* regex matches */
 
@@ -673,7 +673,7 @@
         return NGX_HTTP_LOCATION_REGEX;
     }
 
-#endif /* HAVE_PCRE */
+#endif /* NGX_PCRE */
 
     return NGX_OK;
 }
@@ -991,7 +991,7 @@
     first = *(ngx_http_core_loc_conf_t **) one;
     second = *(ngx_http_core_loc_conf_t **) two;
 
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
 
     if (first->regex && !second->regex) {
         /* shift the regex matches to the end */
@@ -1026,7 +1026,7 @@
     ngx_http_conf_ctx_t       *ctx, *pctx;
     ngx_http_core_srv_conf_t  *cscf;
     ngx_http_core_loc_conf_t  *clcf, *pclcf, **clcfp;
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
     ngx_str_t                  err;
     u_char                     errstr[NGX_MAX_CONF_ERRSTR];
 #endif
@@ -1076,7 +1076,7 @@
                        && value[1].data[0] == '~'
                        && value[1].data[1] == '*'))
         {
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
             err.len = NGX_MAX_CONF_ERRSTR;
             err.data = errstr;
 
@@ -1129,7 +1129,7 @@
             return NGX_CONF_ERROR;
         }
 
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
         if (clcf->regex == NULL
             && ngx_strncmp(clcf->name.data, pclcf->name.data, pclcf->name.len)
                                                                          != 0)
@@ -1323,12 +1323,8 @@
 
         n->name.len = ngx_strlen(n->name.data);
         n->core_srv_conf = conf;
+        n->wildcard = 0;
 
-#if 0
-        ctx = (ngx_http_conf_ctx_t *)
-                                    cf->cycle->conf_ctx[ngx_http_module.index];
-        cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
-#endif
         cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
 
         if (cmcf->max_server_name_len < n->name.len) {
@@ -1512,7 +1508,7 @@
 }
 
 
-static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+static char *ngx_http_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_core_srv_conf_t *scf = conf;
 
@@ -1607,13 +1603,8 @@
     ngx_http_server_name_t     *sn;
     ngx_http_core_main_conf_t  *cmcf;
 
-    /* TODO: several names */
     /* TODO: warn about duplicate 'server_name' directives */
 
-#if 0
-    ctx = (ngx_http_conf_ctx_t *) cf->cycle->conf_ctx[ngx_http_module.index];
-    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
-#endif
     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
 
     value = cf->args->elts;
@@ -1627,12 +1618,23 @@
             return NGX_CONF_ERROR;
         }
 
-        ngx_test_null(sn, ngx_push_array(&scf->server_names), NGX_CONF_ERROR);
+        if (!(sn = ngx_array_push(&scf->server_names))) {
+            return NGX_CONF_ERROR;
+        }
 
         sn->name.len = value[i].len;
         sn->name.data = value[i].data;
         sn->core_srv_conf = scf;
 
+        if (sn->name.data[0] == '*') {
+            sn->name.len--;
+            sn->name.data++;
+            sn->wildcard = 1;
+
+        } else {
+            sn->wildcard = 0;
+        }
+
         if (cmcf->max_server_name_len < sn->name.len) {
             cmcf->max_server_name_len = sn->name.len;
         }
@@ -1806,7 +1808,7 @@
 {
     ssize_t *np = data;
 
-#if __FreeBSD__
+#if (NGX_FREEBSD)
 
     if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 787f8b8..9a17130 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -96,13 +96,15 @@
     ngx_http_core_srv_conf_t  *core_srv_conf;  /* default server conf
                                                   for this address:port */
 
-    unsigned                   default_server:1;
+    ngx_uint_t                 default_server; /* unsigned  default_server:1; */
 } ngx_http_in_addr_t;
 
 
 typedef struct {
     ngx_str_t                  name;
     ngx_http_core_srv_conf_t  *core_srv_conf; /* virtual name server conf */
+
+    ngx_uint_t                 wildcard;  /*unsigned  wildcard:1; */
 } ngx_http_server_name_t;
 
 
@@ -135,7 +137,7 @@
 struct ngx_http_core_loc_conf_s {
     ngx_str_t     name;          /* location name */
 
-#if (HAVE_PCRE)
+#if (NGX_PCRE)
     ngx_regex_t  *regex;
 #endif
 
diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c
index 5b7f3eb..a083b45 100644
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -317,10 +317,15 @@
 
     if (r->headers_out.content_length == NULL) {
         if (r->headers_out.content_length_n >= 0) {
+            b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
+                                  r->headers_out.content_length_n);
+
+#if 0
             b->last += ngx_snprintf((char *) b->last,
                                 sizeof("Content-Length: ") + NGX_OFF_T_LEN + 2,
                                 "Content-Length: " OFF_T_FMT CRLF,
                                 r->headers_out.content_length_n);
+#endif
         }
     }
 
@@ -372,7 +377,7 @@
     {
         b->last = ngx_cpymem(b->last, "Last-Modified: ",
                              sizeof("Last-Modified: ") - 1);
-        b->last += ngx_http_time(b->last, r->headers_out.last_modified_time);
+        b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
 
         *(b->last++) = CR; *(b->last++) = LF;
     }
@@ -389,10 +394,14 @@
         if (clcf->keepalive_header
             && (r->headers_in.gecko || r->headers_in.konqueror))
         {
+            b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF,
+                                  clcf->keepalive_header);
+#if 0
             b->last += ngx_snprintf((char *) b->last,
                             sizeof("Keep-Alive: timeout=") + TIME_T_LEN + 2,
                             "Keep-Alive: timeout=" TIME_T_FMT CRLF,
                             clcf->keepalive_header);
+#endif
         }
 
     } else {
diff --git a/src/http/ngx_http_log_handler.c b/src/http/ngx_http_log_handler.c
index 51166cf..9a1389d 100644
--- a/src/http/ngx_http_log_handler.c
+++ b/src/http/ngx_http_log_handler.c
@@ -210,9 +210,13 @@
 static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
                                      uintptr_t data)
 {
+    return ngx_sprintf(buf, "%ui", r->connection->number);
+
+#if 0
     return buf + ngx_snprintf((char *) buf, NGX_INT_T_LEN + 1,
                               "%" NGX_UINT_T_FMT,
                               r->connection->number);
+#endif
 }
 
 
@@ -244,8 +248,12 @@
 
     ngx_gettimeofday(&tv);
 
+    return ngx_sprintf(buf, "%l.%03l", tv.tv_sec, tv.tv_usec / 1000);
+
+#if 0
     return buf + ngx_snprintf((char *) buf, TIME_T_LEN + 5, "%ld.%03ld",
                               tv.tv_sec, tv.tv_usec / 1000);
+#endif
 }
 
 
@@ -264,24 +272,36 @@
 static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
                                    uintptr_t data)
 {
+    return ngx_sprintf(buf, "%ui",
+                       r->err_status ? r->err_status : r->headers_out.status);
+
+#if 0
     return buf + ngx_snprintf((char *) buf, 4, "%" NGX_UINT_T_FMT,
                         r->err_status ? r->err_status : r->headers_out.status);
+#endif
 }
 
 
 static u_char *ngx_http_log_length(ngx_http_request_t *r, u_char *buf,
                                    uintptr_t data)
 {
+    return ngx_sprintf(buf, "%O", r->connection->sent);
+
+#if 0
     return buf + ngx_snprintf((char *) buf, NGX_OFF_T_LEN + 1, OFF_T_FMT,
                               r->connection->sent);
+#endif
 }
 
 
 static u_char *ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf,
                                           uintptr_t data)
 {
+    return ngx_sprintf(buf, "%O", r->connection->sent - r->header_size);
+#if 0
     return buf + ngx_snprintf((char *) buf, NGX_OFF_T_LEN + 1, OFF_T_FMT,
                               r->connection->sent - r->header_size);
+#endif
 }
 
 
@@ -467,8 +487,7 @@
                     return (u_char *)
                                    sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1;
                 }
-                return buf + ngx_http_time(buf,
-                                           r->headers_out.last_modified_time);
+                return ngx_http_time(buf, r->headers_out.last_modified_time);
             }
 
             if (buf) {
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 6069847..74173d8 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1091,27 +1091,47 @@
 
         name = r->virtual_names->elts;
         for (i = 0; i < r->virtual_names->nelts; i++) {
-            if (r->headers_in.host_name_len != name[i].name.len) {
-                continue;
-            }
 
-            if (ngx_strncasecmp(r->headers_in.host->value.data,
-                                name[i].name.data,
-                                r->headers_in.host_name_len) == 0)
-            {
-                r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
-                r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
-                r->server_name = &name[i].name;
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "server name: %s", name[i].name.data);
 
-                clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-                r->connection->log->file = clcf->err_log->file;
-                if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION))
-                {
-                    r->connection->log->log_level = clcf->err_log->log_level;
+            if (name[i].wildcard) {
+                if (r->headers_in.host_name_len <= name[i].name.len) {
+                    continue;
                 }
 
-                break;
+                if (ngx_rstrncasecmp(r->headers_in.host->value.data,
+                                     name[i].name.data,
+                                     name[i].name.len) == 0)
+                {
+                    continue;
+                }
+
+            } else {
+                if (r->headers_in.host_name_len != name[i].name.len) {
+                    continue;
+                }
+
+                if (ngx_strncasecmp(r->headers_in.host->value.data,
+                                    name[i].name.data,
+                                    name[i].name.len) != 0)
+                {
+                    continue;
+                }
             }
+
+            r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
+            r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
+            r->server_name = &name[i].name;
+
+            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+            r->connection->log->file = clcf->err_log->file;
+
+            if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
+                r->connection->log->log_level = clcf->err_log->log_level;
+            }
+
+            break;
         }
 
         if (i == r->virtual_names->nelts) {
@@ -1562,7 +1582,13 @@
 
         if (b != c->buffer) {
 
-            /* move the large header buffers to the free list */
+            /*
+             * If the large header buffers were allocated while the previous
+             * request processing then we do not use c->buffer for
+             * the pipelined request (see ngx_http_init_request()).
+             * 
+             * Now we would move the large header buffers to the free list.
+             */
 
             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
@@ -1614,6 +1640,14 @@
 
     hc->pipeline = 0;
 
+    /*
+     * To keep a memory footprint as small as possible for an idle
+     * keepalive connection we try to free the ngx_http_request_t and
+     * c->buffer's memory if they were allocated outside the c->pool.
+     * The large header buffers are always allocated outside the c->pool and
+     * are freed too.
+     */
+
     if (ngx_pfree(c->pool, r) == NGX_OK) {
         hc->request = NULL;
     }
@@ -1621,6 +1655,12 @@
     b = c->buffer;
 
     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
+
+        /*
+         * the special note for ngx_http_keepalive_handler() that
+         * c->buffer's memory was freed
+         */
+
         b->pos = NULL;
 
     } else {
@@ -1655,7 +1695,7 @@
     rev->event_handler = ngx_http_keepalive_handler;
 
     if (wev->active) {
-        if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+        if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
             if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
                                                                   == NGX_ERROR)
             {
@@ -1702,7 +1742,7 @@
     }
 
 #if 0
-    /* if "keepalive_buffers off" then we need some other place */
+    /* if ngx_http_request_t was freed then we need some other place */
     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
 #endif
 
@@ -1734,7 +1774,7 @@
 
 #if (HAVE_KQUEUE)
 
-    if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
         if (rev->pending_eof) {
             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
                           "kevent() reported that client %s closed "
@@ -1751,6 +1791,13 @@
     size = b->end - b->start;
 
     if (b->pos == NULL) {
+
+        /*
+         * The c->buffer's memory was freed by ngx_http_set_keepalive().
+         * However, the c->buffer->start and c->buffer->end were not changed
+         * to keep the buffer size.
+         */
+
         if (!(b->pos = ngx_palloc(c->pool, size))) {
             ngx_http_close_connection(c);
             return;
@@ -1824,7 +1871,7 @@
     wev->event_handler = ngx_http_empty_handler;
 
     if (wev->active) {
-        if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+        if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
             if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
                                                                   == NGX_ERROR)
             {
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 022b8a8..8a9c8f2 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -38,11 +38,11 @@
 #define NGX_HTTP_PARSE_HEADER_ERROR        14
 #define NGX_HTTP_PARSE_INVALID_HEADER      14
 #define NGX_HTTP_PARSE_TOO_LONG_HEADER     15
-#define NGX_HTTP_PARSE_NO_HOST_HEADER      17
-#define NGX_HTTP_PARSE_INVALID_CL_HEADER   18
-#define NGX_HTTP_PARSE_POST_WO_CL_HEADER   19
-#define NGX_HTTP_PARSE_HTTP_TO_HTTPS       20
-#define NGX_HTTP_PARSE_INVALID_HOST        21
+#define NGX_HTTP_PARSE_NO_HOST_HEADER      16
+#define NGX_HTTP_PARSE_INVALID_CL_HEADER   17
+#define NGX_HTTP_PARSE_POST_WO_CL_HEADER   18
+#define NGX_HTTP_PARSE_HTTP_TO_HTTPS       19
+#define NGX_HTTP_PARSE_INVALID_HOST        20
 
 
 #define NGX_HTTP_OK                        200
diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c
index a8c6894..37e0f3f 100644
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -125,6 +125,7 @@
         if (!last) {
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                           "the http output chain is empty");
+            return NGX_ERROR;
         }
         return NGX_OK;
     }