changeset 155:46eb23d9471d

nginx-0.0.1-2003-10-22-20:38:26 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 22 Oct 2003 16:38:26 +0000
parents eac26585476e
children afc333135a6b
files src/core/ngx_conf_file.c src/core/ngx_conf_file.h src/core/ngx_file.c src/core/ngx_file.h src/core/ngx_hunk.c src/core/ngx_hunk.h src/core/ngx_listen.c src/core/ngx_listen.h src/core/ngx_write_chain.c src/event/ngx_event_acceptex.h src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h src/http/modules/ngx_http_charset_filter.c src/http/modules/ngx_http_chunked_filter.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_not_modified_filter.c src/http/modules/ngx_http_range_filter.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_filter.h src/http/ngx_http_header_filter.c src/http/ngx_http_output_filter.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_special_response.c src/http/ngx_http_write_filter.c src/os/unix/freebsd/ngx_sendfile.c src/os/unix/ngx_freebsd_sendfile_chain.c src/os/unix/ngx_readv_chain.c
diffstat 31 files changed, 617 insertions(+), 688 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -6,10 +6,20 @@
 
 #define MAX_CONF_ERRSTR  256
 
+/* Ten fixed arguments */
+
 static int argument_number[] = {
     NGX_CONF_NOARGS,
     NGX_CONF_TAKE1,
-    NGX_CONF_TAKE2
+    NGX_CONF_TAKE2,
+    NGX_CONF_TAKE3,
+    NGX_CONF_TAKE4,
+    NGX_CONF_TAKE5,
+    NGX_CONF_TAKE6,
+    NGX_CONF_TAKE7,
+    NGX_CONF_TAKE8,
+    NGX_CONF_TAKE9,
+    NGX_CONF_TAKE10
 };
 
 static int ngx_conf_read_token(ngx_conf_t *cf);
@@ -146,9 +156,17 @@ ngx_log_debug(cf->log, "command '%s'" _ 
 
                     /* is the directive's argument count right ? */
 
-                    if (cmd->type & argument_number[cf->args->nelts - 1]) {
+                    if (cmd->type & NGX_CONF_ANY) {
                         valid = 1;
 
+                    } else if (cmd->type & NGX_CONF_FLAG) {
+
+                        if (cf->args->nelts == 2) {
+                            valid = 1;
+                        } else {
+                            valid = 0;
+                        }
+
                     } else if (cmd->type & NGX_CONF_1MORE) {
 
                         if (cf->args->nelts != 1) {
@@ -157,15 +175,10 @@ ngx_log_debug(cf->log, "command '%s'" _ 
                             valid = 0;
                         }
 
-                    } else if (cmd->type & NGX_CONF_FLAG) {
-
-                        if (cf->args->nelts == 2) {
-                            valid = 1;
-                        } else {
-                            valid = 0;
-                        }
-
-                    } else if (cmd->type & NGX_CONF_ANY) {
+                    } else if (cf->args->nelts <= 10
+                               && (cmd->type
+                                   & argument_number[cf->args->nelts - 1]))
+                    {
                         valid = 1;
 
                     } else {
@@ -573,8 +586,7 @@ char *ngx_conf_set_str_slot(ngx_conf_t *
 
     value = (ngx_str_t *) cf->args->elts;
 
-    field->len = value[1].len;
-    field->data = value[1].data;
+    *field = value[1];
 
     return NGX_CONF_OK;
 }
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -15,6 +15,18 @@
 #define NGX_CONF_NOARGS      0x00000001
 #define NGX_CONF_TAKE1       0x00000002
 #define NGX_CONF_TAKE2       0x00000004
+#define NGX_CONF_TAKE3       0x00000008
+#define NGX_CONF_TAKE4       0x00000010
+#define NGX_CONF_TAKE5       0x00000020
+#define NGX_CONF_TAKE6       0x00000040
+#define NGX_CONF_TAKE7       0x00000080
+#define NGX_CONF_TAKE8       0x00000100
+#define NGX_CONF_TAKE9       0x00000200
+#define NGX_CONF_TAKE10      0x00000400
+
+#define NGX_CONF_TAKE1234    (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3   \
+                              |NGX_CONF_TAKE4)
+
 #define NGX_CONF_ARGS_NUMBER 0x0000ffff
 #define NGX_CONF_ANY         0x00010000
 #define NGX_CONF_1MORE       0x00020000
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -164,3 +164,44 @@ int ngx_next_temp_number(int collision)
 
     return ngx_temp_number++;
 }
+
+
+char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    char  *p = conf;
+
+    int          i, n;
+    ngx_str_t   *value;
+    ngx_path_t  *path, **pp;
+
+    pp = (ngx_path_t **) (p + cmd->offset);
+
+    if (*pp) {
+        return "is duplicate";
+    }
+
+    ngx_test_null(path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)), NULL);
+
+    *pp = path;
+
+    value = (ngx_str_t *) cf->args->elts;
+
+    path->name = value[1];
+
+    path->len = 0;
+
+    for (i = 0, n = 2; n < cf->args->nelts; i++, n++) {
+        path->level[i] = ngx_atoi(value[n].data, value[n].len);
+        if (path->level[i] == NGX_ERROR || path->level[i] == 0) {
+            return "invalid value";
+        }
+
+        path->len += path->level[i] + 1;
+    }
+
+    while (i < 3) {
+        path->level[i++] = 0;
+    }
+
+    return NULL;
+}
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -34,5 +34,24 @@ int ngx_create_path(ngx_file_t *file, ng
 void ngx_init_temp_number();
 int ngx_next_temp_number(int collision);
 
+char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+
+
+#define ngx_conf_merge_path_value(conf, prev, path, l1, l2, l3, pool)        \
+    if (conf == NULL) {                                                      \
+        if (prev == NULL) {                                                  \
+            ngx_test_null(conf, ngx_palloc(pool, sizeof(ngx_path_t)), NULL); \
+            conf->name.len = sizeof(path) - 1;                               \
+            conf->name.data = path;                                          \
+            conf->level[0] = l1;                                             \
+            conf->level[1] = l2;                                             \
+            conf->level[2] = l3;                                             \
+            conf->len = l1 + l2 + l3 + l1 ? 1:0 + l2 ? 1:0 + l3 ? 1:0;       \
+        } else {                                                             \
+            conf = prev;                                                     \
+        }                                                                    \
+    }
+
+
 
 #endif /* _NGX_FILE_H_INCLUDED_ */
--- a/src/core/ngx_hunk.c
+++ b/src/core/ngx_hunk.c
@@ -99,26 +99,26 @@ ngx_hunk_t *ngx_create_hunk_after(ngx_po
 }
 
 
-int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **ch, ngx_chain_t *in)
+int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in)
 {
-    ngx_chain_t  *ce, **le;
+    ngx_chain_t  *cl, **ll;
 
-    le = ch;
+    ll = chain;
 
-    for (ce = *ch; ce; ce = ce->next) {
-        le = &ce->next;
+    for (cl = *chain; cl; cl = cl->next) {
+        ll = &cl->next;
     }
 
     while (in) {
-        ngx_test_null(ce, ngx_alloc_chain_entry(pool), NGX_ERROR);
+        ngx_test_null(cl, ngx_alloc_chain_link(pool), NGX_ERROR);
 
-        ce->hunk = in->hunk;
-        *le = ce;
-        le = &ce->next;
+        cl->hunk = in->hunk;
+        *ll = cl;
+        ll = &cl->next;
         in = in->next;
     }
 
-    *le = NULL;
+    *ll = NULL;
 
     return NGX_OK;
 }
--- a/src/core/ngx_hunk.h
+++ b/src/core/ngx_hunk.h
@@ -99,31 +99,30 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_poo
 #define ngx_alloc_hunk(pool) ngx_palloc(pool, sizeof(ngx_hunk_t))
 #define ngx_calloc_hunk(pool) ngx_pcalloc(pool, sizeof(ngx_hunk_t))
 
-#define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
+
+#define ngx_alloc_chain_link(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
+
 
-#define ngx_add_hunk_to_chain(chain, h, pool, error)                         \
+#define ngx_alloc_link_and_set_hunk(chain, h, pool, error)                   \
             do {                                                             \
-                ngx_test_null(chain, ngx_alloc_chain_entry(pool), error);    \
+                ngx_test_null(chain, ngx_alloc_chain_link(pool), error);     \
                 chain->hunk = h;                                             \
                 chain->next = NULL;                                          \
             } while (0);
 
-#define ngx_alloc_ce_and_set_hunk  ngx_add_hunk_to_chain
+
+#define ngx_chain_add_link(chain, last, cl)                                  \
+            if (chain) {                                                     \
+                *last = cl;                                                  \
+            } else {                                                         \
+                chain = cl;                                                  \
+            }                                                                \
+            last = &cl->next
 
 
-#define ngx_chain_add_ce(chain, last, ce)                                    \
-            if (chain) {                                                     \
-                *last = ce;                                                  \
-            } else {                                                         \
-                chain = ce;                                                  \
-            }                                                                \
-            last = &ce->next
-
-
-int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **ch, ngx_chain_t *in);
+int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in);
 void ngx_chain_update_chains(ngx_chain_t **free, ngx_chain_t **busy,
                              ngx_chain_t **out, ngx_hunk_tag_t tag);
 
 
-
 #endif /* _NGX_HUNK_H_INCLUDED_ */
deleted file mode 100644
--- a/src/core/ngx_listen.c
+++ /dev/null
@@ -1,44 +0,0 @@
-
-#include <ngx_config.h>
-#include <ngx_types.h>
-#include <ngx_errno.h>
-#include <ngx_log.h>
-#include <ngx_listen.h>
-
-ngx_socket_t ngx_listen(struct sockaddr *addr, int backlog,
-                        ngx_log_t *log, char *addr_text)
-{
-    ngx_socket_t   s;
-    int            reuseaddr = 1;
-#if (WIN32)
-    unsigned long  nb = 1;
-#endif
-
-    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, "socket failed");
-
-    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
-                   (const void *) &reuseaddr, sizeof(int)) == -1)
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                     "ngx_listen: setsockopt (SO_REUSEADDR) failed");
-
-#if (WIN32)
-    if (ioctlsocket(s, FIONBIO, &nb) == -1)
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                     "ngx_listen: ioctlsocket (FIONBIO) failed");
-#else
-    if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                     "ngx_listen: fcntl (O_NONBLOCK) failed");
-#endif
-
-    if (bind(s, (struct sockaddr *) addr, sizeof(struct sockaddr_in)) == -1)
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                     "ngx_listen: bind to %s failed", addr_text);
-
-    if (listen(s, backlog) == -1)
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                     "ngx_listen: listen to %s failed", addr_text);
-
-    return s;
-}
deleted file mode 100644
--- a/src/core/ngx_listen.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _NGX_LISTEN_H_INCLUDED_
-#define _NGX_LISTEN_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_log.h>
-#include <ngx_types.h>
-#include <ngx_socket.h>
-#include <ngx_connection.h>
-
-typedef struct {
-    ngx_socket_t      fd;
-
-    struct sockaddr  *sockaddr;
-    socklen_t         socklen;    /* size of sockaddr */
-    int               addr;       /* offset to address in sockaddr */
-    int               addr_text_max_len;
-    ngx_str_t         addr_text;
-
-    int               family;
-    int               type;
-    int               protocol;
-    int               flags;      /* Winsock2 flags */
-
-    void            (*handler)(ngx_connection_t *c); /* handler of accepted
-                                                        connection */
-    void             *ctx;        /* ngx_http_conf_ctx_t, for example */
-    void             *servers;    /* array of ngx_http_in_addr_t, for example */
-
-    ngx_log_t        *log;
-    int               pool_size;
-
-    int               backlog;
-    time_t            post_accept_timeout;  /* should be here because
-                                               of the deferred accept */
-
-    unsigned          bound:1;       /* already bound */
-    unsigned          inherited:1;   /* inherited from previous process */
-    unsigned          nonblocking_accept:1;
-    unsigned          nonblocking:1;
-#if 0
-    unsigned          overlapped:1;  /* Winsock2 overlapped */
-#endif
-    unsigned          shared:1;    /* shared between threads or processes */
-#if (HAVE_DEFERRED_ACCEPT)
-    unsigned          deferred_accept:1;
-#endif
-} ngx_listen_t;
-
-
-extern ngx_array_t ngx_listening_sockets;
-
-
-#endif /* _NGX_LISTEN_H_INCLUDED_ */
deleted file mode 100644
--- a/src/core/ngx_write_chain.c
+++ /dev/null
@@ -1,50 +0,0 @@
-
-#include <ngx_config.h>
-
-#include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_alloc.h>
-#include <ngx_array.h>
-#include <ngx_hunk.h>
-#include <ngx_connection.h>
-
-
-ngx_chain_t *(*ngx_write_chain_proc)(ngx_connection_t *c, ngx_chain_t *in);
-
-
-ngx_chain_t *ngx_write_chain(ngx_connection_t *c, ngx_chain_t *in, off_t flush)
-{
-#if (NGX_EVENT)
-
-    return (*ngx_write_chain_proc)(c, in);
-
-#elif (NGX_EVENT_THREAD)
-
-    off_t         sent;
-    ngx_chain_t  *rc;
-
-    sent = flush - c->sent;
-
-    do {
-        rc = (*ngx_write_chain_proc)(c, in);
-
-        if (rc == NGX_CHAIN_ERROR && rc == NULL) {
-            return rc;
-        }
-
-    } while (c->thread && flush > c->sent - sent);
-
-#else
-
-    ngx_chain_t  *rc;
-
-    do {
-
-        rc = (*ngx_write_chain_proc)(c, in);
-
-    } while (rc != NGX_CHAIN_ERROR && rc != NULL);
-
-    return rc;
-
-#endif
-}
deleted file mode 100644
--- a/src/event/ngx_event_acceptex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _NGX_EVENT_ACCEPTEX_H_INCLUDED_
-#define _NGX_EVENT_ACCEPTEX_H_INCLUDED_
-
-
-#include <ngx_listen.h>
-#include <ngx_event.h>
-
-
-int ngx_event_acceptex(ngx_event_t *ev);
-int ngx_event_post_acceptex(ngx_listen_t *ls, int n);
-
-
-#endif /* _NGX_EVENT_ACCEPTEX_H_INCLUDED_ */
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -9,12 +9,12 @@ static int ngx_event_pipe_read_upstream(
 static int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p);
 
 static int ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p);
-ngx_inline static void ngx_remove_shadow_links(ngx_hunk_t *hunk);
-ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free,
-                                                       ngx_hunk_t *h);
-ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t **chain,
-                                                           ngx_chain_t *ce);
-static int ngx_drain_chains(ngx_event_pipe_t *p);
+ngx_inline static void ngx_event_pipe_remove_shadow_links(ngx_hunk_t *hunk);
+ngx_inline static void ngx_event_pipe_free_shadow_raw_hunk(ngx_chain_t **free,
+                                                           ngx_hunk_t *h);
+ngx_inline static void ngx_event_pipe_add_free_hunk(ngx_chain_t **chain,
+                                                    ngx_chain_t *cl);
+static int ngx_event_pipe_drain_chains(ngx_event_pipe_t *p);
 
 
 int ngx_event_pipe(ngx_event_pipe_t *p, int do_write)
@@ -57,7 +57,7 @@ int ngx_event_pipe_read_upstream(ngx_eve
 {
     int           n, rc, size;
     ngx_hunk_t   *h;
-    ngx_chain_t  *chain, *ce, *te;
+    ngx_chain_t  *chain, *cl, *tl;
 
     if (p->upstream_eof || p->upstream_error || p->upstream_done) {
         return NGX_OK;
@@ -131,8 +131,8 @@ int ngx_event_pipe_read_upstream(ngx_eve
                               NGX_ABORT);
                 p->hunks++;
 
-                ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT);
-                chain = te;
+                ngx_alloc_link_and_set_hunk(tl, h, p->pool, NGX_ABORT);
+                chain = tl;
 
             } else if (!p->cachable && p->downstream->write->ready) {
 
@@ -212,33 +212,33 @@ int ngx_event_pipe_read_upstream(ngx_eve
             }
         }
 
-        ce = chain;
+        cl = chain;
 
-        while (ce && n > 0) {
+        while (cl && n > 0) {
 
-            ngx_remove_shadow_links(ce->hunk);
+            ngx_event_pipe_remove_shadow_links(cl->hunk);
 
-            size = ce->hunk->end - ce->hunk->last;
+            size = cl->hunk->end - cl->hunk->last;
 
             if (n >= size) {
-                ce->hunk->last = ce->hunk->end;
+                cl->hunk->last = cl->hunk->end;
 
-    /* STUB */ ce->hunk->num = p->num++;
+    /* STUB */ cl->hunk->num = p->num++;
 
-                if (p->input_filter(p, ce->hunk) == NGX_ERROR) {
+                if (p->input_filter(p, cl->hunk) == NGX_ERROR) {
                     return NGX_ABORT;
                 }
 
                 n -= size;
-                ce = ce->next;
+                cl = cl->next;
 
             } else {
-                ce->hunk->last += n;
+                cl->hunk->last += n;
                 n = 0;
             }
         }
 
-        p->free_raw_hunks = ce;
+        p->free_raw_hunks = cl;
     }
 
     if ((p->upstream_eof || p->upstream_error) && p->free_raw_hunks) {
@@ -263,15 +263,15 @@ int ngx_event_pipe_read_upstream(ngx_eve
 
 int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
 {
-    size_t        busy_len;
+    size_t        bsize, to_write;
     ngx_hunk_t   *h;
-    ngx_chain_t  *out, **le, *ce, *te;
+    ngx_chain_t  *out, **ll, *cl, *tl;
 
     ngx_log_debug(p->log, "write downstream: %d" _ p->downstream->write->ready);
 
     for ( ;; ) {
         if (p->downstream_error) {
-            return ngx_drain_chains(p);
+            return ngx_event_pipe_drain_chains(p);
         }
 
         if ((p->upstream_eof || p->upstream_error || p->upstream_done)
@@ -285,95 +285,105 @@ int ngx_event_pipe_write_to_downstream(n
             break;
         }
 
-        busy_len = 0;
+        /*
+         * bsize is the busy hunks size
+         * to_write is the size of data that to be written
+         */
+
+        bsize = 0;
+        to_write = 0;
 
         if (!(p->upstream_eof || p->upstream_error || p->upstream_done)) {
-            /* calculate p->busy_len */
-            for (ce = p->busy; ce; ce = ce->next) {
-                busy_len += ngx_hunk_size(ce->hunk);
+            for (cl = p->busy; cl; cl = cl->next) {
+                bsize += cl->hunk->end - cl->hunk->start;
+                to_write += ngx_hunk_size(cl->hunk);
             }
         }
 
         out = NULL;
-        le = NULL;
+        ll = NULL;
 
         for ( ;; ) {
             if (p->out) {
-                ce = p->out;
+                cl = p->out;
 
                 if (!(p->upstream_eof || p->upstream_error || p->upstream_done)
-                    && (busy_len + ngx_hunk_size(ce->hunk) > p->max_busy_len))
+                    && (bsize + ngx_hunk_size(cl->hunk) > p->busy_size))
                 {
                     break;
                 }
 
                 p->out = p->out->next;
-                ngx_remove_shadow_free_raw_hunk(&p->free_raw_hunks, ce->hunk);
+                ngx_event_pipe_free_shadow_raw_hunk(&p->free_raw_hunks,
+                                                    cl->hunk);
 
-ngx_log_debug(p->log, "HUNK OUT: %d %x" _ ce->hunk->num _ ce->hunk->type);
+ngx_log_debug(p->log, "HUNK OUT: %d %x" _ cl->hunk->num _ cl->hunk->type);
 
             } else if (!p->cachable && p->in) {
-                ce = p->in;
+                cl = p->in;
 
                 if (!(p->upstream_eof || p->upstream_error || p->upstream_done)
-                    && (busy_len + ngx_hunk_size(ce->hunk) > p->max_busy_len))
+                    && (bsize + ngx_hunk_size(cl->hunk) > p->busy_size))
                 {
                     break;
                 }
 
                 p->in = p->in->next;
 
-ngx_log_debug(p->log, "HUNK IN: %d" _ ce->hunk->num);
+ngx_log_debug(p->log, "HUNK IN: %d" _ cl->hunk->num);
 
             } else {
                 break;
             }
 
-            busy_len += ngx_hunk_size(ce->hunk);
-            ce->next = NULL;
-            ngx_chain_add_ce(out, le, ce);
+            bsize += ngx_hunk_size(cl->hunk);
+            cl->next = NULL;
+            ngx_chain_add_link(out, ll, cl);
         }
 
         if (out == NULL) {
-            ngx_log_debug(p->log, "no hunks to write BUSY: %d" _ busy_len);
+            ngx_log_debug(p->log, "no hunks to write BUSY: %d" _ to_write);
 
-            if (!p->upstream_blocked || busy_len == 0) {
+            if (!(p->upstream_blocked && to_write)) {
                 break;
             }
 
-            /* if the upstream is blocked then write the busy hunks */
+            /*
+             * if the upstream is blocked and there are the busy hunks
+             * to write then write these hunks
+             */
         }
 
         if (p->output_filter(p->output_ctx, out) == NGX_ERROR) {
             p->downstream_error = 1;
 
-            /* handle the downstream error at the begin of the cycle.  */
+            /* handle the downstream error at the begin of a cycle */
 
             continue;
         }
 
         ngx_chain_update_chains(&p->free, &p->busy, &out, p->tag);
 
-        for (ce = p->free; ce; ce = ce->next) {
+        for (cl = p->free; cl; cl = cl->next) {
 
             /* add the free shadow raw hunk to p->free_raw_hunks */
 
-            if (ce->hunk->type & NGX_HUNK_LAST_SHADOW) {
-                h = ce->hunk->shadow;
+            if (cl->hunk->type & NGX_HUNK_LAST_SHADOW) {
+                h = cl->hunk->shadow;
                 h->pos = h->last = h->start;
                 h->shadow = NULL;
-                ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT);
-                ngx_add_after_partially_filled_hunk(&p->free_raw_hunks, te);
+                ngx_alloc_link_and_set_hunk(tl, h, p->pool, NGX_ABORT);
+                ngx_event_pipe_add_free_hunk(&p->free_raw_hunks, tl);
 
-                ce->hunk->type &= ~NGX_HUNK_LAST_SHADOW;
+                cl->hunk->type &= ~NGX_HUNK_LAST_SHADOW;
             }
-            ce->hunk->shadow = NULL;
+            cl->hunk->shadow = NULL;
 
-            if (p->cyclic_temp_file && (ce->hunk->type & NGX_HUNK_TEMP_FILE)) {
+            if (p->cyclic_temp_file && (cl->hunk->type & NGX_HUNK_TEMP_FILE)) {
 
                 /* reset p->temp_offset if all hunks had been sent */
 
-                if (ce->hunk->file_last == p->temp_offset) {
+                if (cl->hunk->file_last == p->temp_offset) {
                     p->temp_offset = 0;
                 }
             }
@@ -388,7 +398,7 @@ static int ngx_event_pipe_write_chain_to
 {
     int           rc, size, hsize;
     ngx_hunk_t   *h;
-    ngx_chain_t  *ce, *te, *next, *out, **le, **last_free;
+    ngx_chain_t  *cl, *tl, *next, *out, **ll, **last_free;
 
     ngx_log_debug(p->log, "write to file");
 
@@ -414,13 +424,13 @@ static int ngx_event_pipe_write_chain_to
     if (!p->cachable) {
 
         size = 0;
-        ce = p->in;
-        le = NULL;
+        cl = p->in;
+        ll = NULL;
 
 ngx_log_debug(p->log, "offset: %d" _ p->temp_offset);
 
         do {
-            hsize = ce->hunk->last - ce->hunk->pos;
+            hsize = cl->hunk->last - cl->hunk->pos;
 
 ngx_log_debug(p->log, "hunk size: %d" _ hsize);
 
@@ -431,16 +441,16 @@ ngx_log_debug(p->log, "hunk size: %d" _ 
             }
 
             size += hsize;
-            le = &ce->next;
-            ce = ce->next;
+            ll = &cl->next;
+            cl = cl->next;
 
-        } while (ce);
+        } while (cl);
 
 ngx_log_debug(p->log, "size: %d" _ size);
 
-        if (ce) {
-           p->in = ce;
-           *le = NULL;
+        if (cl) {
+           p->in = cl;
+           *ll = NULL;
 
         } else {
            p->in = NULL;
@@ -464,11 +474,11 @@ ngx_log_debug(p->log, "size: %d" _ size)
         /* void */
     }
 
-    for (ce = out; ce; ce = next) {
-        next = ce->next;
-        ce->next = NULL;
+    for (cl = out; cl; cl = next) {
+        next = cl->next;
+        cl->next = NULL;
 
-        h = ce->hunk;
+        h = cl->hunk;
         h->file = p->temp_file;
         h->file_pos = p->temp_offset;
         p->temp_offset += h->last - h->pos;
@@ -480,13 +490,13 @@ ngx_log_debug(p->log, "size: %d" _ size)
             h->type |= NGX_HUNK_FILE|NGX_HUNK_TEMP_FILE;
         }
 
-        ngx_chain_add_ce(p->out, p->last_out, ce);
+        ngx_chain_add_link(p->out, p->last_out, cl);
 
         if (h->type & NGX_HUNK_LAST_SHADOW) {
             h->shadow->last = h->shadow->pos = h->shadow->start;
-            ngx_alloc_ce_and_set_hunk(te, h->shadow, p->pool, NGX_ABORT);
-            *last_free = te;
-            last_free = &te->next;
+            ngx_alloc_link_and_set_hunk(tl, h->shadow, p->pool, NGX_ABORT);
+            *last_free = tl;
+            last_free = &tl->next;
         }
     }
 
@@ -499,7 +509,7 @@ ngx_log_debug(p->log, "size: %d" _ size)
 int ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_hunk_t *hunk)
 {
     ngx_hunk_t   *h;
-    ngx_chain_t  *ce;
+    ngx_chain_t  *cl;
 
     if (hunk->pos == hunk->last) {
         return NGX_OK;
@@ -519,15 +529,15 @@ int ngx_event_pipe_copy_input_filter(ngx
     h->type |= NGX_HUNK_LAST_SHADOW|NGX_HUNK_RECYCLED;
     hunk->shadow = h;
 
-    ngx_alloc_ce_and_set_hunk(ce, h, p->pool, NGX_ERROR);
+    ngx_alloc_link_and_set_hunk(cl, h, p->pool, NGX_ERROR);
 ngx_log_debug(p->log, "HUNK %d" _ h->num);
-    ngx_chain_add_ce(p->in, p->last_in, ce);
+    ngx_chain_add_link(p->in, p->last_in, cl);
 
     return NGX_OK;
 }
 
 
-ngx_inline static void ngx_remove_shadow_links(ngx_hunk_t *hunk)
+ngx_inline static void ngx_event_pipe_remove_shadow_links(ngx_hunk_t *hunk)
 {
     ngx_hunk_t  *h, *next;
 
@@ -554,11 +564,11 @@ ngx_inline static void ngx_remove_shadow
 }
 
 
-ngx_inline static void ngx_remove_shadow_free_raw_hunk(ngx_chain_t **free,
-                                                       ngx_hunk_t *h)
+ngx_inline static void ngx_event_pipe_free_shadow_raw_hunk(ngx_chain_t **free,
+                                                           ngx_hunk_t *h)
 {
     ngx_hunk_t   *s;
-    ngx_chain_t  *ce, **le;
+    ngx_chain_t  *cl, **ll;
 
     if (h->shadow == NULL) {
         return;
@@ -568,77 +578,77 @@ ngx_inline static void ngx_remove_shadow
         /* void */
     }
 
-    le = free;
+    ll = free;
 
-    for (ce = *free ; ce; ce = ce->next) {
-        if (ce->hunk == s) {
-            *le = ce->next;
+    for (cl = *free ; cl; cl = cl->next) {
+        if (cl->hunk == s) {
+            *ll = cl->next;
             break;
         }
 
-        if (ce->hunk->shadow) {
+        if (cl->hunk->shadow) {
             break;
         }
 
-        le = &ce->next;
+        ll = &cl->next;
     }
 }
 
 
-ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t **chain,
-                                                           ngx_chain_t *ce)
+ngx_inline static void ngx_event_pipe_add_free_hunk(ngx_chain_t **chain,
+                                                    ngx_chain_t *cl)
 {
     if (*chain == NULL) {
-        *chain = ce;
+        *chain = cl;
         return;
     }
 
     if ((*chain)->hunk->pos != (*chain)->hunk->last) {
-        ce->next = (*chain)->next;
-        (*chain)->next = ce;
+        cl->next = (*chain)->next;
+        (*chain)->next = cl;
 
     } else {
-        ce->next = (*chain);
-        (*chain) = ce;
+        cl->next = (*chain);
+        (*chain) = cl;
     }
 }
 
 
-static int ngx_drain_chains(ngx_event_pipe_t *p)
+static int ngx_event_pipe_drain_chains(ngx_event_pipe_t *p)
 {
     ngx_hunk_t   *h;
-    ngx_chain_t  *ce, *te;
+    ngx_chain_t  *cl, *tl;
 
     for ( ;; ) {
         if (p->busy) {
-            ce = p->busy;
+            cl = p->busy;
 
         } else if (p->out) {
-            ce = p->out;
+            cl = p->out;
 
         } else if (p->in) {
-            ce = p->in;
+            cl = p->in;
 
         } else {
             return NGX_OK;
         }
 
-        while (ce) {
-            if (ce->hunk->type & NGX_HUNK_LAST_SHADOW) {
-                h = ce->hunk->shadow;
-                /* THINK NEEDED ??? */ h->pos = h->last = h->start;
+        while (cl) {
+            if (cl->hunk->type & NGX_HUNK_LAST_SHADOW) {
+                h = cl->hunk->shadow;
+                h->pos = h->last = h->start;
                 h->shadow = NULL;
-                ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT);
-                ngx_add_after_partially_filled_hunk(&p->free_raw_hunks, te);
+                ngx_alloc_link_and_set_hunk(tl, h, p->pool, NGX_ABORT);
+                ngx_event_pipe_add_free_hunk(&p->free_raw_hunks, tl);
 
-                ce->hunk->type &= ~NGX_HUNK_LAST_SHADOW;
+                cl->hunk->type &= ~NGX_HUNK_LAST_SHADOW;
             }
 
-            ce->hunk->shadow = NULL;
-            te = ce->next;
-            ce->next = p->free;
-            p->free = ce;
-            ce = te;
+            cl->hunk->shadow = NULL;
+            tl = cl->next;
+            cl->next = p->free;
+            p->free = cl;
+            cl = tl;
         }
     }
 }
--- a/src/event/ngx_event_pipe.h
+++ b/src/event/ngx_event_pipe.h
@@ -50,7 +50,7 @@ struct ngx_event_pipe_s {
     ngx_bufs_t         bufs;
     ngx_hunk_tag_t     tag;
 
-    size_t             max_busy_len;
+    size_t             busy_size;
 
     off_t              temp_offset;
     off_t              max_temp_file_size;
--- a/src/http/modules/ngx_http_charset_filter.c
+++ b/src/http/modules/ngx_http_charset_filter.c
@@ -50,9 +50,9 @@ ngx_module_t  ngx_http_charset_filter_mo
 };
 
 
-static int (*next_header_filter) (ngx_http_request_t *r);
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
 #if 0
-static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 #endif
 
 
@@ -62,12 +62,12 @@ static int ngx_http_charset_header_filte
 
     if (r->headers_out.content_type == NULL
         || ngx_strncasecmp(r->headers_out.content_type->value.data,
-                                                           "text/", 5) != 0
+                                                              "text/", 5) != 0
         || ngx_strstr(r->headers_out.content_type->value.data, "charset")
                                                                        != NULL
        )
     {
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
@@ -75,15 +75,19 @@ static int ngx_http_charset_header_filte
     if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
         && r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
     {
-        /* do not set charset for the redirect because NN 4.x uses this
-           charset instead of the next page charset */
+
+        /*
+         * do not set charset for the redirect because NN 4.x uses this
+         * charset instead of the next page charset
+         */
+
         r->headers_out.charset.len = 0;
 
     } else if (r->headers_out.charset.len == 0) {
         r->headers_out.charset = lcf->default_charset;
     }
 
-    return next_header_filter(r);
+    return ngx_http_next_header_filter(r);
 }
 
 
@@ -91,18 +95,18 @@ static int ngx_http_charset_header_filte
 static int ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
     ngx_log_debug(r->connection->log, "CHARSET BODY");
-    return next_body_filter(r, in);
+    return ngx_http_next_body_filter(r, in);
 }
 #endif
 
 
 static int ngx_http_charset_filter_init(ngx_cycle_t *cycle)
 {
-    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_charset_header_filter;
 
 #if 0
-    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_charset_body_filter;
 #endif
 
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -29,14 +29,14 @@ ngx_module_t  ngx_http_chunked_filter_mo
 };
 
 
-static int (*next_header_filter) (ngx_http_request_t *r);
-static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 
 
 static int ngx_http_chunked_header_filter(ngx_http_request_t *r)
 {
     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     if (r->headers_out.content_length_n == -1) {
@@ -48,7 +48,7 @@ static int ngx_http_chunked_header_filte
         }
     }
 
-    return next_header_filter(r);
+    return ngx_http_next_header_filter(r);
 }
 
 
@@ -57,36 +57,31 @@ static int ngx_http_chunked_body_filter(
     char         *chunk;
     size_t        size, len;
     ngx_hunk_t   *h;
-    ngx_chain_t  *out, *ce, *te, **le;
+    ngx_chain_t  *out, *cl, *tl, **ll;
 
     if (in == NULL || !r->chunked) {
-        return next_body_filter(r, in);
+        return ngx_http_next_body_filter(r, in);
     }
 
-    ngx_test_null(out, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-    le = &out->next;
+    ngx_test_null(out, ngx_alloc_chain_link(r->pool), NGX_ERROR);
+    ll = &out->next;
 
     size = 0;
-    ce = in;
+    cl = in;
 
     for ( ;; ) {
-
-        if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-            size += ce->hunk->last - ce->hunk->pos;
-        } else {
-            size += (size_t) (ce->hunk->file_last - ce->hunk->file_pos);
-        }
+        size += ngx_hunk_size(cl->hunk);
 
-        ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-        te->hunk = ce->hunk;
-        *le = te;
-        le = &te->next;
+        ngx_test_null(tl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
+        tl->hunk = cl->hunk;
+        *ll = tl;
+        ll = &tl->next;
 
-        if (ce->next == NULL) {
+        if (cl->next == NULL) {
             break;
         }
 
-        ce = ce->next;
+        cl = cl->next;
     }
 
     ngx_test_null(chunk, ngx_palloc(r->pool, 11), NGX_ERROR);
@@ -101,8 +96,8 @@ static int ngx_http_chunked_body_filter(
 
     ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
 
-    if (ce->hunk->type & NGX_HUNK_LAST) {
-        ce->hunk->type &= ~NGX_HUNK_LAST;
+    if (cl->hunk->type & NGX_HUNK_LAST) {
+        cl->hunk->type &= ~NGX_HUNK_LAST;
         h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY|NGX_HUNK_LAST;
         h->pos = CRLF "0" CRLF CRLF;
         h->last = h->pos + 7;
@@ -113,21 +108,19 @@ static int ngx_http_chunked_body_filter(
         h->last = h->pos + 2;
     }
 
-    ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-    te->hunk = h;
-    te->next = NULL;
-    *le = te;
+    ngx_alloc_link_and_set_hunk(tl, h, r->pool, NGX_ERROR);
+    *ll = tl;
 
-    return next_body_filter(r, out);
+    return ngx_http_next_body_filter(r, out);
 }
 
 
 static int ngx_http_chunked_filter_init(ngx_cycle_t *cycle)
 {
-    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_chunked_header_filter;
 
-    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_chunked_body_filter;
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -7,9 +7,9 @@
 
 
 typedef struct {
-    int         enable;
-    ngx_bufs_t  bufs;
-    int         no_buffer;
+    int            enable;
+    ngx_bufs_t     bufs;
+    int            no_buffer;
 } ngx_http_gzip_conf_t;
 
 
@@ -111,9 +111,8 @@ struct gztrailer {
 #endif
 
 
-
-static int (*next_header_filter) (ngx_http_request_t *r);
-static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 
 
 static int ngx_http_gzip_header_filter(ngx_http_request_t *r)
@@ -134,7 +133,7 @@ static int ngx_http_gzip_header_filter(n
         || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL
        )
     {
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     /* TODO: "text/html" -> custom types */
@@ -142,7 +141,7 @@ static int ngx_http_gzip_header_filter(n
         && ngx_strncasecmp(r->headers_out.content_type->value.data,
                                                           "text/html", 5) != 0)
     {
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     ngx_http_create_ctx(r, ctx, ngx_http_gzip_filter_module,
@@ -162,7 +161,7 @@ static int ngx_http_gzip_header_filter(n
     r->headers_out.content_length = NULL;
     r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY;
 
-    return next_header_filter(r);
+    return ngx_http_next_header_filter(r);
 }
 
 
@@ -171,14 +170,14 @@ static int ngx_http_gzip_body_filter(ngx
     int                    rc, wbits, mem_level, zin, zout, last;
     struct gztrailer      *trailer;
     ngx_hunk_t            *h;
-    ngx_chain_t           *ce;
+    ngx_chain_t           *cl;
     ngx_http_gzip_ctx_t   *ctx;
     ngx_http_gzip_conf_t  *conf;
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
 
     if (ctx == NULL) {
-        return next_body_filter(r, in);
+        return ngx_http_next_body_filter(r, in);
     }
 
     conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
@@ -218,12 +217,9 @@ static int ngx_http_gzip_body_filter(ngx
         h->pos = gzheader;
         h->last = h->pos + 10;
 
-        ngx_test_null(ce, ngx_alloc_chain_entry(r->pool),
-                      ngx_http_gzip_error(ctx));
-        ce->hunk = h;
-        ce->next = NULL;
-        ctx->out = ce;
-        ctx->last_out = &ce->next;
+        ngx_alloc_link_and_set_hunk(cl, h, r->pool, ngx_http_gzip_error(ctx));
+        ctx->out = cl;
+        ctx->last_out = &cl->next;
 
         ctx->crc32 = crc32(0L, Z_NULL, 0);
         ctx->flush = Z_NO_FLUSH;
@@ -319,10 +315,10 @@ ngx_log_debug(r->connection->log, "DEFLA
 
             if (ctx->zstream.avail_out == 0) {
                 ctx->out_hunk->last += conf->bufs.size;
-                ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
-                                      ngx_http_gzip_error(ctx));
-                *ctx->last_out = ce;
-                ctx->last_out = &ce->next;
+                ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                            ngx_http_gzip_error(ctx));
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
                 ctx->redo = 1;
 
             } else {
@@ -333,10 +329,10 @@ ngx_log_debug(r->connection->log, "DEFLA
                     ctx->out_hunk->type |= NGX_HUNK_FLUSH;
                     ctx->flush = Z_NO_FLUSH;
 
-                    ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
-                                          ngx_http_gzip_error(ctx));
-                    *ctx->last_out = ce;
-                    ctx->last_out = &ce->next;
+                    ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                                ngx_http_gzip_error(ctx));
+                    *ctx->last_out = cl;
+                    ctx->last_out = &cl->next;
 
                     break;
 
@@ -355,10 +351,10 @@ ngx_log_debug(r->connection->log, "DEFLA
 
                     ctx->flush = Z_NO_FLUSH;
 
-                    ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
-                                          ngx_http_gzip_error(ctx));
-                    *ctx->last_out = ce;
-                    ctx->last_out = &ce->next;
+                    ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                                ngx_http_gzip_error(ctx));
+                    *ctx->last_out = cl;
+                    ctx->last_out = &cl->next;
 
                     if (ctx->zstream.avail_out >= 8) {
                         trailer = (struct gztrailer *) ctx->out_hunk->last;
@@ -372,12 +368,10 @@ ngx_log_debug(r->connection->log, "DEFLA
 
                         h->type |= NGX_HUNK_LAST;
 
-                        ngx_test_null(ce, ngx_alloc_chain_entry(r->pool),
-                                      ngx_http_gzip_error(ctx));
-                        ce->hunk = h;
-                        ce->next = NULL;
-                        *ctx->last_out = ce;
-                        ctx->last_out = &ce->next;
+                        ngx_alloc_link_and_set_hunk(cl, h, r->pool,
+                                                    ngx_http_gzip_error(ctx));
+                        *ctx->last_out = cl;
+                        ctx->last_out = &cl->next;
                         trailer = (struct gztrailer *) h->pos;
                         h->last += 8;
                     }
@@ -399,10 +393,10 @@ ngx_log_debug(r->connection->log, "DEFLA
                     break;
 
                 } else if (conf->no_buffer && ctx->in == NULL) {
-                    ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
-                                          ngx_http_gzip_error(ctx));
-                    *ctx->last_out = ce;
-                    ctx->last_out = &ce->next;
+                    ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                                ngx_http_gzip_error(ctx));
+                    *ctx->last_out = cl;
+                    ctx->last_out = &cl->next;
 
                     break;
                 }
@@ -413,7 +407,7 @@ ngx_log_debug(r->connection->log, "DEFLA
             return last;
         }
 
-        last = next_body_filter(r, ctx->out);
+        last = ngx_http_next_body_filter(r, ctx->out);
 
         if (last == NGX_ERROR) {
             return ngx_http_gzip_error(ctx);
@@ -443,10 +437,10 @@ ngx_inline static int ngx_http_gzip_erro
 
 static int ngx_http_gzip_filter_init(ngx_cycle_t *cycle)
 {
-    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_gzip_header_filter;
 
-    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_gzip_body_filter;
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_not_modified_filter.c
+++ b/src/http/modules/ngx_http_not_modified_filter.c
@@ -30,7 +30,7 @@ ngx_module_t  ngx_http_not_modified_filt
 };
 
 
-static int (*next_header_filter) (ngx_http_request_t *r);
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
 
 
 static int ngx_http_not_modified_header_filter(ngx_http_request_t *r)
@@ -41,7 +41,7 @@ static int ngx_http_not_modified_header_
         || r->headers_in.if_modified_since == NULL
         || r->headers_out.last_modified_time == -1)
     {
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
@@ -50,7 +50,9 @@ static int ngx_http_not_modified_header_
     ngx_log_debug(r->connection->log, "%d %d" _
                   ims _ r->headers_out.last_modified_time);
 
-    /* I think that the equality of the dates is correcter */
+    /*
+     * I think that the equality of the dates is correcter
+     */
 
     if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) {
         r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
@@ -61,13 +63,13 @@ static int ngx_http_not_modified_header_
         r->headers_out.accept_ranges->key.len = 0;
     }
 
-    return next_header_filter(r);
+    return ngx_http_next_header_filter(r);
 }
 
 
 static int ngx_http_not_modified_filter_init(ngx_cycle_t *cycle)
 {
-    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_not_modified_header_filter;
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -34,8 +34,8 @@ ngx_module_t  ngx_http_range_filter_modu
 };
 
 
-static int (*next_header_filter) (ngx_http_request_t *r);
-static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 
 
 static int ngx_http_range_header_filter(ngx_http_request_t *r)
@@ -53,7 +53,7 @@ static int ngx_http_range_header_filter(
         /* STUB: we currently support ranges for file hunks only */
         || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
     {
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     if (r->headers_in.range == NULL
@@ -69,7 +69,7 @@ static int ngx_http_range_header_filter(
         r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
         r->headers_out.accept_ranges->value.data = "bytes";
 
-        return next_header_filter(r);
+        return ngx_http_next_header_filter(r);
     }
 
     ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t),
@@ -279,7 +279,7 @@ static int ngx_http_range_header_filter(
         }
     }
 
-    return next_header_filter(r);
+    return ngx_http_next_header_filter(r);
 }
 
 
@@ -287,16 +287,18 @@ static int ngx_http_range_body_filter(ng
 {
     int                           i;
     ngx_hunk_t                   *h;
-    ngx_chain_t                  *out, *hce, *rce, *dce, **le;
+    ngx_chain_t                  *out, *hcl, *rcl, *dcl, **ll;
     ngx_http_range_t             *range;
     ngx_http_range_filter_ctx_t  *ctx;
 
     if (r->headers_out.ranges.nelts == 0) {
-        return next_body_filter(r, in);
+        return ngx_http_next_body_filter(r, in);
     }
 
-    /* the optimized version for the static files only
-       that are passed in the single file hunk */
+    /*
+     * the optimized version for the static files only
+     * that are passed in the single file hunk
+     */
 
     if (in
         && in->hunk->type & NGX_HUNK_FILE
@@ -307,11 +309,11 @@ static int ngx_http_range_body_filter(ng
             in->hunk->file_pos = range->start;
             in->hunk->file_last = range->end;
 
-            return next_body_filter(r, in);
+            return ngx_http_next_body_filter(r, in);
         }
 
         ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module);
-        le = &out;
+        ll = &out;
 
         range = r->headers_out.ranges.elts;
         for (i = 0; i < r->headers_out.ranges.nelts; i++) {
@@ -321,16 +323,16 @@ static int ngx_http_range_body_filter(ng
             h->pos = ctx->boundary_header.data;
             h->last = ctx->boundary_header.data + ctx->boundary_header.len;
 
-            ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-            hce->hunk = h;
+            ngx_test_null(hcl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
+            hcl->hunk = h;
 
             ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
             h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
             h->pos = range[i].content_range.data;
             h->last = range[i].content_range.data + range[i].content_range.len;
 
-            ngx_test_null(rce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-            rce->hunk = h;
+            ngx_test_null(rcl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
+            rcl->hunk = h;
 
             ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
             h->type = NGX_HUNK_FILE;
@@ -338,14 +340,12 @@ static int ngx_http_range_body_filter(ng
             h->file_last = range[i].end;
             h->file = in->hunk->file;
 
-            ngx_test_null(dce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-            dce->hunk = h;
-            dce->next = NULL;
+            ngx_alloc_link_and_set_hunk(dcl, h, r->pool, NGX_ERROR);
 
-            *le = hce;
-            hce->next = rce;
-            rce->next = dce;
-            le = &dce->next;
+            *ll = hcl;
+            hcl->next = rcl;
+            rcl->next = dcl;
+            ll = &dcl->next;
         }
 
         ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
@@ -355,27 +355,25 @@ static int ngx_http_range_body_filter(ng
         *h->last++ = '-'; *h->last++ = '-';
         *h->last++ = CR; *h->last++ = LF;
 
-        ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
-        hce->hunk = h;
-        hce->next = NULL;
-        *le = hce;
+        ngx_alloc_link_and_set_hunk(hcl, h, r->pool, NGX_ERROR);
+        *ll = hcl;
 
-        return next_body_filter(r, out);
+        return ngx_http_next_body_filter(r, out);
     }
 
     /* TODO: several incoming hunks of proxied responses
              and memory hunks on platforms that have no sendfile() */
 
-    return next_body_filter(r, in);
+    return ngx_http_next_body_filter(r, in);
 }
 
 
 static int ngx_http_range_filter_init(ngx_cycle_t *cycle)
 {
-    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_range_header_filter;
 
-    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_range_body_filter;
 
     return NGX_OK;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -26,6 +26,8 @@ static void ngx_http_proxy_close_connect
 
 static int ngx_http_proxy_init(ngx_cycle_t *cycle);
 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
+                                           void *parent, void *child);
 
 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
                                      void *conf);
@@ -42,6 +44,62 @@ static ngx_command_t ngx_http_proxy_comm
      0,
      NULL},
 
+    {ngx_string("proxy_connect_timeout"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_msec_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, connect_timeout),
+     NULL},
+
+    {ngx_string("proxy_send_timeout"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_msec_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, send_timeout),
+     NULL},
+
+    {ngx_string("proxy_header_buffer_size"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_size_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, header_buffer_size),
+     NULL},
+
+    {ngx_string("proxy_read_timeout"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_msec_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, read_timeout),
+     NULL},
+
+    {ngx_string("proxy_buffers"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+     ngx_conf_set_bufs_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, bufs),
+     NULL},
+
+    {ngx_string("proxy_busy_buffers_size"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_size_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size),
+     NULL},
+
+    {ngx_string("proxy_temp_path"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
+     ngx_conf_set_path_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, temp_path),
+     NULL},
+
+    {ngx_string("proxy_temp_file_write_size"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_size_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size),
+     NULL},
+
     ngx_null_command
 };
 
@@ -54,11 +112,7 @@ ngx_http_module_t  ngx_http_proxy_module
     NULL,                                  /* merge server configuration */
 
     ngx_http_proxy_create_loc_conf,        /* create location configration */
-#if 0
-    ngx_http_proxy_merge_conf              /* merge location configration */
-#endif
-
-    NULL
+    ngx_http_proxy_merge_loc_conf          /* merge location configration */
 };
 
 
@@ -108,7 +162,7 @@ static ngx_http_header_t headers_in[] = 
 
 static char http_version[] = " HTTP/1.0" CRLF;
 static char host_header[] = "Host: ";
-static char conn_close_header[] = "Connection: close" CRLF;
+static char connection_close_header[] = "Connection: close" CRLF;
 
 
 
@@ -168,7 +222,7 @@ static ngx_chain_t *ngx_http_proxy_creat
           + sizeof(http_version) - 1
           + sizeof(host_header) - 1 + p->host_header.len + 2
                                                           /* 2 is for "\r\n" */
-          + sizeof(conn_close_header) - 1
+          + sizeof(connection_close_header) - 1
           + 2;                          /* 2 is for "\r\n" at the header end */
 
     header = (ngx_table_elt_t *) r->headers_in.headers->elts;
@@ -189,7 +243,7 @@ static ngx_chain_t *ngx_http_proxy_creat
     /* STUB */ len++;
 
     ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL);
-    ngx_add_hunk_to_chain(chain, h, r->pool, NULL);
+    ngx_alloc_link_and_set_hunk(chain, h, r->pool, NULL);
 
 
     /* the request line */
@@ -220,8 +274,8 @@ static ngx_chain_t *ngx_http_proxy_creat
 
     /* the "Connection: close" header */
 
-    h->last = ngx_cpymem(h->last, conn_close_header,
-                         sizeof(conn_close_header) - 1);
+    h->last = ngx_cpymem(h->last, connection_close_header,
+                         sizeof(connection_close_header) - 1);
 
 
     for (i = 0; i < r->headers_in.headers->nelts; i++) {
@@ -341,8 +395,7 @@ static void ngx_http_proxy_send_request(
 #if (NGX_SUPPRESS_WARN)
                 le = NULL;
 #endif
-                p->work_request_hunks =
-                                       ngx_alloc_chain_entry(p->request->pool);
+                p->work_request_hunks = ngx_alloc_chain_link(p->request->pool);
                 if (p->work_request_hunks == NULL) {
                     ngx_http_proxy_finalize_request(p,
                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -357,7 +410,7 @@ static void ngx_http_proxy_send_request(
                     le = &te->next;
                     ce->hunk->pos = ce->hunk->start;
 
-                    te = ngx_alloc_chain_entry(p->request->pool);
+                    te = ngx_alloc_chain_link(p->request->pool);
                     if (te == NULL) {
                         ngx_http_proxy_finalize_request(p,
                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -404,7 +457,7 @@ static void ngx_http_proxy_process_upstr
 
     if (p->header_in == NULL) {
         p->header_in = ngx_create_temp_hunk(p->request->pool,
-                                            p->lcf->header_size,
+                                            p->lcf->header_buffer_size,
                                             0, 0);
         if (p->header_in == NULL) {
             ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -563,10 +616,6 @@ static void ngx_http_proxy_process_upstr
 
             /* there was error while a header line parsing */
 
-#if 0
-            ngx_http_header_parse_error(r, rc);
-            ngx_http_proxy_next_upstream(p);
-#endif
             ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
             return;
         }
@@ -692,10 +741,8 @@ static void ngx_http_proxy_send_response
 
     /* */
 
-#if 0
-    /* TODO: look "Content-Length" */
-    p->block_size = p->lcf->block_size;
-#endif
+
+    /* TODO: preallocate event_pipe hunks, look "Content-Length" */
 
     r->headers_out.status = p->status;
 
@@ -715,7 +762,7 @@ static void ngx_http_proxy_send_response
     ep->output_ctx = r;
     ep->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module;
     ep->bufs = p->lcf->bufs;
-    ep->max_busy_len = p->lcf->max_busy_len;
+    ep->busy_size = p->lcf->busy_buffers_size;
     ep->upstream = p->upstream.connection;
     ep->downstream = r->connection;
     ep->pool = r->pool;
@@ -736,7 +783,7 @@ static void ngx_http_proxy_send_response
     ep->temp_file_warn = "an upstream response is buffered "
                          "to a temporary file";
 
-    ep->preread_hunks = ngx_alloc_chain_entry(r->pool);
+    ep->preread_hunks = ngx_alloc_chain_link(r->pool);
     if (ep->preread_hunks == NULL) {
         ngx_http_proxy_finalize_request(p, 0);
         return;
@@ -758,8 +805,8 @@ static void ngx_http_proxy_send_response
 
         /*
          * we need to disable the use of sendfile() if we use cyclic temp file
-         * because the writing a new data can interfere with sendfile
-         * that uses the same kernel file pages
+         * because the writing a new data can interfere with sendfile()
+         * that uses the same kernel file pages (at least on FreeBSD)
          */
 
         ep->cyclic_temp_file = 1;
@@ -1160,58 +1207,72 @@ static void *ngx_http_proxy_create_loc_c
                   ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)),
                   NGX_CONF_ERROR);
 
-    /* STUB */
-    ngx_test_null(conf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)),
-                  NGX_CONF_ERROR);
+    /* set by ngx_pcalloc():
+
+    conf->bufs.num = 0;
 
-    conf->peers->number = 1;
-    conf->peers->peers[0].addr = inet_addr("127.0.0.1");
-    conf->peers->peers[0].host.data = "localhost";
-    conf->peers->peers[0].host.len = sizeof("localhost") - 1;
-    conf->peers->peers[0].port = htons(9000);
-    conf->peers->peers[0].addr_port_text.data = "127.0.0.1:9000";
-    conf->peers->peers[0].addr_port_text.len = sizeof("127.0.0.1:9000") - 1;
+    conf->path = NULL;
 
-    conf->connect_timeout = 30000;
-    conf->send_timeout = 30000;
-    conf->header_size = 4096;
-    conf->read_timeout = 30000;
+    conf->upstreams = NULL;
+    conf->peers = NULL;
 
-    conf->bufs.num = 5;
-    conf->bufs.size = 4096;
-    conf->max_busy_len = 8192;
-
+    */
 
-    /* CHECK in _init conf->max_temp_size >= conf->bufs.size !!! */
-    conf->max_temp_file_size = 4096 * 3;
-
-
-    conf->temp_file_write_size = 4096 * 2;
-    conf->cyclic_temp_file= 1;
-
-    ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)),
-                  NULL);
+    conf->connect_timeout = NGX_CONF_UNSET;
+    conf->send_timeout = NGX_CONF_UNSET;
+    conf->header_buffer_size = NGX_CONF_UNSET;
+    conf->read_timeout = NGX_CONF_UNSET;
+    conf->busy_buffers_size = NGX_CONF_UNSET;
 
-    conf->temp_path->name.data = "temp";
-    conf->temp_path->name.len = 4;
-    conf->temp_path->level[0] = 1;
-    conf->temp_path->level[1] = 2;
-    conf->temp_path->level[2] = 3;
-    conf->temp_path->len = 0;
+    /*
+     * "proxy_max_temp_file_size" is hardcoded to 1G for reverse proxy,
+     * it should be configurable in the generic proxy
+     */
+    conf->max_temp_file_size = 1024 * 1024 * 1024;
 
-    for (i = 0; i < 3; i++) {
-        if (conf->temp_path->level[i] == 0) {
-            break;
-        }
-        conf->temp_path->len += conf->temp_path->level[i] + 1;
-    }
+    conf->temp_file_write_size = NGX_CONF_UNSET;
 
-    /* */
+    /* "proxy_cyclic_temp_file" is disabled */
+    conf->cyclic_temp_file = 0;
 
     return conf;
 }
 
 
+static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
+                                           void *parent, void *child)
+{
+    ngx_http_proxy_loc_conf_t *prev = parent;
+    ngx_http_proxy_loc_conf_t *conf = child;
+
+    ngx_conf_merge_msec_value(conf->connect_timeout,
+                              prev->connect_timeout, 60000);
+    ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000);
+    ngx_conf_merge_size_value(conf->header_buffer_size,
+                              prev->header_buffer_size, 4096);
+    ngx_conf_merge_msec_value(conf->read_timeout, prev->read_timeout, 30000);
+    ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, 4096);
+    ngx_conf_merge_size_value(conf->busy_buffers_size,
+                              prev->busy_buffers_size, 8192);
+
+#if 0
+    if (conf->max_temp_file_size > conf->bufs.size) {
+        return "\"proxy_max_temp_file\" must be greater "
+               "than one of the \"proxy_buffers\"";
+    }
+#endif
+
+    ngx_conf_merge_size_value(conf->temp_file_write_size,
+                              prev->temp_file_write_size, 16384);
+
+    ngx_conf_merge_path_value(conf->temp_path, prev->temp_path,
+                              "temp", 1, 2, 0, cf->pool);
+
+    return NULL;
+}
+
+
+
 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
                                      void *conf)
 {
@@ -1337,6 +1398,7 @@ static char *ngx_http_proxy_set_pass(ngx
     return NULL;
 }
 
+
 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
                                            ngx_http_proxy_upstream_t *u)
 {
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -21,17 +21,15 @@ typedef struct {
 typedef struct {
     ngx_msec_t                  connect_timeout;
     ngx_msec_t                  send_timeout;
-    ssize_t                     header_size;
+    ssize_t                     header_buffer_size;
     ngx_msec_t                  read_timeout;
 
     ngx_bufs_t                  bufs;
+    ssize_t                     busy_buffers_size;
 
-    /* STUB names */
-    int                         max_busy_len;
-    int                         max_temp_file_size;
-    int                         temp_file_write_size;
+    ssize_t                     max_temp_file_size;
+    ssize_t                     temp_file_write_size;
     int                         cyclic_temp_file;
-    /* */
 
     ngx_path_t                 *temp_path;
 
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -17,12 +17,6 @@ typedef struct {
 } ngx_http_log_ctx_t;
 
 
-typedef int (*ngx_http_output_header_filter_p)(ngx_http_request_t *r);
-
-typedef int (*ngx_http_output_body_filter_p)
-                                   (ngx_http_request_t *r, ngx_chain_t *chain);
-
-
 #define ngx_http_get_module_ctx(r, module)       r->ctx[module.ctx_index]
 
 #define ngx_http_create_ctx(r, cx, module, size, error)                       \
@@ -82,13 +76,6 @@ extern ngx_module_t  ngx_http_module;
 extern int  ngx_max_module;
 
 
-extern ngx_array_t  ngx_http_translate_handlers;
-extern ngx_array_t  ngx_http_index_handlers;
-
-extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
-extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
-
-
 /* STUB */
 int ngx_http_log_handler(ngx_http_request_t *r);
 /**/
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -226,6 +226,7 @@ void ngx_http_handler(ngx_http_request_t
     }
 
 #if 0
+    /* TEST STUB */ r->http_version = NGX_HTTP_VERSION_10;
     /* TEST STUB */ r->keepalive = 0;
 #endif
 
--- a/src/http/ngx_http_filter.h
+++ b/src/http/ngx_http_filter.h
@@ -7,12 +7,17 @@
 #define NGX_HTTP_FILTER_NEED_TEMP           4
 
 
-int ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in);
-int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
+typedef int (*ngx_http_output_header_filter_pt)(ngx_http_request_t *r);
+typedef int (*ngx_http_output_body_filter_pt)
+                                   (ngx_http_request_t *r, ngx_chain_t *chain);
 
 
-extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
-extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+int ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *chain);
+int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain);
+
+
+extern ngx_http_output_header_filter_pt  ngx_http_top_header_filter;
+extern ngx_http_output_body_filter_pt    ngx_http_top_body_filter;
 
 
 #endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -371,5 +371,6 @@ static int ngx_http_header_filter(ngx_ht
 static int ngx_http_header_filter_init(ngx_cycle_t *cycle)
 {
     ngx_http_top_header_filter = ngx_http_header_filter;
+
     return NGX_OK;
 }
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -32,6 +32,8 @@ typedef struct {
 } ngx_http_output_filter_ctx_t;
 
 
+ngx_inline static int ngx_http_output_filter_need_to_copy(ngx_http_request_t *r,
+                                                          ngx_hunk_t *hunk);
 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src,
                                             int sendfile);
 static void *ngx_http_output_filter_create_conf(ngx_conf_t *cf);
@@ -74,23 +76,12 @@ ngx_module_t  ngx_http_output_filter_mod
 };
 
 
-#define ngx_next_filter  (*ngx_http_top_body_filter)
-
-#define need_to_copy(r, hunk)                                             \
-            (!ngx_hunk_special(hunk)                                      \
-             && (!r->sendfile                                             \
-                 || ((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)         \
-                   && (hunk->type & NGX_HUNK_IN_MEMORY) == 0)             \
-                 || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)              \
-                  && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))))
-
-
 
 int ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
     int                             rc, last;
     ssize_t                         size;
-    ngx_chain_t                    *ce;
+    ngx_chain_t                    *cl;
     ngx_http_output_filter_ctx_t   *ctx;
     ngx_http_output_filter_conf_t  *conf;
 
@@ -112,11 +103,13 @@ int ngx_http_output_filter(ngx_http_requ
     if (ctx->in == NULL) {
 
         if (in == NULL) {
-            return ngx_next_filter(r, in);
+            return ngx_http_top_body_filter(r, in);
         }
 
-        if (in->next == NULL && (!need_to_copy(r, in->hunk))) {
-            return ngx_next_filter(r, in);
+        if (in->next == NULL
+            && (!ngx_http_output_filter_need_to_copy(r, in->hunk)))
+        {
+            return ngx_http_top_body_filter(r, in);
         }
     }
 
@@ -137,16 +130,16 @@ int ngx_http_output_filter(ngx_http_requ
 
         while (ctx->in) {
 
-            if (!need_to_copy(r, ctx->in->hunk)) {
+            if (!ngx_http_output_filter_need_to_copy(r, ctx->in->hunk)) {
 
-                /* move the chain entry to the chain ctx->out */
+                /* move the chain link to the chain ctx->out */
 
-                ce = ctx->in;
-                ctx->in = ce->next;
+                cl = ctx->in;
+                ctx->in = cl->next;
 
-                *ctx->last_out = ce;
-                ctx->last_out = &ce->next;
-                ce->next = NULL;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+                cl->next = NULL;
 
                 continue;
             }
@@ -204,9 +197,9 @@ int ngx_http_output_filter(ngx_http_requ
                 ctx->in = ctx->in->next;
             }
 
-            ngx_add_hunk_to_chain(ce, ctx->hunk, r->pool, NGX_ERROR);
-            *ctx->last_out = ce;
-            ctx->last_out = &ce->next;
+            ngx_alloc_link_and_set_hunk(cl, ctx->hunk, r->pool, NGX_ERROR);
+            *ctx->last_out = cl;
+            ctx->last_out = &cl->next;
             ctx->hunk = NULL;
 
             if (ctx->free == NULL) {
@@ -218,7 +211,7 @@ int ngx_http_output_filter(ngx_http_requ
             return last;
         }
 
-        last = ngx_next_filter(r, ctx->out);
+        last = ngx_http_top_body_filter(r, ctx->out);
 
         ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out,
                                (ngx_hunk_tag_t) &ngx_http_output_filter_module);
@@ -227,6 +220,34 @@ int ngx_http_output_filter(ngx_http_requ
 }
 
 
+ngx_inline static int ngx_http_output_filter_need_to_copy(ngx_http_request_t *r,
+                                                          ngx_hunk_t *hunk)
+{
+    if (ngx_hunk_special(hunk)) {
+        return 0;
+    }
+
+    if (!r->sendfile) {
+        return 1;
+    }
+
+    if ((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
+        && (!(hunk->type & NGX_HUNK_IN_MEMORY)))
+    {
+        return 1;
+    }
+
+
+    if ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)
+        && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+
 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src,
                                             int sendfile)
 {
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -49,17 +49,17 @@ static ngx_http_header_t headers_in[] = 
     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) },
     { ngx_string("If-Modified-Since"),
                          offsetof(ngx_http_headers_in_t, if_modified_since) },
+    { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
+
     { ngx_string("Content-Length"),
                             offsetof(ngx_http_headers_in_t, content_length) },
     { ngx_string("Accept-Encoding"),
                            offsetof(ngx_http_headers_in_t, accept_encoding) },
-
     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
 #if 0
     { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
 #endif
 
-    { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) },
 
     { ngx_null_string, 0 }
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -66,12 +66,12 @@ typedef struct {
     ngx_table_elt_t  *host;
     ngx_table_elt_t  *connection;
     ngx_table_elt_t  *if_modified_since;
+    ngx_table_elt_t  *user_agent;
+
     ngx_table_elt_t  *content_length;
+    ngx_table_elt_t  *accept_encoding;
     ngx_table_elt_t  *range;
 
-    ngx_table_elt_t  *accept_encoding;
-
-    ngx_table_elt_t  *user_agent;
     ngx_table_elt_t  *keep_alive;
 
     size_t            host_name_len;
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -154,7 +154,7 @@ int ngx_http_special_response_handler(ng
 {
     int           err, rc;
     ngx_hunk_t   *h;
-    ngx_chain_t  *out, **le, *ce;
+    ngx_chain_t  *out, **ll, *cl;
 
     r->headers_out.status = error;
 
@@ -219,15 +219,15 @@ int ngx_http_special_response_handler(ng
     }
 
     out = NULL;
-    le = NULL;
+    ll = NULL;
 
     ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
     h->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY;
     h->pos = error_pages[err].data;
     h->last = error_pages[err].data + error_pages[err].len;
 
-    ngx_alloc_ce_and_set_hunk(ce, h, r->pool, NGX_ERROR);
-    ngx_chain_add_ce(out, le, ce);
+    ngx_alloc_link_and_set_hunk(cl, h, r->pool, NGX_ERROR);
+    ngx_chain_add_link(out, ll, cl);
 
 
     ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
@@ -235,8 +235,8 @@ int ngx_http_special_response_handler(ng
     h->pos = error_tail;
     h->last = error_tail + sizeof(error_tail) - 1;
 
-    ngx_alloc_ce_and_set_hunk(ce, h, r->pool, NGX_ERROR);
-    ngx_chain_add_ce(out, le, ce);
+    ngx_alloc_link_and_set_hunk(cl, h, r->pool, NGX_ERROR);
+    ngx_chain_add_link(out, ll, cl);
 
     if (/* STUB: "msie_padding on/off" */ 1
         && r->http_version >= NGX_HTTP_VERSION_10
@@ -249,8 +249,8 @@ int ngx_http_special_response_handler(ng
         h->pos = msie_stub;
         h->last = msie_stub + sizeof(msie_stub) - 1;
 
-        ngx_alloc_ce_and_set_hunk(ce, h, r->pool, NGX_ERROR);
-        ngx_chain_add_ce(out, le, ce);
+        ngx_alloc_link_and_set_hunk(cl, h, r->pool, NGX_ERROR);
+        ngx_chain_add_link(out, ll, cl);
     }
 
     h->type |= NGX_HUNK_LAST;
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -60,7 +60,7 @@ int ngx_http_write_filter(ngx_http_reque
 {
     int                            last;
     off_t                          size, flush;
-    ngx_chain_t                   *ce, **le, *chain;
+    ngx_chain_t                   *cl, **ll, *chain;
     ngx_http_write_filter_ctx_t   *ctx;
     ngx_http_write_filter_conf_t  *conf;
 
@@ -74,20 +74,20 @@ int ngx_http_write_filter(ngx_http_reque
 
     size = flush = 0;
     last = 0;
-    le = &ctx->out;
+    ll = &ctx->out;
 
-    /* find the size, the flush point and the last entry of the saved chain */
+    /* find the size, the flush point and the last link of the saved chain */
 
-    for (ce = ctx->out; ce; ce = ce->next) {
-        le = &ce->next;
+    for (cl = ctx->out; cl; cl = cl->next) {
+        ll = &cl->next;
 
-        size += ngx_hunk_size(ce->hunk);
+        size += ngx_hunk_size(cl->hunk);
 
-        if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
+        if (cl->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
             flush = size;
         }
 
-        if (ce->hunk->type & NGX_HUNK_LAST) {
+        if (cl->hunk->type & NGX_HUNK_LAST) {
             last = 1;
         }
     }
@@ -95,20 +95,17 @@ int ngx_http_write_filter(ngx_http_reque
     /* add the new chain to the existent one */
 
     for (/* void */; in; in = in->next) {
-        ngx_test_null(ce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+        ngx_alloc_link_and_set_hunk(cl, in->hunk, r->pool, NGX_ERROR);
+        *ll = cl;
+        ll = &cl->next;
 
-        ce->hunk = in->hunk;
-        ce->next = NULL;
-        *le = ce;
-        le = &ce->next;
+        size += ngx_hunk_size(cl->hunk);
 
-        size += ngx_hunk_size(ce->hunk);
-
-        if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
+        if (cl->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
             flush = size;
         }
 
-        if (ce->hunk->type & NGX_HUNK_LAST) {
+        if (cl->hunk->type & NGX_HUNK_LAST) {
             last = 1;
         }
     }
@@ -124,7 +121,7 @@ int ngx_http_write_filter(ngx_http_reque
 
     /*
      * avoid the output if there is no last hunk, no flush point and
-     * size of the hunks is smaller then "buffer_output"
+     * the size of the hunks is smaller than "buffer_output" directive
      */
 
     if (!last && flush == 0 && size < conf->buffer_output) {
deleted file mode 100644
--- a/src/os/unix/freebsd/ngx_sendfile.c
+++ /dev/null
@@ -1,66 +0,0 @@
-
-#include <ngx_config.h>
-
-#if (HAVE_FREEBSD_SENDFILE)
-
-#include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_socket.h>
-#include <ngx_errno.h>
-#include <ngx_log.h>
-#include <ngx_connection.h>
-#include <ngx_sendv.h>
-#include <ngx_sendfile.h>
-
-/*
-  CHECK:
-       check sent if errno == EINTR then should return right sent.
-       EINTR should not occur according to man.
-*/
-
-
-int ngx_sendfile(ngx_connection_t *c,
-                 ngx_iovec_t *headers, int hdr_cnt,
-                 ngx_fd_t fd, off_t offset, size_t nbytes,
-                 ngx_iovec_t *trailers, int trl_cnt,
-                 off_t *sent, u_int flags)
-{
-    int             rc, i;
-    ngx_err_t       err;
-    struct sf_hdtr  hdtr;
-
-    hdtr.headers = headers;
-    hdtr.hdr_cnt = hdr_cnt;
-    hdtr.trailers = trailers;
-    hdtr.trl_cnt = trl_cnt;
-
-#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG)
-    for (i = 0; i < hdr_cnt; i++) {
-        nbytes += headers[i].iov_len;
-    }
-#endif
-
-    rc = sendfile(fd, c->fd, offset, nbytes, &hdtr, sent, flags);
-
-    if (rc == -1) {
-        err = ngx_errno;
-        if (err != NGX_EAGAIN && err != NGX_EINTR) {
-            ngx_log_error(NGX_LOG_ERR, c->log, err, "sendfile failed");
-
-            return NGX_ERROR;
-
-        } else {
-            ngx_log_error(NGX_LOG_INFO, c->log, err,
-                          "sendfile sent only %qd bytes", *sent);
-
-            return NGX_AGAIN;
-        }
-    }
-
-    ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _
-                  rc _ offset _ *sent _ nbytes);
-
-    return NGX_OK;
-}
-
-#endif
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -32,14 +32,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
     ngx_err_t        err;
     ngx_array_t      header, trailer;
     ngx_hunk_t      *file;
-    ngx_chain_t     *ce, *tail;
+    ngx_chain_t     *cl, *tail;
 
     if (!c->write->ready) {
         return in;
     }
 
     do {
-        ce = in;
+        cl = in;
         file = NULL;
         fsize = 0;
         hsize = 0;
@@ -51,80 +51,80 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
         ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec),
                        NGX_CHAIN_ERROR);
 
-        /* create the iovec and coalesce the neighbouring chain entries */
+        /* create the header iovec and coalesce the neighbouring hunks */
 
         prev = NULL;
         iov = NULL;
 
-        for (ce = in; ce; ce = ce->next) {
-            if (ngx_hunk_special(ce->hunk)) {
+        for (cl = in; cl; cl = cl->next) {
+            if (ngx_hunk_special(cl->hunk)) {
                 continue;
             }
 
-            if (!ngx_hunk_in_memory_only(ce->hunk)) {
+            if (!ngx_hunk_in_memory_only(cl->hunk)) {
                 break;
             }
 
-            if (prev == ce->hunk->pos) {
-                iov->iov_len += ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+            if (prev == cl->hunk->pos) {
+                iov->iov_len += cl->hunk->last - cl->hunk->pos;
+                prev = cl->hunk->last;
 
             } else {
                 ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
-                iov->iov_base = ce->hunk->pos;
-                iov->iov_len = ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+                iov->iov_base = cl->hunk->pos;
+                iov->iov_len = cl->hunk->last - cl->hunk->pos;
+                prev = cl->hunk->last;
             }
 
-            hsize += ce->hunk->last - ce->hunk->pos;
+            hsize += cl->hunk->last - cl->hunk->pos;
         }
 
         /* get the file hunk */
 
-        if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
-            file = ce->hunk;
+        if (cl && (cl->hunk->type & NGX_HUNK_FILE)) {
+            file = cl->hunk;
             fsize = (size_t) (file->file_last - file->file_pos);
             fprev = file->file_last;
-            ce = ce->next;
+            cl = cl->next;
 
             /* coalesce the neighbouring file hunks */
 
-            while (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
-                if (file->file->fd != ce->hunk->file->fd
-                    || fprev != ce->hunk->file_pos)
+            while (cl && (cl->hunk->type & NGX_HUNK_FILE)) {
+                if (file->file->fd != cl->hunk->file->fd
+                    || fprev != cl->hunk->file_pos)
                 {
                     break;
                 }
 
-                fsize += (size_t) (ce->hunk->file_last - ce->hunk->file_pos);
-                fprev = ce->hunk->file_last;
-                ce = ce->next;
+                fsize += (size_t) (cl->hunk->file_last - cl->hunk->file_pos);
+                fprev = cl->hunk->file_last;
+                cl = cl->next;
             }
         }
 
-        /* create the iovec and coalesce the neighbouring chain entries */
+        /* create the tailer iovec and coalesce the neighbouring hunks */
 
         prev = NULL;
         iov = NULL;
 
-        for ( /* void */; ce; ce = ce->next) {
-            if (ngx_hunk_special(ce->hunk)) {
+        for ( /* void */; cl; cl = cl->next) {
+            if (ngx_hunk_special(cl->hunk)) {
                 continue;
             }
 
-            if (!ngx_hunk_in_memory_only(ce->hunk)) {
+            if (!ngx_hunk_in_memory_only(cl->hunk)) {
                 break;
             }
 
-            if (prev == ce->hunk->pos) {
-                iov->iov_len += ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+            if (prev == cl->hunk->pos) {
+                iov->iov_len += cl->hunk->last - cl->hunk->pos;
+                prev = cl->hunk->last;
 
             } else {
                 ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
-                iov->iov_base = ce->hunk->pos;
-                iov->iov_len = ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+                iov->iov_base = cl->hunk->pos;
+                iov->iov_len = cl->hunk->last - cl->hunk->pos;
+                prev = cl->hunk->last;
             }
         }
 
@@ -133,7 +133,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
          * a single sendfile() capability
          */
 
-        tail = ce;
+        tail = cl;
 
         if (file) {
 
@@ -155,7 +155,7 @@ ngx_log_debug(c->log, "NOPUSH");
             hdtr.trl_cnt = trailer.nelts;
 
             /*
-             * the old sendfile() "nbytes bug":
+             * the "nbytes bug" of the old sendfile() syscall:
              * http://www.freebsd.org/cgi/query-pr.cgi?pr=33771
              */
 
@@ -220,9 +220,9 @@ ngx_log_debug(c->log, "NOPUSH");
 
         c->sent += sent;
 
-        for (ce = in; ce; ce = ce->next) {
+        for (cl = in; cl; cl = cl->next) {
 
-            if (ngx_hunk_special(ce->hunk)) {
+            if (ngx_hunk_special(cl->hunk)) {
                 continue;
             }
 
@@ -230,41 +230,43 @@ ngx_log_debug(c->log, "NOPUSH");
                 break;
             }
 
-            size = ngx_hunk_size(ce->hunk);
+            size = ngx_hunk_size(cl->hunk);
 
             if (sent >= size) {
                 sent -= size;
 
-                if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-                    ce->hunk->pos = ce->hunk->last;
+                if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
+                    cl->hunk->pos = cl->hunk->last;
                 }
 
-                if (ce->hunk->type & NGX_HUNK_FILE) {
-                    ce->hunk->file_pos = ce->hunk->file_last;
+                if (cl->hunk->type & NGX_HUNK_FILE) {
+                    cl->hunk->file_pos = cl->hunk->file_last;
                 }
 
                 continue;
             }
 
-            if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-                ce->hunk->pos += sent;
+            if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
+                cl->hunk->pos += sent;
             }
 
-            if (ce->hunk->type & NGX_HUNK_FILE) {
-                ce->hunk->file_pos += sent;
+            if (cl->hunk->type & NGX_HUNK_FILE) {
+                cl->hunk->file_pos += sent;
             }
 
             break;
         }
 
-        in = ce;
+        in = cl;
 
         if (eagain) {
+
             /*
              * sendfile() can return EAGAIN even if it has sent
              * a whole file part and successive sendfile() would
-             * return EAGAIN right away and would not send anything.
+             * return EAGAIN right away and would not send anything
              */
+
             c->write->ready = 0;
             break;
         }
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -4,7 +4,7 @@
 #include <ngx_event.h>
 
 
-ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry)
+ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
 {
     ssize_t        n;
     struct iovec  *iov;
@@ -19,19 +19,17 @@ ssize_t ngx_readv_chain(ngx_connection_t
 
     /* TODO: coalesce the neighbouring chain entries */
 
-    while (entry) {
+    while (chain) {
         ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
-        iov->iov_base = entry->hunk->last;
-        iov->iov_len = entry->hunk->end - entry->hunk->last;
-        entry = entry->next;
+        iov->iov_base = chain->hunk->last;
+        iov->iov_len = chain->hunk->end - chain->hunk->last;
+        chain = chain->next;
     }
 
 ngx_log_debug(c->log, "recv: %d:%d" _ io.nelts _ iov->iov_len);
 
     n = readv(c->fd, (struct iovec *) io.elts, io.nelts);
 
-    ngx_destroy_array(&io);
-
     if (n == -1) {
         c->read->ready = 0;