nginx-0.0.1-2002-08-20-18:48:28 import
diff --git a/src/http/modules/ngx_http_header_filter.c b/src/http/modules/ngx_http_header_filter.c
index d247654..efe0744 100644
--- a/src/http/modules/ngx_http_header_filter.c
+++ b/src/http/modules/ngx_http_header_filter.c
@@ -1,4 +1,11 @@
 
+#include <nginx.h>
+
+#include <ngx_config.h>
+#include <ngx_string.h>
+#include <ngx_hunk.h>
+#include <ngx_http.h>
+
 
 typedef struct {
     int    len;
@@ -18,44 +25,60 @@
     ngx_hunk_t   *h;
     ngx_chain_t  *ch;
 
-    ngx_test_null(h, ngx_get_hunk(r->pool, 1024, 0, 64), NGX_HTTP_FILTER_ERROR);
+    ngx_test_null(h, ngx_get_hunk(r->pool, 1024, 0, 64),
+                  /* STUB */
+                  -1);
+/*
+                  NGX_HTTP_FILTER_ERROR);
+*/
 
-    status = r->headers_out->status - GX_HTTP_OK;
+    status = r->headers_out->status - NGX_HTTP_OK;
 
-    ngx_memcpy(h->pos.mem, "HTTP/1.0 ", 9);
-    h->pos.mem += 9;
-    ngx_memcpy(h->pos.mem, http_codes[status].line, http_codes[status].len);
-    h->pos.mem += http_codes[status].len;
-    *(h->pos.mem++) = CR; *(h->pos.mem++) = LF;
+    ngx_memcpy(h->last.mem, "HTTP/1.0 ", 9);
+    h->last.mem += 9;
+    ngx_memcpy(h->last.mem, http_codes[status].line, http_codes[status].len);
+    h->last.mem += http_codes[status].len;
+    *(h->last.mem++) = CR; *(h->last.mem++) = LF;
 
-    memcpy(h->pos.mem, "Date: ", 6);
-    h->pos.mem += 6;
-    h->pos.mem += ngx_http_get_time(h->pos.mem, time());
-    *(h->pos.mem++) = CR; *(h->pos.mem++) = LF;
+/*
+    memcpy(h->last.mem, "Date: ", 6);
+    h->last.mem += 6;
+    h->last.mem += ngx_http_get_time(h->last.mem, time(NULL));
+    *(h->last.mem++) = CR; *(h->last.mem++) = LF;
+*/
 
     /* 2^64 is 20 characters  */
     if (r->headers_out->content_length)
-        h->pos.mem += ngx_snprintf(h->pos.mem, 49, "Content-Length: %d" CRLF,
-                                   r->headers_out->content_length);
+        h->last.mem += ngx_snprintf(h->last.mem, 49, "Content-Length: %d" CRLF,
+                                    r->headers_out->content_length);
 
     /* check */
 
-    memcpy(h->pos.mem, "Server: ", 8);
-    h->pos.mem += 8;
+    memcpy(h->last.mem, "Server: ", 8);
+    h->last.mem += 8;
     if (r->headers_out->server) {
-        h->pos.mem = ngx_cpystrn(h->pos.mem, r->headers_out->server,
-                                 h->last.mem - h->pos.mem);
-        check space
+        h->last.mem = ngx_cpystrn(h->last.mem, r->headers_out->server,
+                                  h->end - h->last.mem);
+
+        /* check space */
+
     } else {
-        ngx_memcpy(h->pos.mem, NGINX_VER, sizeof(NGINX_VER));
-        h->pos.mem += sizeof(NGINX_VER);
+        ngx_memcpy(h->last.mem, NGINX_VER, sizeof(NGINX_VER));
+        h->last.mem += sizeof(NGINX_VER);
     }
-    *(h->pos.mem++) = CR; *(h->pos.mem++) = LF;
+    *(h->last.mem++) = CR; *(h->last.mem++) = LF;
+
+    /* end of HTTP header */
+    *(h->last.mem++) = CR; *(h->last.mem++) = LF;
 
     ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)),
+                  /* STUB */
+                  -1);
+/*
                   NGX_HTTP_FILTER_ERROR);
+*/
 
-    ch->hunk = in->hunk;
+    ch->hunk = h;
     ch->next = NULL;
 
     return ngx_http_write_filter(r, ch);
diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c
index f2053c4..20d0b9e 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -1,55 +1,114 @@
 
 #include <ngx_config.h>
-
-#include <ngx_strings.h>
-#include <ngx_open.h>
-#include <ngx_stat.h>
-
+#include <ngx_string.h>
+#include <ngx_file.h>
+#include <ngx_hunk.h>
 #include <ngx_http.h>
 
+ngx_http_module_t  ngx_http_static_module;
+
+
+#if 0
+/* STUB */
+static ngx_http_static_ctx_t module_ctx;
+
+void ngx_http_static_init()
+{
+     module_ctx.out = NULL;
+
+     ngx_http_static_module.ctx = &module_ctx;
+}
+/* */
+#endif
+
+
 int ngx_http_static_handler(ngx_http_request_t *r)
 {
-    int          index_len, err, i;
-    char        *name, *loc, *file
-    ngx_file_t   fd;
+    int rc;
+    ngx_hunk_t  *h;
+    ngx_chain_t *ch;
 
-    ngx_http_header_out_t  out;
+/*
     ngx_http_event_static_handler_loc_conf_t  *cf;
 
     cf = (ngx_http_event_static_handler_loc_conf_t *)
              ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module);
 
-    ngx_assert(r->fd, return NGX_HTTP_INTERNAL_SERVER_ERROR,
-               r->connection->log, "ngx_http_static_handler: no file");
+*/
 
-    out.status = NGX_HTTP_OK;
-    out.content_length = r->stat.sb_size;
-    out.last_modified = r->stat.sb_mtime;
+    r->fd = ngx_open_file(r->filename, NGX_FILE_RDONLY);
+    if (r->fd == -1) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
+                      "ngx_http_static_handler: "
+                      ngx_open_file_n " %s failed", r->filename);
+        /* STUB */
+        return -1;
+    }
 
-    /* */
-    out.content_type = "text/html";
+    if (ngx_stat_fd(r->fd, &r->file_info) == -1) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
+                      "ngx_http_static_handler: "
+                      ngx_stat_fd_n " %s failed", r->filename);
+        /* STUB */
+        return -1;
+    }
 
-    rc = ngx_send_http_header(&out);
+    r->headers_out->status = NGX_HTTP_OK;
+    r->headers_out->content_length = ngx_file_size(r->file_info);
+/*
+    r->headers_out->last_modified = ngx_file_mtime(r->file_info);
+*/
+
+    /* STUB */
+    r->headers_out->content_type = "text/html";
+
+    /* STUB */
+    rc = ngx_http_header_filter(r);
+/*
+    rc = ngx_send_http_header(r->headers_out);
+*/
     if (r->header_only)
         return rc;
 
-    /* NGX_HTTP_INTERNAL_SERVER_ERROR is too late */
+    /* TODO: NGX_HTTP_INTERNAL_SERVER_ERROR is too late */
 
+    /* STUB */
+    ngx_test_null(h, ngx_get_hunk(r->pool, 1024, 0, 64),
+                  /* STUB */
+                  -1);
+/*
     ngx_test_null(h, ngx_create_hunk(r->pool), NGX_HTTP_INTERNAL_SERVER_ERROR);
-    h->type = NGX_HUNK_FILE | NGX_HUNK_LAST;
+*/
+    h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
     h->fd = r->fd;
     h->pos.file = 0;
-    h->end.file = r->stat.sb_size;
+    h->last.file = ngx_file_size(r->file_info);
 
+    /* STUB */
+    ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)),
+                  /* STUB */
+                  -1);
+/*
+                  NGX_HTTP_FILTER_ERROR);
+*/
+
+/*
     ngx_test_null(ch, ngx_create_chain(r->pool),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
+*/
     ch->hunk = h;
     ch->next = NULL;
 
-    return ngx_http_filter(ch);
+    /* STUB */
+    rc = ngx_http_write_filter(r, ch);
+    ngx_log_debug(r->connection->log, "write_filter: %d" _ rc);
+    return rc;
+/*
+    return ngx_http_filter(r, ch);
+*/
 }
 
-/*
+#if 0
 
 static void *ngx_create_index_config()
 {
@@ -98,4 +157,4 @@
     *conf = cf;
 }
 
-*/
+#endif
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index c3343fa..9d7bf8b 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1,6 +1,10 @@
 
+#include <ngx_config.h>
+#include <ngx_string.h>
+#include <ngx_listen.h>
 #include <ngx_http.h>
 
+extern ngx_array_t *ngx_listening_sockets;
 
 /* STUB */
 
@@ -9,22 +13,25 @@
 
 static ngx_http_server_t ngx_http_server;
 
-int ngx_http_init(ngx_pool_t *pool)
+int ngx_http_init(ngx_pool_t *pool, ngx_log_t *log)
 {
     ngx_listen_t  *ls;
 
-    ngx_http_server.handler = ngx_http_init_connection;
-
     ngx_http_server.buff_size = 1024;
-
+#if (WIN32)
+    ngx_http_server.doc_root = "html";
+#else
     ngx_http_server.doc_root = "/home/is/work/xml/site-1.0.0/html";
-    ngx_http_server.doc_root_len = strlen(server.doc_root);
+#endif
+    ngx_http_server.doc_root_len = strlen(ngx_http_server.doc_root) + 1;
+
+    ngx_http_write_filter_init();
 
     ls = ngx_push_array(ngx_listening_sockets);
-    ngx_memzero(ls, sizeof(nxg_listen_t));
+    ngx_memzero(ls, sizeof(ngx_listen_t));
 
     addr.sin_family = AF_INET;
-    addr.sin_addr.s_addr = inet_addr(optarg)
+    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
     addr.sin_port = htons(8000);
 
     ngx_snprintf(ngx_cpystrn(addr_text, inet_ntoa(addr.sin_addr), 16),
@@ -32,13 +39,17 @@
 
     ls->family = AF_INET;
     ls->type = SOCK_STREAM;
-    ls->protocol = 0;
+    ls->protocol = IPPROTO_IP;
     ls->addr = &addr;
-    ls->addr_len = sizeof(sockaddr_in);
-    ls->text = &addr_text;
+    ls->addr_len = sizeof(struct sockaddr_in);
+    ls->addr_text = addr_text;
     ls->backlog = -1;
     ls->nonblocking = 1;
 
+    ls->handler = ngx_http_init_connection;
+    ls->server = &ngx_http_server;
+    ls->log = log;
+
     return 1;
 }
 
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index e05dcc8..165e5e6 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -4,6 +4,7 @@
 
 #include <ngx_config.h>
 #include <ngx_types.h>
+#include <ngx_file.h>
 #include <ngx_connection.h>
 
 
@@ -22,6 +23,7 @@
 #define NGX_OK                          0
 
 #define NGX_HTTP_OK                     200
+#define NGX_HTTP_MOVED_PERMANENTLY      302
 #define NGX_HTTP_NOT_FOUND              404
 #define NGX_HTTP_INTERNAL_SERVER_ERROR  503
 
@@ -38,8 +40,9 @@
 #define ngx_get_module_ctx(r, module)  (module)->ctx
 
 typedef struct {
-    char  *doc_root;
-    int    doc_root_len;
+    char   *doc_root;
+    size_t  doc_root_len;
+    size_t  buff_size;
 } ngx_http_server_t;
 
 typedef struct {
@@ -52,23 +55,30 @@
 typedef struct {
     int     status;
     int     connection;
-    size_t  content_length;
+    off_t   content_length;
+    char   *location;
     char   *content_type;
     char   *charset;
     char   *etag;
+    char   *server;
     time_t  date;
     time_t  last_modified;
-} ngx_http_header_out_t;
+} ngx_http_headers_out_t;
 
 typedef struct ngx_http_request_s ngx_http_request_t;
 
 struct ngx_http_request_s {
     char  *filename;
     char  *location;
+    ngx_file_t  fd;
+
+    ngx_http_headers_out_t *headers_out;
 
     int    filename_len;
     int  (*handler)(ngx_http_request_t *r);
 
+    ngx_file_info_t file_info;
+
     int    method;
 
     int    http_version;
@@ -83,7 +93,7 @@
     ngx_buff_t  *buff;
     ngx_pool_t  *pool;
 
-    /* internal */
+    unsigned  header_only:1;
     unsigned  unusual_uri:1;
     unsigned  complex_uri:1;
 
diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c
index 9e63f92..e0fb7b3 100644
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -1,5 +1,6 @@
 
 #include <ngx_config.h>
+#include <ngx_file.h>
 #include <ngx_log.h>
 #include <ngx_alloc.h>
 #include <ngx_hunk.h>
@@ -26,6 +27,9 @@
 
 static int ngx_http_close_request(ngx_event_t *ev);
 
+/* STUB */
+static int ngx_http_writer(ngx_event_t *ev);
+
 /*
     returns
     -1 if error
@@ -62,6 +66,7 @@
 int ngx_http_init_request(ngx_event_t *ev)
 {
     ngx_connection_t   *c = (ngx_connection_t *) ev->data;
+    ngx_http_server_t  *srv = (ngx_http_server_t *) c->server;
     ngx_http_request_t *r;
 
     ngx_log_debug(ev->log, "ngx_http_init_request: entered");
@@ -71,14 +76,14 @@
 
     c->data = r;
     r->connection = c;
+    r->server = srv;
 
     ngx_test_null(r->pool, ngx_create_pool(16384, ev->log), -1);
     ngx_test_null(r->buff, ngx_palloc(r->pool, sizeof(ngx_buff_t)), -1);
-    ngx_test_null(r->buff->buff,
-                  ngx_pcalloc(r->pool, sizeof(c->server->buff_size)), -1);
+    ngx_test_null(r->buff->buff, ngx_palloc(r->pool, srv->buff_size), -1);
 
     r->buff->pos = r->buff->last = r->buff->buff;
-    r->buff->end = r->buff->buff + c->server->buff_size;
+    r->buff->end = r->buff->buff + srv->buff_size;
 
     r->state_handler = ngx_process_http_request_line;
 
@@ -180,11 +185,15 @@
 
 static int ngx_process_http_request(ngx_http_request_t *r)
 {
-    int   err;
+    int   err, rc;
     char *name, *loc, *file;
 
     ngx_log_debug(r->connection->log, "HTTP request");
 
+    ngx_test_null(r->headers_out,
+                  ngx_pcalloc(r->pool, sizeof(ngx_http_headers_out_t)),
+                  ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR));
+
     if (*(r->uri_end - 1) == '/') {
         r->handler = NGX_HTTP_DIRECTORY_HANDLER;
         return NGX_OK;
@@ -204,14 +213,11 @@
 
     ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->filename);
 
-}
-#if 0
-
-    if (ngx_stat(r->filename, &r->stat) == -1) {
+    if (ngx_file_type(r->filename, &r->file_info) == -1) {
         err = ngx_errno;
-        ngx_log_error(GX_LOG_ERR, r->connection->log, err,
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
                      "ngx_process_http_request: "
-                      ngx_stat_n " %s failed", r->filename);
+                      ngx_file_type_n " %s failed", r->filename);
 
         if (err == NGX_ENOENT)
             return ngx_http_error(r, NGX_HTTP_NOT_FOUND);
@@ -219,29 +225,50 @@
             return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
     }
 
-    if (ngx_is_dir(r->stat)) {
+    if (ngx_is_dir(r->file_info)) {
+        ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->filename);
         *file++ = '/';
         *file = '\0';
         r->headers_out->location = r->location;
         return ngx_http_redirect(r, NGX_HTTP_MOVED_PERMANENTLY);
     }
 
-    r->stat_valid = 1;
+    /* STUB */
+    rc =  ngx_http_static_handler(r);
+    if (rc == 0) {
+        r->connection->write->event_handler = ngx_http_writer;
+        ngx_add_event(r->connection->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT);
+    }
+    return rc;
+
     r->handler = NGX_HTTP_STATIC_HANDLER;
     return NGX_OK;
 }
 
+
+static int ngx_http_writer(ngx_event_t *ev)
+{
+    int rc;
+    ngx_connection_t   *c = (ngx_connection_t *) ev->data;
+    ngx_http_request_t *r = (ngx_http_request_t *) c->data;
+
+    rc = ngx_http_write_filter(r, NULL);
+    ngx_log_debug(r->connection->log, "write_filter: %d" _ rc);
+    return rc;
+}
+
 static int ngx_http_handler(ngx_http_request_t *r, int handler)
 {
     if (handler == NGX_HTTP_STATIC_HANDLER) 
         return ngx_http_static_handler(r);
 
+#if 0
     elsif (handler == NGX_HTTP_DIRECTORY_HANDLER) 
         return ngx_http_index_handler(r);
+#endif
 
     return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
 }
-#endif
 
 static int ngx_http_redirect(ngx_http_request_t *r, int redirect)
 {
diff --git a/src/http/ngx_http_filter.c b/src/http/ngx_http_filter.c
new file mode 100644
index 0000000..2533820
--- /dev/null
+++ b/src/http/ngx_http_filter.c
@@ -0,0 +1,239 @@
+
+
+
+ngx_http_module_t  ngx_http_filter_module;
+
+
+/* STUB */
+static ngx_http_filter_ctx_t module_ctx;
+
+void ngx_http_filter_init()
+{
+     module_ctx.buffer_output = 10240;
+     module_ctx.out = NULL;
+     module_ctx.next_filter = ngx_http_write_filter;
+
+     ngx_http_filter_module.ctx = &module_ctx;
+}
+/* */
+
+
+/*
+int ngx_http_filter(ngx_http_request_t *r, ngx_chain_t *in)
+*/
+
+/*
+    flags NGX_HUNK_RECYCLED, NGX_HUNK_FLUSH, NGX_HUNK_LAST
+*/
+
+int ngx_http_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
+{
+    enum { NO = 0, COPY, FILE } temp;
+
+    ngx_http_write_ctx_t  *ctx;
+
+    ctx = (ngx_http_filter_ctx_t *)
+                              ngx_get_module_ctx(r->main ? r->main : r,
+                                                      &ngx_http_filter_module);
+
+
+
+    if (hunk == NULL)
+        if (in == NULL)
+            next_filter(NULL);
+        else
+
+
+
+
+
+    if (hunk != NULL)
+        if (in == NULL)
+            if (temp == NO)
+                fast_chain = hunk;
+                next_filter(fast_chain);
+            else
+                if (ctx->hunk busy)
+                    add hunk to ctx->in
+                    next_filter(NULL);
+                else
+                    if (hunk > ctx->hunk)
+                        copy hunk part to ctx->hunk
+                        add hunk to ctx->in
+                    else
+                        copy hunk to ctx->hunk
+                    fast_chain = ctx->hunk
+                    next_filter(fast_chain);
+
+        else /* in != NULL */
+           add hunk to ctx->in
+
+
+
+
+
+            
+
+
+
+    if ((r->filter & NGX_FILT_NEED_IN_MEMORY) && (hunk->type & NGX_HUNK_FILE))
+        temp = FILE;
+
+    else if ((r->filter & NGX_FILT_NEED_TEMP)
+             && (hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP))
+        temp = COPY;
+
+    if (temp) {
+        size = hunk->last.mem - hunk->pos.mem;
+
+        if (hunk->type & NGX_HUNK_LAST) {
+            if (size > ctx->hunk_size)
+                size = ctx->hunk_size;
+
+            hunk_size = size;
+
+        } else {
+            hunk_size = ctx->hunk_size;
+        }
+    }
+
+    if (!ctx->hunk)
+        ngx_test_null(ctx->hunk, ngx_create_temp_hunk(hunk_size), ...);
+
+    if (temp == FILE) {
+        n = ngx_read_file(hunk->fd, ctx->hunk->pos.mem, size);
+
+        if (n == -1) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
+                          ngx_read_file_n " failed for client");
+            return -1;
+
+        } else {
+            ngx_assert((n == size), /* void */ ; ,
+                       r->connection->log, 0,
+                       ngx_read_file_n " reads only %d of %d for client",
+                       n, size);
+        }
+
+        hunk->pos.mem += n;
+        ctx->hunk->last.mem += n;
+
+    } else if (temp == COPY) {
+        ngx_memcpy(ctx->hunk->pos.mem, hunk->pos.mem, size);
+
+        hunk->pos.mem += size;
+        ctx->hunk->last.mem += size;
+    }
+
+
+
+
+
+
+    /* if no hunk is passed and there is no our hunk
+       or our hunk is still busy then call next filter */
+    if (hunk == NULL
+        && (ctx->hunk == NULL
+            || ((ctx->hunk != NULL)
+                && (ctx->hunk->pos.mem < ctx->hunk->last.mem))
+           )
+       )
+        ctx->next_filter(r, NULL);
+    }
+
+    /* hunk != NULL || ctx->hunk->pos.mem == ctx->hunk->last.mem */
+
+    /* find last link of saved chain */
+    prev = &ctx->out;
+    for (ch = ctx->out; ch; ch = ch->next) {
+        prev = &ch->next;
+    }
+
+    if hunk
+        if need our hunk - alloc it and add to our queue
+        else add hunk to our queue
+
+/*
+        size += ch->hunk->last.file - ch->hunk->pos.file;
+
+        ngx_log_debug(r->connection->log, "old chunk: %x %qx %qd" _
+                      ch->hunk->type _ ch->hunk->pos.file _
+                      ch->hunk->last.file - ch->hunk->pos.file);
+
+        if (ch->hunk->type & NGX_HUNK_FLUSH)
+            flush = size;
+
+        if (ch->hunk->type & NGX_HUNK_LAST)
+            last = 1;
+    }
+*/
+
+    /* add new chain to existent one */
+    for (/* void */; in; in = in->next) {
+        ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)),
+                      NGX_HTTP_FILTER_ERROR);
+
+        ch->hunk = h;
+        ch->next = NULL;
+        *prev = ch;
+        prev = &ch->next;
+        size += ch->hunk->last.file - ch->hunk->pos.file;
+
+        ngx_log_debug(r->connection->log, "new chunk: %x %qx %qd" _
+                      ch->hunk->type _ ch->hunk->pos.file _
+                      ch->hunk->last.file - ch->hunk->pos.file);
+
+        if (ch->hunk->type & NGX_HUNK_FLUSH)
+            flush = size;
+
+        if (ch->hunk->type & NGX_HUNK_LAST)
+            last = 1;
+    }
+
+
+
+
+
+/*
+    !(HAVE_SENDFILE) == NGX_FILT_NEED_IN_MEMORY
+*/
+
+    if ((r->filter & NGX_FILT_NEED_IN_MEMORY) && (h->type & NGX_HUNK_FILE)) {
+
+        size = h->last.mem - h->pos.mem;
+        if (size > ctx->hunk_size)
+            size = ctx->hunk_size;
+
+        if (!ctx->hunk)
+            ngx_test_null(ctx->hunk, ngx_create_temp_hunk(size), ...);
+
+        ngx_read_file(h->fd, ctx->hunk->pos.mem, size);
+
+        h->hunk->pos.mem += size;
+    }
+
+    if ((r->filter & NGX_FILT_NEED_TEMP)
+        && (h->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP))
+    {
+        size = h->last.mem - h->pos.mem;
+        if (size > ctx->hunk_size)
+            size = ctx->hunk_size;
+
+        if (!ctx->hunk)
+            ngx_test_null(ctx->hunk, ngx_create_temp_hunk(size), ...);
+
+        ngx_memcpy(ctx->hunk->pos.mem, h->pos.mem, size);
+
+        h->hunk->pos.mem += size;
+    }
+
+
+
+
+
+
+    rc = ctx->next_filter(r, ch);
+
+    /* STUB */
+    rc = ngx_http_write_filter(r, ch);
+}
diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c
index 5e4eaa6..9855eb7 100644
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -34,7 +34,7 @@
 
     ctx = (ngx_http_write_filter_ctx_t *)
                               ngx_get_module_ctx(r->main ? r->main : r,
-                                                &ngx_http_write_filter_module);
+                                                 &ngx_http_write_filter_module);
     size = flush = 0;
     last = 0;
     prev = &ctx->out;
@@ -44,6 +44,10 @@
         prev = &ch->next;
         size += ch->hunk->last.file - ch->hunk->pos.file;
 
+        ngx_log_debug(r->connection->log, "old chunk: %x %qx %qd" _
+                      ch->hunk->type _ ch->hunk->pos.file _
+                      ch->hunk->last.file - ch->hunk->pos.file);
+
         if (ch->hunk->type & NGX_HUNK_FLUSH)
             flush = size;
 
@@ -62,6 +66,10 @@
         prev = &ch->next;
         size += ch->hunk->last.file - ch->hunk->pos.file;
 
+        ngx_log_debug(r->connection->log, "new chunk: %x %qx %qd" _
+                      ch->hunk->type _ ch->hunk->pos.file _
+                      ch->hunk->last.file - ch->hunk->pos.file);
+
         if (ch->hunk->type & NGX_HUNK_FLUSH)
             flush = size;
 
@@ -69,7 +77,7 @@
             last = 1;
     }
 
-    if (flush == 0 && size < ctx->buffer_output)
+    if (!last && flush == 0 && size < ctx->buffer_output)
         return NGX_HTTP_FILTER_DONE;
 
     chain = ngx_event_write(r->connection, ctx->out, flush);