]> git.kaiwu.me - nginx.git/commitdiff
nginx-0.0.1-2003-10-12-20:49:16 import
authorIgor Sysoev <igor@sysoev.ru>
Sun, 12 Oct 2003 16:49:16 +0000 (16:49 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Sun, 12 Oct 2003 16:49:16 +0000 (16:49 +0000)
34 files changed:
src/core/nginx.c
src/core/ngx_modules.c
src/event/modules/ngx_aio_module.c
src/event/modules/ngx_devpoll_module.c
src/event/modules/ngx_iocp_module.c
src/event/modules/ngx_kqueue_module.c
src/event/modules/ngx_poll_module.c
src/event/modules/ngx_select_module.c
src/event/ngx_event.c
src/event/ngx_event.h
src/event/ngx_event_close.c
src/event/ngx_event_connect.c
src/event/ngx_event_proxy.c
src/event/ngx_event_timer.c
src/event/ngx_event_timer.h
src/http/modules/ngx_http_gzip_filter.c
src/http/modules/ngx_http_index_handler.c
src/http/modules/proxy/ngx_http_proxy_handler.c
src/http/ngx_http.c
src/http/ngx_http_core_module.c
src/http/ngx_http_header_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/ngx_aio_write.c
src/os/unix/ngx_aio_write_chain.c
src/os/unix/ngx_freebsd_init.c
src/os/unix/ngx_freebsd_sendfile_chain.c
src/os/unix/ngx_recv.c
src/os/unix/ngx_writev_chain.c
src/os/win32/ngx_win32_config.h
src/os/win32/ngx_wsarecv.c
src/os/win32/ngx_wsasend_chain.c

index dce1a5d15737dc0f8d78574a33e3c6a4c3ca6d92..98404a0233987fa73af2e1c03ca142ed8dfa7d79 100644 (file)
@@ -688,7 +688,6 @@ static void ngx_clean_old_cycles(ngx_event_t *ev)
         ngx_add_timer(ev, 30000);
 
     } else {
-        ngx_cleaner_event.timer_set = 0;
         ngx_destroy_pool(ngx_temp_pool);
         ngx_temp_pool = NULL;
         ngx_old_cycles.nelts = 0;
index 85bcfa014af003f360abe47aab5c8613db6095f0..d7268c9ebff14519d2be4965925b68ba9cf3e26d 100644 (file)
@@ -38,8 +38,8 @@ extern ngx_module_t  ngx_http_not_modified_filter_module;
 extern ngx_module_t  ngx_http_range_filter_module;
 extern ngx_module_t  ngx_http_charset_filter_module;
 
-extern ngx_module_t  ngx_http_index_module;
 extern ngx_module_t  ngx_http_static_module;
+extern ngx_module_t  ngx_http_index_module;
 extern ngx_module_t  ngx_http_proxy_module;
 
 extern ngx_module_t  ngx_http_log_module;
@@ -89,8 +89,8 @@ ngx_module_t *ngx_modules[] = {
     /* &ngx_http_ssi_filter_module, */
     &ngx_http_charset_filter_module,
 
-    &ngx_http_index_module,
     /* &ngx_http_static_module, */
+    &ngx_http_index_module,
     &ngx_http_proxy_module,
 
     &ngx_http_log_module,
index cdfb1b01f4763afaa1ba10bba344313454921707..4b89c2a546baf24b339fa8a692af4cff855023a9 100644 (file)
@@ -68,7 +68,7 @@ static int ngx_aio_init(ngx_cycle_t *cycle)
 
     ngx_io = ngx_os_aio;
 
-    ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_USE_AIO_EVENT;
+    ngx_event_flags = NGX_USE_AIO_EVENT;
     ngx_event_actions = ngx_aio_module_ctx.actions;
 
 
index e55f17c9d6a5ad0a868a703201087c13f5b923c5..c21abde0df6c317990e8373ee34c0b94e6977211 100644 (file)
@@ -173,7 +173,7 @@ ngx_log_debug(cycle->log, "EV: %d" _ dpcf->events);
 
     ngx_event_actions = ngx_devpoll_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT|NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT;
 
     return NGX_OK;
 }
index 2f31eb6fbfbe8fcfd3bf6c3f5a013472b4f7236d..86d763b7115769b03d4581d5cebdb4a45690f2d3 100644 (file)
@@ -105,7 +105,7 @@ static int ngx_iocp_init(ngx_cycle_t *cycle)
 
     ngx_event_actions = ngx_iocp_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_HAVE_IOCP_EVENT;
+    ngx_event_flags = NGX_USE_AIO_EVENT|NGX_USE_IOCP_EVENT;
 
     return NGX_OK;
 }
index d0a9d2e481724906e534cb2ee3fe9c46aac6c9a1..14eb27038d6db302af32b761087e13a7389d8e26 100644 (file)
@@ -151,10 +151,9 @@ ngx_log_debug(cycle->log, "EV: %d" _ kcf->events);
 
     ngx_event_actions = ngx_kqueue_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
-                     |NGX_HAVE_ONESHOT_EVENT
+    ngx_event_flags = NGX_USE_ONESHOT_EVENT
 #if (HAVE_CLEAR_EVENT)
-                     |NGX_HAVE_CLEAR_EVENT
+                     |NGX_USE_CLEAR_EVENT
 #else
                      |NGX_USE_LEVEL_EVENT
 #endif
@@ -238,9 +237,11 @@ static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
         return NGX_OK;
     }
 
-    /* when the file descriptor is closed a kqueue automatically deletes
-       its filters so we do not need to delete explicity the event
-       before the closing the file descriptor */
+    /*
+     * when the file descriptor is closed a kqueue automatically deletes
+     * its filters so we do not need to delete explicity the event
+     * before the closing the file descriptor.
+     */
 
     if (flags & NGX_CLOSE_EVENT) {
         return NGX_OK;
@@ -427,13 +428,17 @@ static int ngx_kqueue_process_events(ngx_log_t *log)
 
             if (ev->oneshot && ev->timer_set) {
                 ngx_del_timer(ev);
-                ev->timer_set = 0;
             }
 
-            /* fall through */
+            ev->ready = 1;
+
+            ev->event_handler(ev);
+
+            break;
 
         case EVFILT_AIO:
             ev->ready = 1;
+            ev->active = 0;
 
             ev->event_handler(ev);
 
index 4d50b4a52e9bddfcf7c92a41af011477420b542d..9d2f8aca3187f76743053b08903fd5fb19c20e3b 100644 (file)
@@ -109,9 +109,7 @@ static int ngx_poll_init(ngx_cycle_t *cycle)
 
     ngx_event_actions = ngx_poll_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
-                      |NGX_HAVE_ONESHOT_EVENT
-                      |NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;
 
     return NGX_OK;
 }
@@ -364,7 +362,6 @@ static int ngx_poll_process_events(ngx_log_t *log)
         if (ev->oneshot) {
             if (ev->timer_set) {
                 ngx_del_timer(ev);
-                ev->timer_set = 0;
             }
 
             if (ev->write) {
index 1f8a5d98e4dd37f1d0661f735eecd4c49b2ddeb4..7924766693ad66de4bb6fabb922343ad57e9b428 100644 (file)
@@ -108,9 +108,7 @@ static int ngx_select_init(ngx_cycle_t *cycle)
 
     ngx_event_actions = ngx_select_module_ctx.actions;
 
-    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
-                      |NGX_HAVE_ONESHOT_EVENT
-                      |NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;
 
 #if (WIN32)
     max_read = max_write = 0;
@@ -401,7 +399,6 @@ static int ngx_select_process_events(ngx_log_t *log)
         if (ev->oneshot) {
             if (ev->timer_set) {
                 ngx_del_timer(ev);
-                ev->timer_set = 0;
             }
 
             if (ev->write) {
index 7c709e3447374315d990b1f635af1d0d133ca172..71bf45d1675b5c3345c257e4fc91386fc9de3a2e 100644 (file)
@@ -224,7 +224,7 @@ ngx_log_debug(cycle->log, "TYPE: %d" _ ecf->use);
         /* required by poll */
         wev->index = NGX_INVALID_INDEX;
 
-        if ((ngx_event_flags & NGX_HAVE_IOCP_EVENT) == 0) {
+        if ((ngx_event_flags & NGX_USE_IOCP_EVENT) == 0) {
             if (s[i].remain) {
 
                 if (ngx_del_event(&cycle->old_cycle->read_events[fd],
@@ -238,7 +238,7 @@ ngx_log_debug(cycle->log, "TYPE: %d" _ ecf->use);
 
 #if (WIN32)
 
-        if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+        if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
             rev->event_handler = &ngx_event_acceptex;
 
             if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
index 8bb2017bd4c3c9ed23962beea8094c60e41d1601..643ea2b76f683b4115db9e552bcb985893f614b0 100644 (file)
@@ -24,9 +24,6 @@ struct ngx_event_s {
     void            *data;
     void           (*event_handler)(ngx_event_t *ev);
 
-#if 0
-    int            (*close_handler)(ngx_event_t *ev);
-#endif
     void            *context;
     char            *action;
 
@@ -35,9 +32,6 @@ struct ngx_event_s {
     ngx_event_t     *prev;     /* queue in mutex(), aio_read(), aio_write()  */
     ngx_event_t     *next;     /*                                            */
 
-#if 0
-    int            (*timer_handler)(ngx_event_t *ev);
-#endif
     ngx_event_t     *timer_prev;
     ngx_event_t     *timer_next;
 
@@ -61,17 +55,26 @@ struct ngx_event_s {
 #endif
     unsigned         write:1;
 
-    unsigned         instance:1;  /* used to detect stale events in kqueue,
-                                     rt signals and epoll */
+    /* used to detect stale events in kqueue, rt signals and epoll */
+    unsigned         instance:1;
 
+    /*
+     * event was passed or would be passed to a kernel;
+     * the posted aio operation.
+     */
     unsigned         active:1;
+
+    /* ready event; the complete aio operation */
     unsigned         ready:1;
+
     unsigned         timedout:1;
-    unsigned         blocked:1;
     unsigned         timer_set:1;
+
+#if 1
+    unsigned         blocked:1;
+#endif
     unsigned         delayed:1;
 
-    unsigned         process:1;
     unsigned         read_discarded:1;
 
     unsigned         ignore_econnreset:1;
@@ -156,50 +159,68 @@ typedef struct {
 } ngx_event_actions_t;
 
 
-/* The event filter requires to read/write the whole data -
-   select, poll, /dev/poll, kqueue. */
-#define NGX_HAVE_LEVEL_EVENT    0x00000001
-
-/* The event filter is deleted after a notification without an additional
-   syscall - select, poll, kqueue.  */
-#define NGX_HAVE_ONESHOT_EVENT  0x00000002
-
-/* The event filter notifies only the changes and an initial level - kqueue */
-#define NGX_HAVE_CLEAR_EVENT    0x00000004
-
-/* The event filter has kqueue features - the eof flag, errno,
-   available data, etc */
-#define NGX_HAVE_KQUEUE_EVENT   0x00000008
-
-/* The event filter supports low water mark - kqueue's NOTE_LOWAT.
-   kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag */
-#define NGX_HAVE_LOWAT_EVENT    0x00000010
-
-/* The event filter notifies only the changes (the edges)
-   but not an initial level - epoll */
-#define NGX_HAVE_EDGE_EVENT     0x00000020
-
-/* No need to add or delete the event filters - rt signals */
-#define NGX_HAVE_SIGIO_EVENT    0x00000040
-
-/* No need to add or delete the event filters - overlapped, aio_read, aioread */
-#define NGX_HAVE_AIO_EVENT      0x00000080
-
-/* Need to add socket or handle only once - i/o completion port.
-   It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set */
-#define NGX_HAVE_IOCP_EVENT     0x00000100
-
-
-#define NGX_USE_LEVEL_EVENT     0x00010000
-#define NGX_USE_AIO_EVENT       0x00020000
-
-
-/* Event filter is deleted before closing file.
-   Has no meaning for select, poll, epoll.
-
-   kqueue:     kqueue deletes event filters for file that closed
-               so we need only to delete filters in user-level batch array
-   /dev/poll:  we need to flush POLLREMOVE event before closing file */
+/*
+ * The event filter requires to read/write the whole data -
+ * select, poll, /dev/poll, kqueue.
+ */
+#define NGX_USE_LEVEL_EVENT    0x00000001
+
+/*
+ * The event filter is deleted after a notification without an additional
+ * syscall - select, poll, kqueue.
+ */
+#define NGX_USE_ONESHOT_EVENT  0x00000002
+
+/*
+ *  The event filter notifies only the changes and an initial level - kqueue.
+ */
+#define NGX_USE_CLEAR_EVENT    0x00000004
+
+/*
+ * The event filter has kqueue features - the eof flag, errno,
+ * available data, etc
+ */
+#define NGX_HAVE_KQUEUE_EVENT  0x00000008
+
+/*
+ * The event filter supports low water mark - kqueue's NOTE_LOWAT.
+ * kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag.
+ */
+#define NGX_HAVE_LOWAT_EVENT   0x00000010
+
+/*
+ * The event filter notifies only the changes (the edges)
+ * but not an initial level - epoll.
+ */
+#define NGX_USE_EDGE_EVENT     0x00000020
+
+/*
+ * No need to add or delete the event filters - rt signals.
+ */
+#define NGX_USE_SIGIO_EVENT    0x00000040
+
+/*
+ * No need to add or delete the event filters - overlapped, aio_read,
+ * aioread, io_submit.
+ */
+#define NGX_USE_AIO_EVENT      0x00000080
+
+/*
+ * Need to add socket or handle only once - i/o completion port.
+ * It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set.
+ */
+#define NGX_USE_IOCP_EVENT     0x00000100
+
+
+
+/*
+ * The event filter is deleted before the closing file.
+ * Has no meaning for select, poll, epoll.
+ *
+ * kqueue:     kqueue deletes event filters for file that closed
+ *             so we need only to delete filters in user-level batch array
+ * /dev/poll:  we need to flush POLLREMOVE event before closing file
+ */
 
 #define NGX_CLOSE_EVENT         1
 
@@ -209,10 +230,12 @@ typedef struct {
 #define NGX_READ_EVENT     EVFILT_READ
 #define NGX_WRITE_EVENT    EVFILT_WRITE
 
-/* NGX_CLOSE_EVENT is the module flag and it would not go into a kernel
-   so we need to choose the value that would not interfere with any existent
-   and future flags. kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR.
-   They are reserved and cleared on a kernel entrance */
+/*
+ * NGX_CLOSE_EVENT is the module flag and it would not go into a kernel
+ * so we need to choose the value that would not interfere with any existent
+ * and future flags.  kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR.
+ * They are reserved and cleared on a kernel entrance.
+ */
 #undef  NGX_CLOSE_EVENT
 #define NGX_CLOSE_EVENT    EV_FLAG1
 
@@ -383,14 +406,14 @@ void ngx_worker(ngx_cycle_t *cycle);
 
 ngx_inline static int ngx_handle_read_event(ngx_event_t *rev)
 {
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+    if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_EDGE_EVENT)) {
 
         /* aio, iocp, epoll */
 
         return NGX_OK;
     }
 
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         /* kqueue */
 
@@ -426,16 +449,41 @@ ngx_inline static int ngx_handle_read_event(ngx_event_t *rev)
 }
 
 
+ngx_inline static int ngx_handle_level_read_event(ngx_event_t *rev)
+{
+    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+        if (!rev->active && !rev->ready) {
+            if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
+                                                                == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+
+        if (rev->active && rev->ready) {
+            if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
 ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int lowat)
 {
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+    if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_EDGE_EVENT)) {
 
         /* aio, iocp, epoll */
 
         return NGX_OK;
     }
 
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         /* kqueue */
 
@@ -478,6 +526,30 @@ ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int lowat)
 }
 
 
+ngx_inline static int ngx_handle_level_write_event(ngx_event_t *wev)
+{
+    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+        if (!wev->active && !wev->ready) {
+            if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
+                                                                == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+
+        if (wev->active && wev->ready) {
+            if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_OK;
+}
+
 
 /* ***************************** */
 
index 06e911759a35238acd1a495f818681173d24abe3..c57c19560477276c94e2da46ea4d8b48b4e0f18f 100644 (file)
@@ -20,12 +20,10 @@ int ngx_event_close_connection(ngx_event_t *ev)
 
     if (c->read->timer_set) {
         ngx_del_timer(c->read);
-        c->read->timer_set = 0;
     }
 
     if (c->write->timer_set) {
         ngx_del_timer(c->write);
-        c->write->timer_set = 0;
     }
 
     ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
index 72031d95a89442c40f9159db088ed542262edff6..b2b70d44c7c47a8e2057b1e2d6e3efcaf1806a91 100644 (file)
@@ -202,7 +202,7 @@ int ngx_event_connect_peer(ngx_peer_connection_t *pc)
 
     /* TODO: epoll, aio, iocp */
 
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {     /* kqueue */
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {     /* kqueue */
         event = NGX_CLEAR_EVENT;
 
     } else {                                  /* select, poll, /dev/poll */
index 71bae9535adda2590b2dca5c8675a92de4531e16..b49b6b9ca4c7e2b39a020f9c6046b1468961e57a 100644 (file)
@@ -584,7 +584,7 @@ ngx_log_debug(p->log, "downstream level: %d" _ p->downstream_level);
 
 int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p)
 {
-    int           i, rc, size;
+    int           rc, size;
     ngx_hunk_t   *h;
     ngx_chain_t  *entry, *next, *saved_in, *saved_read;
 
index b70bafbdb9abafcd1485f3227c2108b0f9f6f89b..53ca9cd197fc4df7adf279bacb1cff70d46c74ea 100644 (file)
@@ -4,7 +4,7 @@
 #include <ngx_event.h>
 
 
-/* in multithreaded enviroment all timer operations must be
+/* TODO: in multithreaded enviroment all timer operations must be
    protected by the single mutex */
 
 
@@ -70,11 +70,18 @@ void ngx_event_timer_done(ngx_cycle_t *cycle)
 void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
 {
     ngx_event_t  *e, *queue;
+#if (NGX_DEBUG_EVENT)
+    ngx_connection_t *c;
+#endif
+
+    if (ev->timer_set) {
+        ngx_del_timer(ev);
+    }
 
 #if (NGX_DEBUG_EVENT)
-    ngx_connection_t *c = ev->data;
-    ngx_log_debug(ev->log, "set timer: %d:%d, slot: %d" _
-                  c->fd _ timer _ ngx_timer_cur_queue);
+    c = ev->data;
+    ngx_log_debug(ev->log, "set timer: %d:%d:%d, slot: %d" _
+                  c->fd _ ev->write _ timer _ ngx_timer_cur_queue);
 #endif
 
     if (ev->timer_next || ev->timer_prev) {
@@ -107,6 +114,10 @@ void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
 
     e->timer_prev->timer_next = ev;
     e->timer_prev = ev;
+
+    ev->timer_set = 1;
+
+    return;
 }
 
 
@@ -129,9 +140,9 @@ int ngx_event_find_timer(void)
 
     if (timer == NGX_MAX_MSEC) {
         return 0;
-    } else {
-        return timer;
     }
+
+    return timer;
 }
 
 
@@ -190,6 +201,10 @@ void ngx_event_expire_timers(ngx_msec_t timer)
         timer += ngx_temp_timer_queue.timer_next->timer_delta;
         ev = ngx_temp_timer_queue.timer_next;
 
+#if (NGX_DEBUG_EVENT)
+        ngx_log_debug(ev->log, "process temp timer queue");
+#endif
+
         ngx_del_timer(ev);
         ngx_add_timer(ev, timer);
     }
index 7a6c52cb204d7db63c7632d7b47743294774adbc..565b233735b3d4a8fe9aaab0313deadcb1b95d3d 100644 (file)
@@ -19,7 +19,7 @@ ngx_inline static void ngx_event_del_timer(ngx_event_t *ev)
 {
 #if (NGX_DEBUG_EVENT)
     ngx_connection_t *c = ev->data;
-    ngx_log_debug(ev->log, "del timer: %d" _ c->fd);
+    ngx_log_debug(ev->log, "del timer: %d:%d" _ c->fd _ ev->write);
 #endif
 
     if (!ev->timer_next || !ev->timer_prev) {
@@ -40,6 +40,8 @@ ngx_inline static void ngx_event_del_timer(ngx_event_t *ev)
     if (ev->timer_prev) {
         ev->timer_prev = NULL;
     }
+
+    ev->timer_set = 0;
 }
 
 
index 3e80c0b1336f19208c5f2f147a2a636272446a00..f5e83842a7a8e7054db41e240b0a062c8c7d0754 100644 (file)
@@ -23,7 +23,7 @@ typedef struct {
     ngx_hunk_t    *out_hunk;
     int            hunks;
 
-    int            length;
+    off_t          length;
     void          *alloc;
 
     unsigned       flush:4;
@@ -90,7 +90,9 @@ ngx_module_t  ngx_http_gzip_filter_module = {
 };
 
 
-static char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
+static char gzheader[10] = { 0x1f,
+                             (char) 0x8b,  /* suppress MSVC warning */
+                             Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
 
 #if (HAVE_LITTLE_ENDIAN)
 
@@ -197,7 +199,7 @@ static int ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
 #if 0
         ngx_test_null(ctx->alloc, ngx_alloc(200K, r->log), NGX_ERROR);
 #else
-        ctx->alloc = (void *) ~NULL;
+        ctx->alloc = (void *) -1;
 #endif
 
         rc = deflateInit2(&ctx->zstream, /**/ 1, Z_DEFLATED,
index 7c348e2ad720286850b4c2958486a5306d3e72ee..1bf2bd99df04f58836012a7d207ab67fbc18283d 100644 (file)
@@ -10,10 +10,20 @@ typedef struct {
 } ngx_http_index_conf_t;
 
 
+typedef struct {
+    int          index;
+    unsigned     tested:1;
+} ngx_http_index_ctx_t;
+
+
 #define NGX_HTTP_DEFAULT_INDEX   "index.html"
 
 
-static int ngx_http_index_test_dir(ngx_http_request_t *r);
+static int ngx_http_index_test_dir(ngx_http_request_t *r,
+                                   ngx_http_index_ctx_t *ctx);
+static int ngx_http_index_error(ngx_http_request_t *r,
+                                ngx_http_index_ctx_t *ctx, ngx_err_t err);
+
 static int ngx_http_index_init(ngx_cycle_t *cycle);
 static void *ngx_http_index_create_conf(ngx_conf_t *cf);
 static char *ngx_http_index_merge_conf(ngx_conf_t *cf,
@@ -58,14 +68,14 @@ ngx_module_t  ngx_http_index_module = {
 
 
 /*
-   Try to open the first index file before the directory existence test
  because the valid requests should be many more than invalid ones.
  If open() failed then stat() should be more quickly because some data
  is already cached in the kernel.
  Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
  Unix has ENOTDIR error, although it less helpfull - it shows only
  that path contains the usual file in place of the directory.
-*/
+ * Try to open the first index file before the test of the directory existence
* because the valid requests should be many more than invalid ones.
* If open() failed then stat() should be more quickly because some data
* is already cached in the kernel.
* Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
* Unix has ENOTDIR error, although it less helpfull - it shows only
* that path contains the usual file in place of the directory.
+ */
 
 int ngx_http_index_handler(ngx_http_request_t *r)
 {
@@ -74,38 +84,58 @@ int ngx_http_index_handler(ngx_http_request_t *r)
     ngx_str_t                  redirect, *index;
     ngx_err_t                  err;
     ngx_fd_t                   fd;
+    ngx_http_index_ctx_t      *ctx;
     ngx_http_index_conf_t     *icf;
     ngx_http_core_loc_conf_t  *clcf;
 
-    icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+    if (r->uri.data[r->uri.len - 1] != '/') {
+        return NGX_DECLINED;
+    }
 
-    ngx_test_null(r->path.data,
-                  ngx_palloc(r->pool,
-                             clcf->doc_root.len + r->uri.len
-                             + icf->max_index_len),
-                  NGX_HTTP_INTERNAL_SERVER_ERROR);
+    ctx = ngx_http_get_module_ctx(r, ngx_http_index_module);
+    if (ctx == NULL) {
+        ngx_http_create_ctx(r, ctx, ngx_http_index_module,
+                            sizeof(ngx_http_index_ctx_t),
+                            NGX_HTTP_INTERNAL_SERVER_ERROR);
+    }
 
-    redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data,
-                               clcf->doc_root.len);
-    file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1);
-    r->path.len = file - r->path.data;
+    icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    test_dir = 1;
-    path_not_found = 1;
+    if (r->path.data == NULL) {
+        r->path_allocated = clcf->doc_root.len + r->uri.len
+                                                          + icf->max_index_len;
+        ngx_test_null(r->path.data,
+                      ngx_palloc(r->pool, r->path_allocated),
+                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+        redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data,
+                                   clcf->doc_root.len);
+        file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1);
+        r->path.len = file - r->path.data;
+
+    } else{
+        redirect.data = r->path.data + r->path.len;
+        file = redirect.data + r->uri.len;
+    }
 
     index = icf->indices.elts;
-    for (i = 0; i < icf->indices.nelts; i++) {
+    for (/* void */; ctx->index < icf->indices.nelts; ctx->index++) {
 
-        if (index[i].data[0] != '/') {
-            ngx_memcpy(file, index[i].data, index[i].len + 1);
-            name = r->path.data;
+        if (index[ctx->index].data[0] == '/') {
+            name = index[ctx->index].data;
 
         } else {
-            name = index[i].data;
+            ngx_memcpy(file, index[ctx->index].data, index[ctx->index].len + 1);
+            name = r->path.data;
         }
 
         fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
+
+        if (fd == NGX_AGAIN) {
+            return NGX_AGAIN;
+        }
+
         if (fd == NGX_INVALID_FILE) {
             err = ngx_errno;
 
@@ -113,25 +143,20 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
               "DEBUG: " ngx_open_file_n " %s failed", name);
 
             if (err == NGX_ENOTDIR) {
-                path_not_found = 1;
+                return ngx_http_index_error(r, ctx, err);
 
             } else if (err == NGX_EACCES) {
-                r->path_err = err;
-                return NGX_HTTP_FORBIDDEN;
+                return ngx_http_index_error(r, ctx, err);
             }
 
-            if (test_dir) {
-                if (path_not_found) {
-                    r->path_err = err;
-                    return NGX_HTTP_NOT_FOUND;
-                }
+            if (!ctx->tested) {
+                rc = ngx_http_index_test_dir(r, ctx);
 
-                rc = ngx_http_index_test_dir(r);
                 if (rc != NGX_OK) {
                     return rc;
                 }
 
-                test_dir = 0;
+                ctx->tested = 1;
             }
 
             if (err == NGX_ENOENT) {
@@ -147,14 +172,15 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
         r->file.name.data = name;
         r->file.fd = fd;
 
-        if (index[i].data[0] == '/') {
-            r->file.name.len = index[i].len;
-            redirect.len = index[i].len;
-            redirect.data = index[i].data;
+        if (index[ctx->index].data[0] == '/') {
+            r->file.name.len = index[ctx->index].len;
+            redirect.len = index[ctx->index].len;
+            redirect.data = index[ctx->index].data;
 
         } else {
-            redirect.len = r->uri.len + index[i].len;
-            r->file.name.len = clcf->doc_root.len + r->uri.len + index[i].len;
+            redirect.len = r->uri.len + index[ctx->index].len;
+            r->file.name.len = clcf->doc_root.len + r->uri.len
+                                                       + index[ctx->index].len;
         }
 
         return ngx_http_internal_redirect(r, &redirect, NULL);
@@ -164,29 +190,26 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
 }
 
 
-static int ngx_http_index_test_dir(ngx_http_request_t *r)
+static int ngx_http_index_test_dir(ngx_http_request_t *r,
+                                   ngx_http_index_ctx_t *ctx)
 {
+    ngx_err_t  err;
+
     r->path.data[r->path.len - 1] = '\0';
     r->path.data[r->path.len] = '\0';
 
 ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data);
 
-#if 0
-    if (r->path_err == NGX_EACCES) {
-        return NGX_HTTP_FORBIDDEN;
-    }
-#endif
-
     if (ngx_file_type(r->path.data, &r->file.info) == -1) {
 
-        r->path_err = ngx_errno;
+        err = ngx_errno;
 
-        if (r->path_err == NGX_ENOENT) {
+        if (err == NGX_ENOENT) {
             r->path.data[r->path.len - 1] = '/';
-            return NGX_HTTP_NOT_FOUND;
+            return ngx_http_index_error(r, ctx, err);
         }
 
-        ngx_log_error(NGX_LOG_CRIT, r->connection->log, r->path_err,
+        ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
                       ngx_file_type_n " %s failed", r->path.data);
 
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -196,10 +219,26 @@ ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data);
 
     if (ngx_is_dir(r->file.info)) {
         return NGX_OK;
+    }
 
-    } else {
-        return NGX_HTTP_NOT_FOUND;
+    /* THINK: not reached ??? */
+    return ngx_http_index_error(r, ctx, 0);
+}
+
+
+static int ngx_http_index_error(ngx_http_request_t *r,
+                                ngx_http_index_ctx_t *ctx, ngx_err_t err)
+{
+    if (err == NGX_EACCES) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
+                      "\"%s\" is forbidden", r->path.data);
+    
+        return NGX_HTTP_FORBIDDEN;
     }
+
+    ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
+                  "\"%s\" is not found", r->path.data);
+    return NGX_HTTP_NOT_FOUND;
 }
 
 
@@ -212,8 +251,9 @@ static int ngx_http_index_init(ngx_cycle_t *cycle)
     ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
 
-    ngx_test_null(h, ngx_push_array(&cmcf->index_handlers), NGX_ERROR);
-
+    ngx_test_null(h, ngx_push_array(
+                             &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
+                  NGX_ERROR);
     *h = ngx_http_index_handler;
 
     return NGX_OK;
index adb9be5c4119db6621a3abb9935c21bc84e1c2e7..b21eac47a5663c7c2923bff6b56df77412d120f8 100644 (file)
@@ -292,10 +292,8 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
 
                 if (chain) {
                     ngx_add_timer(c->write, p->lcf->send_timeout);
-                    c->write->timer_set = 1;
 
                 } else {
-                    c->write->timer_set = 0;
                     /* TODO: del event */
                 }
 
@@ -376,7 +374,6 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
             /* rc == NGX_AGAIN */
 
             ngx_add_timer(c->write, p->lcf->connect_timeout);
-            c->write->timer_set = 1;
 
             return;
         }
@@ -600,29 +597,11 @@ static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
                  p->header_in->end - p->header_in->last);
 
     if (n == NGX_AGAIN) {
-        if (rev->timer_set) {
-            ngx_del_timer(rev);
-        } else {
-            rev->timer_set = 1;
-        }
-
         ngx_add_timer(rev, p->lcf->read_timeout);
 
-        if (!rev->active) {
-            if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
-                /* kqueue */
-                event = NGX_CLEAR_EVENT;
-
-            } else {
-                /* select, poll, /dev/poll */
-                event = NGX_LEVEL_EVENT;
-            }
-
-            if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
-                ngx_http_proxy_finalize_request(p,
-                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
-                return NGX_ERROR;
-            }
+        if (ngx_handle_read_event(rev) == NGX_ERROR) {
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return NGX_ERROR;
         }
 
         return NGX_AGAIN;
@@ -1052,12 +1031,10 @@ static void ngx_http_proxy_close_connection(ngx_connection_t *c)
 
     if (c->read->timer_set) {
         ngx_del_timer(c->read);
-        c->read->timer_set = 0;
     }
 
     if (c->write->timer_set) {
         ngx_del_timer(c->write);
-        c->write->timer_set = 0;
     }
 
     /* TODO: move connection to the connection pool */
index 48980bbbb079f3ce16eddb8036dca30b812fedb7..c2e917815b2fedd09edf5fd2b7134f95dd541f64 100644 (file)
@@ -201,7 +201,7 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
     }
 
 
-    /* init list of the handlers */
+    /* init lists of the handlers */
 
     ngx_init_array(cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
                    cf->cycle->pool, 10, sizeof(ngx_http_handler_pt),
@@ -219,10 +219,6 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
     cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].type = NGX_OK;
 
 
-    ngx_init_array(cmcf->index_handlers, cf->cycle->pool,
-                   3, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR);
-
-
     /* create the lists of the ports, the addresses and the server names
        to allow quickly find the server core module configuration at run-time */
 
index 69c741c87cda3a5bf903719dd60919a2dcfbb91b..59d4d6f58d1b7b5e3dc5fcb801fd72a22566c75f 100644 (file)
@@ -8,12 +8,11 @@
 
 /* STUB */
 int ngx_http_static_handler(ngx_http_request_t *r);
+/**/
 
 static void ngx_http_phase_event_handler(ngx_event_t *rev);
 static void ngx_http_run_phases(ngx_http_request_t *r);
 
-static int ngx_http_core_index_handler(ngx_http_request_t *r);
-
 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
@@ -221,9 +220,6 @@ void ngx_http_handler(ngx_http_request_t *r)
 
     r->connection->write->event_handler = ngx_http_phase_event_handler;
 
-    r->phase = 0;
-    r->phase_handler = 0;
-
     ngx_http_run_phases(r);
 
     return;
@@ -238,6 +234,8 @@ static void ngx_http_phase_event_handler(ngx_event_t *ev)
     c = ev->data;
     r = c->data;
 
+    ngx_log_debug(ev->log, "phase event handler");
+
     ngx_http_run_phases(r);
 
     return;
@@ -263,6 +261,10 @@ static void ngx_http_run_phases(ngx_http_request_t *r)
         {
             rc = h[r->phase_handler](r);
 
+            if (r->closed) {
+                return;
+            }
+
             if (rc == NGX_DECLINED) {
                 continue;
             }
@@ -370,8 +372,24 @@ int ngx_http_core_translate_handler(ngx_http_request_t *r)
     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
     if (r->uri.data[r->uri.len - 1] == '/') {
-        r->content_handler = ngx_http_core_index_handler;
-        return NGX_OK;
+        if (r->path.data == NULL) {
+            ngx_test_null(r->path.data,
+                          ngx_palloc(r->pool,
+                                     clcf->doc_root.len + r->uri.len),
+                          NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+            ngx_cpystrn(ngx_cpymem(r->path.data, clcf->doc_root.data,
+                                   clcf->doc_root.len),
+                        r->uri.data, r->uri.len + 1);
+
+        } else {
+            r->path.data[r->path.len] = '\0';
+        }
+
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "directory index of \"%s\" is forbidden", r->path.data);
+
+        return NGX_HTTP_FORBIDDEN;
     }
 
     /* "+ 2" is for trailing '/' in redirect and '\0' */
@@ -388,9 +406,11 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
 
 #if (WIN9X)
 
-    /* There is no way to open a file or a directory in Win9X with
-       one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag.
-       so we need to check its type before the opening */
+    /*
+     * There is no way to open a file or a directory in Win9X with
+     * one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag.
+     * so we need to check its type before the opening
+     */
 
     r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data);
     if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
@@ -488,42 +508,6 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
 }
 
 
-static int ngx_http_core_index_handler(ngx_http_request_t *r)
-{
-    int                         i, rc;
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
-    h = cmcf->index_handlers.elts;
-    for (i = cmcf->index_handlers.nelts; i > 0; /* void */) {
-        rc = h[--i](r);
-
-        if (rc != NGX_DECLINED) {
-
-            if (rc == NGX_HTTP_NOT_FOUND) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, r->path_err,
-                              "\"%s\" is not found", r->path.data);
-            }
-
-            if (rc == NGX_HTTP_FORBIDDEN) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, r->path_err,
-                          "\"%s\" is forbidden", r->path.data);
-            }
-
-            return rc;
-        }
-    }
-
-    r->path.data[r->path.len] = '\0';
-    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                  "directory index of \"%s\" is forbidden", r->path.data);
-
-    return NGX_HTTP_FORBIDDEN;
-}
-
-
 int ngx_http_send_header(ngx_http_request_t *r)
 {
     return (*ngx_http_top_header_filter)(r);
@@ -591,12 +575,38 @@ int ngx_http_internal_redirect(ngx_http_request_t *r,
         }
     }
 
+    /* clear the modules contexts */
+    ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
+
+    r->phase = 0;
+    r->phase_handler = 0;
+
     ngx_http_handler(r);
 
     return NGX_OK;
 }
 
 
+#if 1       /* STUB: test the delay http handler */
+
+int ngx_http_delay_handler(ngx_http_request_t *r)
+{
+    static int  on;
+
+    if (on++ == 0) {
+        ngx_log_debug(r->connection->log, "SET http delay");
+        ngx_add_timer(r->connection->write, 10000);
+        return NGX_AGAIN;
+    }
+
+    r->connection->write->timedout = 0;
+    ngx_log_debug(r->connection->log, "RESET http delay");
+    return NGX_DECLINED;
+}
+
+#endif
+
+
 static int ngx_http_core_init(ngx_cycle_t *cycle)
 {
     ngx_http_handler_pt        *h;
@@ -609,9 +619,15 @@ static int ngx_http_core_init(ngx_cycle_t *cycle)
     ngx_test_null(h, ngx_push_array(
                              &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
                   NGX_ERROR);
-
     *h = ngx_http_core_translate_handler;
 
+#if 0
+    ngx_test_null(h, ngx_push_array(
+                             &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
+                  NGX_ERROR);
+    *h = ngx_http_delay_handler;
+#endif
+
     return NGX_OK;
 }
 
index 346c332266f1d54bb0e06e2b53cbe4162fd73593..b05452ae73d88a2d1b9088f8103236d915b77ee2 100644 (file)
@@ -121,7 +121,10 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
         } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
             /* 3XX */
             status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 8;
-            r->header_only = 1;
+
+            if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
+                r->header_only = 1;
+            }
 
         } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
             /* 4XX */
index cde7f1d6435a2da0990b24cb0ce1bb89cabc3d81..5efbf3e2d21090545eea6605c75f75f6b55fcbbe 100644 (file)
@@ -22,7 +22,8 @@ static void ngx_http_set_lingering_close(ngx_http_request_t *r);
 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
 static void ngx_http_empty_handler(ngx_event_t *wev);
 
-static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err);
+static void ngx_http_header_parse_error(ngx_http_request_t *r,
+                                        int parse_err, int error);
 static size_t ngx_http_log_error(void *data, char *buf, size_t len);
 
 
@@ -65,7 +66,6 @@ static ngx_http_header_t headers_in[] = {
 
 void ngx_http_init_connection(ngx_connection_t *c)
 {
-    int                  event;
     ngx_event_t         *rev;
     ngx_http_log_ctx_t  *lctx;
 
@@ -104,9 +104,8 @@ void ngx_http_init_connection(ngx_connection_t *c)
     }
 
     ngx_add_timer(rev, c->listening->post_accept_timeout);
-    rev->timer_set = 1;
 
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+    if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_EDGE_EVENT)) {
         /* aio, iocp, epoll */
         ngx_http_init_request(rev);
         return;
@@ -116,25 +115,6 @@ void ngx_http_init_connection(ngx_connection_t *c)
         ngx_http_close_connection(c);
         return;
     }
-
-#if 0
-
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
-        /* kqueue */
-        event = NGX_CLEAR_EVENT;
-
-    } else {
-        /* select, poll, /dev/poll */
-        event = NGX_LEVEL_EVENT;
-    }
-
-    if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
-        ngx_http_close_connection(c);
-    }
-
-#endif
-
-    return;
 }
 
 
@@ -153,10 +133,16 @@ static void ngx_http_init_request(ngx_event_t *rev)
 
     c = rev->data;
 
-    r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
-    if (r == NULL) {
-        ngx_http_close_connection(c);
-        return;
+    if (c->data) {
+        r = c->data;
+        ngx_memzero(r, sizeof(ngx_http_request_t));
+
+    } else {
+        r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
+        if (r == NULL) {
+            ngx_http_close_connection(c);
+            return;
+        }
     }
 
     /* find the server configuration for the address:port */
@@ -315,8 +301,8 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
             r->request_line.data = r->request_start;
             r->request_line.data[r->request_line.len] = '\0';
 
-            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST);
-            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST,
+                                        NGX_HTTP_BAD_REQUEST);
             return;
         }
 
@@ -328,8 +314,8 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
         {
             /* no space for "\r\n" at the end of the header */
 
-            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
-            ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
+            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
+                                        NGX_HTTP_REQUEST_URI_TOO_LARGE);
             return;
         }
 
@@ -459,8 +445,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
 
         /* there was error while a request line parsing */
 
-        ngx_http_header_parse_error(r, rc);
-        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+        ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
 
         return;
     }
@@ -469,11 +454,13 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
 
     if (r->header_in->last == r->header_in->end) {
 
-        /* If it's a pipelined request and a request line is not complete
-           then we need to copy it to the start of the r->header_in hunk.
-           We need to copy it here only if the large client headers
-           are enabled otherwise a request line had been already copied
-           to the start of the r->header_in hunk in ngx_http_set_keepalive() */
+        /*
+         * If it's a pipelined request and a request line is not complete
+         * then we need to copy it to the start of the r->header_in hunk.
+         * We need to copy it here only if the large client headers
+         * are enabled otherwise a request line had been already copied
+         * to the start of the r->header_in hunk in ngx_http_set_keepalive().
+         */
 
         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
@@ -481,9 +468,8 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
             offset = r->request_start - r->header_in->start;
 
             if (offset == 0) {
-                ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
-                ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
-
+                ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
+                                            NGX_HTTP_REQUEST_URI_TOO_LARGE);
                 return;
             }
 
@@ -504,8 +490,8 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
             }
 
         } else {
-            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
-            ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
+            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
+                                        NGX_HTTP_REQUEST_URI_TOO_LARGE);
         }
     }
 
@@ -651,8 +637,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
             } else {
                 if (r->http_version > NGX_HTTP_VERSION_10) {
                     ngx_http_header_parse_error(r,
-                                                NGX_HTTP_PARSE_NO_HOST_HEADER);
-                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                                                NGX_HTTP_PARSE_NO_HOST_HEADER,
+                                                NGX_HTTP_BAD_REQUEST);
                     return;
                 }
                 r->headers_in.host_name_len = 0;
@@ -662,16 +648,20 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
                 r->headers_in.content_length_n =
                              ngx_atoi(r->headers_in.content_length->value.data,
                                       r->headers_in.content_length->value.len);
+
                 if (r->headers_in.content_length_n == NGX_ERROR) {
                     ngx_http_header_parse_error(r,
-                                             NGX_HTTP_PARSE_INVALID_CL_HEADER);
-                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                                             NGX_HTTP_PARSE_INVALID_CL_HEADER,
+                                             NGX_HTTP_BAD_REQUEST);
                     return;
                 }
             }
 
+            if (r->header_timeout_set) {
+                ngx_del_timer(rev);
+            }
+
             rev->event_handler = ngx_http_block_read;
-            c->write->event_handler = ngx_http_writer;
             ngx_http_handler(r);
             return;
 
@@ -679,9 +669,7 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
 
             /* there was error while a header line parsing */
 
-            ngx_http_header_parse_error(r, rc);
-            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
-
+            ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
             return;
         }
 
@@ -697,8 +685,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
 
                 if (offset == 0) {
                     ngx_http_header_parse_error(r,
-                                                NGX_HTTP_PARSE_TOO_LONG_HEADER);
-                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                                                NGX_HTTP_PARSE_TOO_LONG_HEADER,
+                                                NGX_HTTP_BAD_REQUEST);
                     return;
                 }
 
@@ -713,8 +701,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
                 r->header_end -= offset;
 
             } else {
-                ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER);
-                ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
+                                            NGX_HTTP_BAD_REQUEST);
                 return;
             }
         }
@@ -724,7 +712,6 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
 
 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
 {
-    int                        event;
     ssize_t                    n;
     ngx_event_t               *rev;
     ngx_http_core_srv_conf_t  *cscf;
@@ -743,14 +730,7 @@ static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
 
     if (n == NGX_AGAIN) {
         if (!r->header_timeout_set) {
-            if (rev->timer_set) {
-                ngx_del_timer(rev);
-            } else {
-                rev->timer_set = 1;
-            }
-
             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
-
             ngx_add_timer(rev, cscf->client_header_timeout);
             r->header_timeout_set = 1;
         }
@@ -761,25 +741,6 @@ static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
             return NGX_ERROR;
         }
 
-#if 0
-        if (!rev->active) {
-            if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
-                /* kqueue */
-                event = NGX_CLEAR_EVENT;
-
-            } else {
-                /* select, poll, /dev/poll */
-                event = NGX_LEVEL_EVENT;
-            }
-
-            if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
-                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-                ngx_http_close_connection(r->connection);
-                return NGX_ERROR;
-            }
-        }
-#endif
-
         return NGX_AGAIN;
     }
 
@@ -802,7 +763,7 @@ static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
 
 void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
 {
-    ngx_event_t  *rev, *wev;
+    ngx_log_debug(r->connection->log, "finalize http request");
 
     if (r->main || r->closed) {
         return;
@@ -810,16 +771,12 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
 
     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
 
-        rev = r->connection->read;
-        if (rev->timer_set) {
-            ngx_del_timer(rev);
-            rev->timer_set = 0;
+        if (r->connection->read->timer_set) {
+            ngx_del_timer(r->connection->read);
         }
 
-        wev = r->connection->write;
-        if (wev->timer_set) {
-            ngx_del_timer(wev);
-            wev->timer_set = 0;
+        if (r->connection->write->timer_set) {
+            ngx_del_timer(r->connection->write);
         }
 
         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
@@ -836,16 +793,12 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
         return;
     }
 
-    rev = r->connection->read;
-    if (rev->timer_set) {
-        ngx_del_timer(rev);
-        rev->timer_set = 0;
+    if (r->connection->read->timer_set) {
+        ngx_del_timer(r->connection->read);
     }
 
-    wev = r->connection->write;
-    if (wev->timer_set) {
-        ngx_del_timer(wev);
-        wev->timer_set = 0;
+    if (r->connection->write->timer_set) {
+        ngx_del_timer(r->connection->write);
     }
 
     if (r->keepalive != 0) {
@@ -865,7 +818,6 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
 
 static void ngx_http_set_write_handler(ngx_http_request_t *r)
 {
-    int                        event;
     ngx_event_t               *wev;
     ngx_http_core_loc_conf_t  *clcf;
 
@@ -879,44 +831,12 @@ static void ngx_http_set_write_handler(ngx_http_request_t *r)
     clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
                                         ngx_http_core_module);
     ngx_add_timer(wev, clcf->send_timeout);
-    wev->timer_set = 1;
 
     if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
         ngx_http_close_request(r, 0);
         ngx_http_close_connection(r->connection);
     }
 
-#if 0
-
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
-        /* aio, iocp, epoll */
-        return;
-    }
-
-#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
-
-    if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
-        wev->lowat = clcf->send_lowat;
-    }
-
-#endif
-
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
-        /* kqueue */
-        event = NGX_CLEAR_EVENT;
-
-    } else {
-        /* select, poll, /dev/poll */
-        event = NGX_LEVEL_EVENT;
-    }
-
-    if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
-        ngx_http_close_request(r, 0);
-        ngx_http_close_connection(r->connection);
-    }
-
-#endif
-
     return;
 }
 
@@ -924,7 +844,6 @@ static void ngx_http_set_write_handler(ngx_http_request_t *r)
 void ngx_http_writer(ngx_event_t *wev)
 {
     int                        rc;
-    ngx_event_t               *rev;
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
     ngx_http_core_loc_conf_t  *clcf;
@@ -937,53 +856,23 @@ void ngx_http_writer(ngx_event_t *wev)
     ngx_log_debug(c->log, "writer output filter: %d" _ rc);
 
     if (rc == NGX_AGAIN) {
-
-        clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                           ngx_http_core_module);
-        if (wev->timer_set) {
-            ngx_del_timer(wev);
-        } else {
-            wev->timer_set = 1;
+        if (!wev->ready) {
+            clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                                ngx_http_core_module);
+            ngx_add_timer(wev, clcf->send_timeout);
         }
 
-        ngx_add_timer(wev, clcf->send_timeout);
-
-        return;
-    }
+        if (ngx_handle_level_write_event(wev) == NGX_ERROR) {
+            ngx_http_close_request(r, 0);
+            ngx_http_close_connection(r->connection);
+        }
 
-    if (rc == NGX_ERROR) {
-        ngx_http_close_request(r, 0);
-        ngx_http_close_connection(c);
         return;
     }
 
-    /* rc == NGX_OK */
-
     ngx_log_debug(c->log, "http writer done");
 
-    rev = r->connection->read;
-    if (rev->timer_set) {
-        ngx_del_timer(rev);
-        rev->timer_set = 0;
-    }
-
-    if (wev->timer_set) {
-        ngx_del_timer(wev);
-        wev->timer_set = 0;
-    }
-
-    if (r->keepalive != 0) {
-        ngx_http_set_keepalive(r);
-
-    } else if (r->lingering_close) {
-        ngx_http_set_lingering_close(r);
-
-    } else {
-        ngx_http_close_request(r, 0);
-        ngx_http_close_connection(r->connection);
-    }
-
-    return;
+    ngx_http_finalize_request(r, rc);
 }
 
 
@@ -996,22 +885,15 @@ static void ngx_http_block_read(ngx_event_t *rev)
 
     /* aio does not call this handler */
 
-    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
-
-        /* select, poll, /dev/poll */
-
-        rev->blocked = 1;
-
+    if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
         if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
-            c = (ngx_connection_t *) rev->data;
-            r = (ngx_http_request_t *) c->data;
+            c = rev->data;
+            r = c->data;
             ngx_http_close_request(r, 0);
             ngx_http_close_connection(c);
         }
     }
 
-    /* kqueue, epoll */
-
     return;
 }
 
@@ -1027,39 +909,33 @@ int ngx_http_discard_body(ngx_http_request_t *r)
 
     if (rev->timer_set) {
         ngx_del_timer(rev);
-        rev->timer_set = 0;
     }
 
-    if (r->headers_in.content_length_n > 0) {
+    if (r->headers_in.content_length_n <= 0) {
+        return NGX_OK;
+    }
 
-        size = r->header_in->last - r->header_in->pos;
+    size = r->header_in->last - r->header_in->pos;
 
-        if (size) {
-            if (r->headers_in.content_length_n > size) {
-                r->headers_in.content_length_n -= size;
+    if (size) {
+        if (r->headers_in.content_length_n > size) {
+            r->headers_in.content_length_n -= size;
 
-            } else {
-                r->header_in->pos += r->headers_in.content_length_n;
-                r->headers_in.content_length_n = 0;
-                return NGX_OK;
-            }
+        } else {
+            r->header_in->pos += r->headers_in.content_length_n;
+            r->headers_in.content_length_n = 0;
+            return NGX_OK;
         }
+    }
 
-        rev->event_handler = ngx_http_read_discarded_body_event;
+    rev->event_handler = ngx_http_read_discarded_body_event;
 
-        if (rev->blocked) {
-            if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
-                if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
-                                                                == NGX_ERROR) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
-                }
-            }
-
-            rev->blocked = 0;
-            return ngx_http_read_discarded_body(r);
-        }
+    if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
+    return ngx_http_read_discarded_body(r);
+
     return NGX_OK;
 }
 
@@ -1075,12 +951,18 @@ static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
 
     rc = ngx_http_read_discarded_body(r);
 
+    if (rc == NGX_AGAIN) {
+        if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+            ngx_http_close_request(r, rc);
+            ngx_http_close_connection(c);
+            return;
+        }
+    }
+
     if (rc != NGX_OK) {
         ngx_http_close_request(r, rc);
         ngx_http_close_connection(c);
     }
-
-    return;
 }
 
 
@@ -1091,6 +973,10 @@ static int ngx_http_read_discarded_body(ngx_http_request_t *r)
 
     ngx_log_debug(r->connection->log, "http read discarded body");
 
+    if (r->headers_in.content_length_n == 0) {
+        return NGX_OK;
+    }
+
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     if (r->discarded_buffer == NULL) {
@@ -1101,6 +987,7 @@ static int ngx_http_read_discarded_body(ngx_http_request_t *r)
     }
 
     size = r->headers_in.content_length_n;
+
     if (size > clcf->discarded_buffer_size) {
         size = clcf->discarded_buffer_size;
     }
@@ -1111,7 +998,7 @@ static int ngx_http_read_discarded_body(ngx_http_request_t *r)
     }
 
     if (n == NGX_AGAIN) {
-        return NGX_OK;
+        return NGX_AGAIN;
     }
 
     r->headers_in.content_length_n -= n;
@@ -1122,7 +1009,7 @@ static int ngx_http_read_discarded_body(ngx_http_request_t *r)
 
 static void ngx_http_set_keepalive(ngx_http_request_t *r)
 {
-    int                        len, blocked;
+    int                        len;
     ngx_hunk_t                *h;
     ngx_event_t               *rev, *wev;
     ngx_connection_t          *c;
@@ -1139,39 +1026,26 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
     ctx->action = "closing request";
     ngx_http_close_request(r, 0);
 
-    if (rev->timer_set) {
-        ngx_del_timer(rev);
-    } else {
-        rev->timer_set = 1;
-    }
-
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
     ngx_add_timer(rev, clcf->keepalive_timeout);
 
-    if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
-        if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
-            ngx_http_close_connection(c);
-            return;
-        }
-
-        blocked = 1;
-        rev->blocked = 0;
-
-    } else {
-        blocked = 0;
+    if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+        ngx_http_close_connection(c);
+        return;
     }
 
     h = c->buffer;
 
-    /* pipelined request */
     if (h->pos < h->last) {
 
-        /* We do not know here whether a pipelined request is complete
-           so if the large client headers are not enabled
-           we need to copy the data to the start of c->buffer.
-           This copy should be rare because clients that support
-           pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */
+        /* Pipelined request.
+         *
+         * We do not know here whether a pipelined request is complete
+         * so if the large client headers are not enabled
+         * we need to copy the data to the start of c->buffer.
+         * This copy should be rare because clients that support
+         * pipelined requests (Mozilla 1.x, Opera 6.x+) are still rare.
+         */
 
         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
@@ -1195,16 +1069,12 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
     h->pos = h->last = h->start;
     rev->event_handler = ngx_http_keepalive_handler;
     wev = c->write;
+    wev->event_handler = ngx_http_empty_handler;
 
-    if (wev->active) {
-        if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
-            if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
-                ngx_http_close_connection(c);
-                return;
-            }
-
-        } else if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0) {
-            wev->event_handler = ngx_http_empty_handler;
+    if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && wev->active) {
+        if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
+            ngx_http_close_connection(c);
+            return;
         }
     }
 
@@ -1220,7 +1090,7 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
         c->tcp_nopush = 0;
     }
 
-    if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) {
+    if (rev->ready || (ngx_event_flags & NGX_USE_AIO_EVENT)) {
         ngx_http_keepalive_handler(rev);
     }
 }
@@ -1228,7 +1098,7 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
 
 static void ngx_http_keepalive_handler(ngx_event_t *rev)
 {
-    ssize_t n;
+    ssize_t              n;
     ngx_connection_t    *c;
     ngx_http_log_ctx_t  *lctx;
 
@@ -1241,8 +1111,10 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev)
         return;
     }
 
-    /* MSIE closes a keepalive connection with RST flag
-       so we ignore ECONNRESET here */
+    /*
+     * MSIE closes a keepalive connection with RST flag
+     * so we ignore ECONNRESET here.
+     */
 
     rev->ignore_econnreset = 1;
     ngx_set_socket_errno(0);
@@ -1278,46 +1150,35 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev)
 
 static void ngx_http_set_lingering_close(ngx_http_request_t *r)
 {
-    ngx_event_t               *rev;
+    ngx_event_t               *rev, *wev;
     ngx_connection_t          *c;
     ngx_http_core_loc_conf_t  *clcf;
 
     c = r->connection;
-    rev = c->read;
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
+    rev = c->read;
     rev->event_handler = ngx_http_lingering_close_handler;
 
-    if (rev->timer_set) {
-        ngx_del_timer(rev);
-    } else {
-        rev->timer_set = 1;
+    r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
+    ngx_add_timer(rev, clcf->lingering_timeout);
+
+    if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(c);
+        return;
     }
 
-    ngx_add_timer(rev, clcf->lingering_timeout);
+    wev = c->write;
+    wev->event_handler = ngx_http_empty_handler;
 
-    if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
-        if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
+    if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && wev->active) {
+        if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
             ngx_http_close_request(r, 0);
             ngx_http_close_connection(c);
             return;
         }
-        rev->blocked = 0;
-    }
-
-    if (c->write->active) {
-        if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
-            if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
-                ngx_http_close_request(r, 0);
-                ngx_http_close_connection(c);
-                return;
-            }
-
-        } else if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0) {
-            c->write->event_handler = ngx_http_empty_handler;
-        }
     }
 
     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
@@ -1328,7 +1189,7 @@ static void ngx_http_set_lingering_close(ngx_http_request_t *r)
         return;
     }
 
-    if (rev->ready || (ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
+    if (rev->ready || (ngx_event_flags & NGX_USE_AIO_EVENT)) {
         ngx_http_lingering_close_handler(rev);
     }
 }
@@ -1401,11 +1262,6 @@ static void ngx_http_lingering_close_handler(ngx_event_t *rev)
         timer = clcf->lingering_timeout;
     }
 
-    if (rev->timer_set) {
-        ngx_del_timer(rev);
-    } else {
-        rev->timer_set = 1;
-    }
     ngx_add_timer(rev, timer);
 
     return;
@@ -1414,7 +1270,7 @@ static void ngx_http_lingering_close_handler(ngx_event_t *rev)
 
 static void ngx_http_empty_handler(ngx_event_t *wev)
 {
-    ngx_log_debug(wev->log, "http empty handler");
+    ngx_log_debug(wev->log, "http EMPTY handler");
 
     return;
 }
@@ -1457,7 +1313,7 @@ void ngx_http_close_request(ngx_http_request_t *r, int error)
     }
 
     /* ctx->url was allocated from r->pool */
-    ctx = (ngx_http_log_ctx_t *) r->connection->log->data;
+    ctx = r->connection->log->data;
     ctx->url = NULL;
 
     ngx_destroy_pool(r->pool);
@@ -1479,12 +1335,10 @@ void ngx_http_close_connection(ngx_connection_t *c)
 
     if (c->read->timer_set) {
         ngx_del_timer(c->read);
-        c->read->timer_set = 0;
     }
 
     if (c->write->timer_set) {
         ngx_del_timer(c->write);
-        c->write->timer_set = 0;
     }
 
     if (ngx_del_conn) {
@@ -1513,7 +1367,8 @@ void ngx_http_close_connection(ngx_connection_t *c)
 }
 
 
-static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err)
+static void ngx_http_header_parse_error(ngx_http_request_t *r,
+                                        int parse_err, int error)
 {
     ngx_http_log_ctx_t  *ctx;
 
@@ -1532,6 +1387,8 @@ static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err)
     }
 
     r->connection->log->handler = ngx_http_log_error;
+
+    ngx_http_finalize_request(r, error);
 }
 
 
index 1f8b254b9e45c590baadf275be97d0f37e7e2fa1..c3029909fa288fd6ceee131a84a98f4be9208670 100644 (file)
@@ -157,6 +157,8 @@ struct ngx_http_request_s {
     ngx_str_t            args;
     ngx_str_t            exten;
     ngx_str_t            unparsed_uri;
+    ngx_str_t            path;
+    int                  path_allocated;
 
     ngx_http_request_t  *main;
 
@@ -172,9 +174,6 @@ struct ngx_http_request_s {
 
     char                *discarded_buffer;
 
-    ngx_str_t            path;
-    int                  path_err;
-
     /* URI is not started with '/' - "GET http://" */
     unsigned             unusual_uri:1;
     /* URI with "/.", "%" and on Win32 with "//" */
index 825d8bc977fb58cd8387755b8883a138984ebab6..0e16c987d80da8a66aa1cc5fc493da09102ad18e 100644 (file)
@@ -22,6 +22,14 @@ static char msie_stub[] =
 ;
 
 
+static char error_301_page[] =
+"<html>" CRLF
+"<head><title>301 Moved Permanently</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>301 Moved Permanently</h1></center>" CRLF
+;
+
+
 static char error_302_page[] =
 "<html>" CRLF
 "<head><title>302 Found</title></head>" CRLF
@@ -111,8 +119,8 @@ static char error_504_page[] =
 
 
 static ngx_str_t error_pages[] = {
   ngx_null_string,             /* 300 */
-    ngx_null_string,             /* 301 */
/* ngx_null_string, */          /* 300 */
+    ngx_string(error_301_page),
     ngx_string(error_302_page),
     ngx_null_string,             /* 303 */
 
@@ -224,7 +232,11 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
     h->pos = error_tail;
     h->last = error_tail + sizeof(error_tail) - 1;
 
-    if (/* STUB: "msie_padding on/off" */ 1) {
+    if (/* STUB: "msie_padding on/off" */ 1
+        && r->http_version >= NGX_HTTP_VERSION_10
+        && error >= NGX_HTTP_BAD_REQUEST)
+    {
+
         if (ngx_http_output_filter(r, h) == NGX_ERROR) {
             return NGX_ERROR;
         }
index cf587508d425653602f08efc6e8b89932bf12b02..0f580a2858cd984ded91f565e6837b4300e6e25a 100644 (file)
@@ -139,7 +139,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
         return NGX_OK;
     }
 
-    if (!r->connection->write->ready || r->connection->write->delayed) {
+    if (r->connection->write->delayed) {
         return NGX_AGAIN;
     }
 
@@ -161,10 +161,9 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
 
     if (chain == NULL) {
         return NGX_OK;
-
-    } else {
-        return NGX_AGAIN;
     }
+
+    return NGX_AGAIN;
 }
 
 
index 3a4d8e0b445680b0534a8191137e3bbfe82574cd..5eded37b727429702f8c56b4d11b3b34b93966b6 100644 (file)
@@ -109,6 +109,7 @@ ngx_log_debug(ev->log, "aio: aiocb: %08x" _ &ev->aiocb);
         return NGX_ERROR;
     }
 
+    ev->active = 0;
     ngx_log_debug(ev->log, "aio_write: %d" _ rc);
 
     return rc;
index b12afec411fdf53eec178842fafa7849816c01e8..b8760b0fa7fba0b725ea2dae82f2d46d02499ba8 100644 (file)
@@ -1,6 +1,7 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
+#include <ngx_event.h>
 #include <ngx_aio.h>
 
 
@@ -17,10 +18,18 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
     ce = in;
 
     while (ce) {
+
+        /* we can post the single aio operation only */
+
+        if (c->write->active) {
+            return ce;
+        }
+
         buf = prev = ce->hunk->pos;
         size = 0;
 
         /* coalesce the neighbouring chain entries */
+
         while (ce && prev == ce->hunk->pos) {
             size += ce->hunk->last - ce->hunk->pos;
             prev = ce->hunk->last;
@@ -33,34 +42,32 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
         ngx_log_debug(c->log, "aio_write rc: %d" _ rc);
 #endif
 
+        if (rc == NGX_ERROR) {
+            return NGX_CHAIN_ERROR;
+        }
+
         if (rc > 0) {
             sent += rc;
             c->sent += rc;
-
-        } else if (rc == NGX_ERROR) {
-            return NGX_CHAIN_ERROR;
-
-        } else if (rc == NGX_AGAIN) {
-            break;
         }
-    }
 
 #if (NGX_DEBUG_WRITE_CHAIN)
-    ngx_log_debug(c->log, "aio_write sent: " OFF_FMT _ c->sent);
+        ngx_log_debug(c->log, "aio_write sent: " OFF_FMT _ c->sent);
 #endif
 
-    for (ce = in; ce; ce = ce->next) {
+        for (ce = in; ce; ce = ce->next) {
 
-        if (sent >= ce->hunk->last - ce->hunk->pos) {
-            sent -= ce->hunk->last - ce->hunk->pos;
-            ce->hunk->pos = ce->hunk->last;
+            if (sent >= ce->hunk->last - ce->hunk->pos) {
+                sent -= ce->hunk->last - ce->hunk->pos;
+                ce->hunk->pos = ce->hunk->last;
 
-            continue;
-        }
+                continue;
+            }
 
-        ce->hunk->pos += sent;
+            ce->hunk->pos += sent;
 
-        break;
+            break;
+        }
     }
 
     return ce;
index 1a307711464dcd7e04eceabb5f470feedd32ad44..058711681246c08873925e0d58f083985c903eea 100644 (file)
@@ -19,8 +19,13 @@ ngx_os_io_t ngx_os_io = {
     ngx_unix_recv,
     ngx_readv_chain,
     NULL,
+#if (HAVE_FREEBSD_SENDFILE)
     ngx_freebsd_sendfile_chain,
     NGX_HAVE_SENDFILE|NGX_HAVE_ZEROCOPY
+#else
+    ngx_writev_chain,
+    NULL
+#endif
 };
 
 
index 5db40808cd819c4f0619e95b3436c9e784b7024d..f7751a772cfd72393f7de417d7a1b18ca01d5104 100644 (file)
@@ -34,6 +34,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
     ngx_hunk_t      *file;
     ngx_chain_t     *ce, *tail;
 
+    if (!c->write->ready) {
+        return in;
+    }
+
     do {
         ce = in;
         file = NULL;
index 154565413d03a3d2b9a364647a4be61732cb8c98..cef4328216c9e70e5f50cfa51027845c27897337 100644 (file)
@@ -43,8 +43,11 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
         if (n >= 0) {
             if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
                 rev->available -= n;
-                if (rev->available == 0) {
+                if (rev->available <= 0) {
                     rev->ready = 0;
+                    if (rev->available < 0) {
+                        rev->available = 0;
+                    }
                 }
 
                 return n;
index 32b2dd48d551b1cefd280baf4b66b69b4f953a8e..70141e3417947e7db1b95c19b8b5a7a4fe0c8026 100644 (file)
@@ -1,6 +1,7 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
+#include <ngx_event.h>
 
 
 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
@@ -13,6 +14,10 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
     ngx_array_t      iovecs;
     ngx_chain_t     *ce;
 
+    if (!c->write->ready) {
+        return in;
+    }
+
     ngx_init_array(iovecs, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
 
     prev = NULL;
index 96cf000ee4d1576213d309026a58f0a3b72f519e..7d123d71c0a33d6254bec0bc6274a4978d4a2395 100644 (file)
@@ -36,4 +36,8 @@
 #endif
 
 
+/* STUB */
+#define HAVE_LITTLE_ENDIAN  1
+
+
 #endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */
index 038554a686eb8f762d1da98f5ae13330645c14ff..883bed80516bbf5516ef71632a01278d5c69b2c1 100644 (file)
@@ -17,12 +17,12 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
     rev = c->read;
     bytes = 0;
 
-    if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) && rev->ready) {
+    if ((ngx_event_flags & NGX_USE_AIO_EVENT) && rev->ready) {
         rev->ready = 0;
 
         /* the overlapped WSARecv() completed */
 
-        if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+        if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
             if (rev->ovlp.error) {
                 ngx_log_error(NGX_LOG_ERR, c->log, rev->ovlp.error,
                               "WSARecv() failed");
@@ -44,7 +44,7 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
         return bytes;
     }
 
-    if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
+    if (ngx_event_flags & NGX_USE_AIO_EVENT) {
         ovlp = (LPWSAOVERLAPPED) &c->read->ovlp;
         ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
 
@@ -75,7 +75,7 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
         }
     }
 
-    if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+    if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
 
         /*
          * If a socket was bound with I/O completion port
index ebaa77e96184ccc3627bc28fc962f4f21bc6764e..5bfd71542ab5fe1cd04b70ea098a92193afde3a3 100644 (file)
@@ -65,8 +65,8 @@ non-block
 
     wev = c->write;
 
-    if (((ngx_event_flags & NGX_HAVE_AIO_EVENT) && !wev->ready)
-        || ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0))
+    if (((ngx_event_flags & NGX_USE_AIO_EVENT) && !wev->ready)
+        || ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0))
     {
         /*
          * WSABUFs must be 4-byte aligned otherwise
@@ -94,7 +94,7 @@ non-block
             }
         }
 
-        if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
+        if (ngx_event_flags & NGX_USE_AIO_EVENT) {
             ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
             ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
 
@@ -120,7 +120,7 @@ non-block
 
         } else {
 
-            if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+            if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
 
                 /*
                  * If a socket was bound with I/O completion port then
@@ -133,7 +133,7 @@ non-block
         }
 
     } else {
-        if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+        if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
             wev->ready = 0;
 
             /* the overlapped WSASend() completed */