changeset 189:c966c09be66b

nginx-0.0.1-2003-11-18-19:49:00 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 18 Nov 2003 16:49:00 +0000
parents 0061d1f0908d
children 02a715e85df1
files src/event/modules/ngx_kqueue_module.c src/event/ngx_event.h src/event/ngx_event_connect.c src/event/ngx_event_pipe.c src/http/modules/proxy/ngx_http_proxy_cache.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/modules/proxy/ngx_http_proxy_upstream.c src/http/ngx_http_busy_lock.c src/http/ngx_http_cache.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/os/unix/ngx_freebsd_config.h src/os/unix/ngx_linux_config.h src/os/unix/ngx_solaris_config.h
diffstat 15 files changed, 157 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -285,9 +285,9 @@ static int ngx_kqueue_set_event(ngx_even
 
 #if (HAVE_LOWAT_EVENT)
 
-    if ((flags & EV_ADD) && ev->lowat > 0) {
+    if (flags & NGX_LOWAT_EVENT) {
         change_list[nchanges].fflags = NOTE_LOWAT;
-        change_list[nchanges].data = ev->lowat;
+        change_list[nchanges].data = ev->available;
 
     } else {
         change_list[nchanges].fflags = 0;
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -45,13 +45,20 @@ struct ngx_event_s {
     /*
      * kqueue only:
      *   accept:     number of sockets that wait to be accepted
-     *   read:       bytes to read
-     *   write:      available space in buffer
+     *   read:       bytes to read when event is ready
+     *               or lowat when event is set with NGX_LOWAT_EVENT flag
+     *   write:      available space in buffer when event is ready
+     *               or lowat when event is set with NGX_LOWAT_EVENT flag
      *
      * otherwise:
      *   accept:     1 if accept many, 0 otherwise
      */
+
+#if (HAVE_KQUEUE)
     int              available;
+#else
+    unsigned         available:1;
+#endif
 
     unsigned         oneshot:1;
 
@@ -104,10 +111,6 @@ struct ngx_event_s {
     int              kq_errno;
 #endif
 
-#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
-    int              lowat;
-#endif
-
 
 #if (HAVE_AIO)
 
@@ -224,7 +227,11 @@ extern ngx_event_actions_t   ngx_event_a
  * /dev/poll:  we need to flush POLLREMOVE event before closing file
  */
 
-#define NGX_CLOSE_EVENT         1
+#define NGX_CLOSE_EVENT    1
+
+
+/* this flag has meaning only for kqueue */
+#define NGX_LOWAT_EVENT    0
 
 
 #if (HAVE_KQUEUE)
@@ -233,13 +240,17 @@ extern ngx_event_actions_t   ngx_event_a
 #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 and NGX_LOWAT_EVENT are the module flags and they would
+ * not go into a kernel so we need to choose the value that would not interfere
+ * with any existent and future kqueue 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
+#define NGX_CLOSE_EVENT    EV_EOF
+
+#undef  NGX_LOWAT_EVENT
+#define NGX_LOWAT_EVENT    EV_FLAG1
 
 #define NGX_LEVEL_EVENT    0
 #define NGX_ONESHOT_EVENT  EV_ONESHOT
@@ -351,7 +362,7 @@ int ngx_event_post_acceptex(ngx_listenin
 
 
 
-ngx_inline static int ngx_handle_read_event(ngx_event_t *rev, int close)
+ngx_inline static int ngx_handle_read_event(ngx_event_t *rev, int flags)
 {
     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
@@ -380,10 +391,8 @@ ngx_inline static int ngx_handle_read_ev
             return NGX_OK;
         }
 
-        if (rev->active && (rev->ready || close)) {
-            if (ngx_del_event(rev, NGX_READ_EVENT, close ? NGX_CLOSE_EVENT : 0)
-                                                                  == NGX_ERROR)
-            {
+        if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {
+            if (ngx_del_event(rev, NGX_READ_EVENT, flags) == NGX_ERROR) {
                 return NGX_ERROR;
             }
 
@@ -423,21 +432,14 @@ ngx_inline static int ngx_handle_level_r
 }
 
 
-ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int lowat)
+ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int flags)
 {
     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         /* kqueue */
 
-#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
-
-        if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
-            wev->lowat = lowat;
-        }
-
-#endif
         if (!wev->active && !wev->ready) {
-            if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT)
+            if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT|flags)
                                                                 == NGX_ERROR) {
                 return NGX_ERROR;
             }
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -260,6 +260,8 @@ ngx_log_debug(pc->log, "CONNECT: %s" _ p
         return NGX_AGAIN;
     }
 
+ngx_log_debug(pc->log, "CONNECTED");
+
     wev->ready = 1;
 
     return NGX_OK;
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -19,6 +19,7 @@ static int ngx_event_pipe_drain_chains(n
 
 int ngx_event_pipe(ngx_event_pipe_t *p, int do_write)
 {
+    int           flags;
     ngx_event_t  *rev, *wev;
 
     for ( ;; ) {
@@ -45,7 +46,9 @@ int ngx_event_pipe(ngx_event_pipe_t *p, 
     if (p->upstream->fd != -1) {
         rev = p->upstream->read;
 
-        if (ngx_handle_read_event(rev, (rev->eof || rev->error)) == NGX_ERROR) {
+        flags = (rev->eof || rev->error) ? NGX_CLOSE_EVENT : 0;
+
+        if (ngx_handle_read_event(rev, flags) == NGX_ERROR) {
             return NGX_ABORT;
         }
 
@@ -54,12 +57,10 @@ int ngx_event_pipe(ngx_event_pipe_t *p, 
         }
     }
 
-ngx_log_debug(p->log, "DOWN: %d" _ p->downstream->fd);
-
     if (p->downstream->fd != -1) {
         wev = p->downstream->write;
-
-        if (ngx_handle_write_event(wev, p->send_lowat) == NGX_ERROR) {
+        wev->available = p->send_lowat;
+        if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
             return NGX_ABORT;
         }
 
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -283,8 +283,28 @@ void ngx_http_proxy_cache_busy_lock(ngx_
         p->cache->ctx.file.info_valid = 1;
     }
 
+    if (rc == NGX_AGAIN) {
 
-    if (rc == NGX_AGAIN) {
+        if ((ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_HAVE_KQUEUE_EVENT))
+            && !p->request->connection->write->active)
+        {
+            /*
+             * kqueue allows to detect when client closes prematurely
+             * connection
+             */
+
+            p->request->connection->write->event_handler =
+                                        ngx_http_proxy_check_broken_connection;
+
+            if (ngx_add_event(p->request->connection->write, NGX_WRITE_EVENT,
+                                                NGX_CLEAR_EVENT) == NGX_ERROR)
+            {
+                ngx_http_proxy_finalize_request(p,
+                                                NGX_HTTP_INTERNAL_SERVER_ERROR);
+                return;
+            }
+        }
+
         return;
     }
 
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -338,6 +338,45 @@ static int ngx_http_proxy_handler(ngx_ht
 }
 
 
+void ngx_http_proxy_check_broken_connection(ngx_event_t *wev)
+{
+    ngx_connection_t      *c;
+    ngx_http_request_t    *r;
+    ngx_http_proxy_ctx_t  *p;
+
+    ngx_log_debug(wev->log, "http proxy check client");
+
+    c = wev->data;
+    r = c->data;
+    p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+#if (HAVE_KQUEUE)
+    if (wev->kq_eof) {
+        wev->eof = 1;
+
+        if (wev->kq_errno) {
+            wev->error = 1;
+        }
+
+        if (!p->cachable && p->upstream->peer.connection) {
+            ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno,
+                          "client closed prematurely connection, "
+                          "so upstream connection is closed too");
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
+            return;
+        }
+
+        ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno,
+                      "client closed prematurely connection");
+
+        if (p->upstream == NULL || p->upstream->peer.connection == NULL) {
+            ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
+        }
+    }
+#endif
+}
+
+
 void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev)
 {
     ngx_connection_t      *c;
@@ -351,6 +390,12 @@ void ngx_http_proxy_busy_lock_handler(ng
     p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
     p->action = "waiting upstream in busy lock";
 
+    if (p->request->connection->write->eof) {
+        ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
+        ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
+        return;
+    }
+
     if (rev->timedout) {
         rev->timedout = 0;
         p->busy_lock.time++;
@@ -369,14 +414,15 @@ void ngx_http_proxy_busy_lock_handler(ng
 
     /*
      * TODO: kevent() notify about error, otherwise we need to
-     * call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio
+     * call ngx_peek(): recv(MSG_PEEK) to get errno. THINK about aio
      * if there's no error we need to disable event.
      */
 
+#if 0
 #if (HAVE_KQUEUE)
 
     if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) {
-        p->lcf->busy_lock->waiting--;
+        ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
 
         ngx_del_timer(rev);
 
@@ -388,13 +434,12 @@ void ngx_http_proxy_busy_lock_handler(ng
             return;
         }
 
-        /* we have not HTTP code for the case when a client cancels a request */
-
-        ngx_http_proxy_finalize_request(p, 0);
+        ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
         return;
     }
 
 #endif
+#endif
 
 }
 
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -203,6 +203,8 @@ int ngx_http_proxy_send_cached_response(
 int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p);
 int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p);
 
+void ngx_http_proxy_check_broken_connection(ngx_event_t *wev);
+
 void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
 void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p);
 void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -19,7 +19,6 @@ static void ngx_http_proxy_process_upstr
 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_check_broken_connection(ngx_event_t *wev);
 static void ngx_http_proxy_process_body(ngx_event_t *ev);
 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type);
 
@@ -502,8 +501,8 @@ static void ngx_http_proxy_send_request(
     if (rc == NGX_AGAIN) {
         ngx_add_timer(c->write, p->lcf->send_timeout);
 
-        if (ngx_handle_write_event(c->write, /* STUB: lowat */ 0) == NGX_ERROR)
-        {
+        c->write->available = /* STUB: lowat */ 0;
+        if (ngx_handle_write_event(c->write, NGX_LOWAT_EVENT) == NGX_ERROR) {
             ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
             return;
         }
@@ -526,6 +525,8 @@ static void ngx_http_proxy_send_request(
         return;
     }
 
+    ngx_add_timer(c->read, p->lcf->read_timeout);
+
 #if 0
     if (c->read->ready) {
 
@@ -566,9 +567,11 @@ static void ngx_http_proxy_send_request_
         return;
     }
 
-    if (p->request->connection->write->eof) {
-        ngx_http_proxy_close_connection(p);
-        ngx_http_close_connection(p->request->connection);
+    if (p->request->connection->write->eof
+        && (!p->cachable || !p->request_sent))
+    {
+        ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
+        return;
     }
 
     ngx_http_proxy_send_request(p);
@@ -868,7 +871,9 @@ static ssize_t ngx_http_proxy_read_upstr
                  p->header_in->end - p->header_in->last);
 
     if (n == NGX_AGAIN) {
+#if 0
         ngx_add_timer(rev, p->lcf->read_timeout);
+#endif
 
         if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
             ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -1042,45 +1047,6 @@ static void ngx_http_proxy_send_response
 }
 
 
-static void ngx_http_proxy_check_broken_connection(ngx_event_t *wev)
-{
-    ngx_connection_t      *c;
-    ngx_http_request_t    *r;
-    ngx_http_proxy_ctx_t  *p;
-
-    ngx_log_debug(wev->log, "http proxy check client");
-
-    c = wev->data;
-    r = c->data;
-    p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
-#if (HAVE_KQUEUE)
-    if (wev->kq_eof) {
-        wev->eof = 1;
-
-        if (wev->kq_errno) {
-            wev->error = 1;
-        }
-
-        if (!p->cachable && p->upstream->peer.connection) {
-            ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno,
-                          "client closed prematurely connection, "
-                          "so upstream connection is closed too");
-            ngx_http_proxy_close_connection(p);
-
-        } else {
-            ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno,
-                          "client closed prematurely connection");
-        }
- 
-        if (p->upstream->peer.connection == NULL) {
-            ngx_http_close_connection(c);
-        }
-    }
-#endif
-}
-
-
 static void ngx_http_proxy_process_body(ngx_event_t *ev)
 {
     ngx_connection_t      *c;
@@ -1215,6 +1181,11 @@ ngx_log_debug(p->request->connection->lo
         ngx_http_proxy_close_connection(p);
     }
 
+    if (p->request->connection->write->eof) {
+        ngx_http_proxy_finalize_request(p, status ? status:
+                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
+    }
+
     if (status) {
         p->state->status = status;
 
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -103,6 +103,10 @@ ngx_log_debug(bc->event->log, "BUSYLOCK:
 void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
                           ngx_http_busy_lock_ctx_t *bc)
 {
+    if (bl == NULL) {
+        return;
+    }
+
     if (bl->md5) {
         bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
         bl->cachable--;
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -107,6 +107,13 @@ int ngx_http_cache_open_file(ngx_http_re
     ctx->date = h->date;
     ctx->length = h->length;
 
+    if (h->key_len > (size_t) (ctx->buf->last - ctx->buf->pos)) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "cache file \"%s\" is probably invalid",
+                      ctx->file.name.data);
+        return NGX_DECLINED;
+    }
+
     if (h->key_len != ctx->key.len
         || ngx_strncmp(h->key, ctx->key.data, h->key_len) != 0)
     {
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -664,6 +664,10 @@ static ssize_t ngx_http_read_request_hea
         return n;
     }
 
+    if (!rev->ready) {
+        return NGX_AGAIN;
+    }
+
     n = ngx_recv(r->connection, r->header_in->last,
                  r->header_in->end - r->header_in->last);
 
@@ -853,7 +857,8 @@ static void ngx_http_set_write_handler(n
                                         ngx_http_core_module);
     ngx_add_timer(wev, clcf->send_timeout);
 
-    if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
+    wev->available = clcf->send_lowat;
+    if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
         ngx_http_close_request(r, 0);
         ngx_http_close_connection(r->connection);
     }
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -49,6 +49,12 @@
 #define NGX_HTTP_REQUEST_URI_TOO_LARGE     414
 #define NGX_HTTP_RANGE_NOT_SATISFIABLE     416
 
+/*
+ * HTTP does not define a code for the case when a client closed a connection
+ * while we are processing request so we introduce own code to log this case
+ */
+#define NGX_HTTP_CLIENT_CLOSED_REQUEST     420
+
 #define NGX_HTTP_INTERNAL_SERVER_ERROR     500
 #define NGX_HTTP_NOT_IMPLEMENTED           501
 #define NGX_HTTP_BAD_GATEWAY               502
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -33,11 +33,13 @@ typedef u_int32_t  uintptr_t;
 #endif
 
 
+/* TODO: autoconf ??? */
 #if __FreeBSD_version < 330002  /* exactly */
 typedef uint32_t   socklen_t;
 #endif
 
 
+/* TODO: autoconf */
 #if (i386)
 
 #define OFF_FMT    "%lld"
@@ -52,7 +54,7 @@ typedef uint32_t   socklen_t;
 
 #endif
 
-#define TIME_FMT   "%lu"
+#define TIME_FMT   "%ld"
 #define PID_FMT    "%d"
 #define RLIM_FMT   "%lld"
 
@@ -91,8 +93,8 @@ typedef uint32_t   socklen_t;
 
 
 /* STUB */
-#define HAVE_PREAD         1
-#define HAVE_PWRITE        1
+#define HAVE_PREAD         0
+#define HAVE_PWRITE        0
 #define HAVE_LOCALTIME_R   1
 
 
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -34,7 +34,7 @@
 #define OFF_FMT    "%lld"
 #define SIZE_FMT   "%d"
 #define SIZEX_FMT  "%x"
-#define TIME_FMT   "%lu"
+#define TIME_FMT   "%ld"
 #define PID_FMT    "%d"
 #define RLIM_FMT   "%lu"
 
--- a/src/os/unix/ngx_solaris_config.h
+++ b/src/os/unix/ngx_solaris_config.h
@@ -33,7 +33,7 @@ typedef uint32_t  u_int32_t;
 #define OFF_FMT    "%lld"
 #define SIZE_FMT   "%d"
 #define SIZEX_FMT  "%x"
-#define TIME_FMT   "%lu"
+#define TIME_FMT   "%ld"
 #define PID_FMT    "%ld"
 #define RLIM_FMT   "%lu"