nginx-0.0.1-2003-11-18-19:49:00 import
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c
index 7c5ec59..28ffde1 100644
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -283,8 +283,28 @@
p->cache->ctx.file.info_valid = 1;
}
-
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;
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index ecfe658..83b9066 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -338,6 +338,45 @@
}
+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 @@
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 @@
/*
* 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 @@
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
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 138a778..e822a3f 100644
--- 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_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);
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index 3795d15..135050e 100644
--- 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_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 @@
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 @@
return;
}
+ ngx_add_timer(c->read, p->lcf->read_timeout);
+
#if 0
if (c->read->ready) {
@@ -566,9 +567,11 @@
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 @@
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_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_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;
diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c
index 085cd56..172e15e 100644
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -103,6 +103,10 @@
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--;
diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c
index b11558c..b3245a0 100644
--- a/src/http/ngx_http_cache.c
+++ b/src/http/ngx_http_cache.c
@@ -107,6 +107,13 @@
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)
{
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 9dd040e..a59b12a 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -664,6 +664,10 @@
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 @@
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);
}
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index a91dbea..ef26a60 100644
--- 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