nginx-0.0.1-2003-10-12-20:49:16 import

This commit is contained in:
Igor Sysoev 2003-10-12 16:49:16 +00:00
parent b3e73d869e
commit 0a280a3fc0
34 changed files with 565 additions and 550 deletions

View File

@ -688,7 +688,6 @@ static void ngx_clean_old_cycles(ngx_event_t *ev)
ngx_add_timer(ev, 30000); ngx_add_timer(ev, 30000);
} else { } else {
ngx_cleaner_event.timer_set = 0;
ngx_destroy_pool(ngx_temp_pool); ngx_destroy_pool(ngx_temp_pool);
ngx_temp_pool = NULL; ngx_temp_pool = NULL;
ngx_old_cycles.nelts = 0; ngx_old_cycles.nelts = 0;

View 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_range_filter_module;
extern ngx_module_t ngx_http_charset_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_static_module;
extern ngx_module_t ngx_http_index_module;
extern ngx_module_t ngx_http_proxy_module; extern ngx_module_t ngx_http_proxy_module;
extern ngx_module_t ngx_http_log_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_ssi_filter_module, */
&ngx_http_charset_filter_module, &ngx_http_charset_filter_module,
&ngx_http_index_module,
/* &ngx_http_static_module, */ /* &ngx_http_static_module, */
&ngx_http_index_module,
&ngx_http_proxy_module, &ngx_http_proxy_module,
&ngx_http_log_module, &ngx_http_log_module,

View File

@ -68,7 +68,7 @@ static int ngx_aio_init(ngx_cycle_t *cycle)
ngx_io = ngx_os_aio; 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; ngx_event_actions = ngx_aio_module_ctx.actions;

View File

@ -173,7 +173,7 @@ ngx_log_debug(cycle->log, "EV: %d" _ dpcf->events);
ngx_event_actions = ngx_devpoll_module_ctx.actions; 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; return NGX_OK;
} }

View File

@ -105,7 +105,7 @@ static int ngx_iocp_init(ngx_cycle_t *cycle)
ngx_event_actions = ngx_iocp_module_ctx.actions; 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; return NGX_OK;
} }

View File

@ -151,10 +151,9 @@ ngx_log_debug(cycle->log, "EV: %d" _ kcf->events);
ngx_event_actions = ngx_kqueue_module_ctx.actions; ngx_event_actions = ngx_kqueue_module_ctx.actions;
ngx_event_flags = NGX_HAVE_LEVEL_EVENT ngx_event_flags = NGX_USE_ONESHOT_EVENT
|NGX_HAVE_ONESHOT_EVENT
#if (HAVE_CLEAR_EVENT) #if (HAVE_CLEAR_EVENT)
|NGX_HAVE_CLEAR_EVENT |NGX_USE_CLEAR_EVENT
#else #else
|NGX_USE_LEVEL_EVENT |NGX_USE_LEVEL_EVENT
#endif #endif
@ -238,9 +237,11 @@ static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
return NGX_OK; 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 * when the file descriptor is closed a kqueue automatically deletes
before the closing the file descriptor */ * its filters so we do not need to delete explicity the event
* before the closing the file descriptor.
*/
if (flags & NGX_CLOSE_EVENT) { if (flags & NGX_CLOSE_EVENT) {
return NGX_OK; return NGX_OK;
@ -427,13 +428,17 @@ static int ngx_kqueue_process_events(ngx_log_t *log)
if (ev->oneshot && ev->timer_set) { if (ev->oneshot && ev->timer_set) {
ngx_del_timer(ev); ngx_del_timer(ev);
ev->timer_set = 0;
} }
/* fall through */ ev->ready = 1;
ev->event_handler(ev);
break;
case EVFILT_AIO: case EVFILT_AIO:
ev->ready = 1; ev->ready = 1;
ev->active = 0;
ev->event_handler(ev); ev->event_handler(ev);

View File

@ -109,9 +109,7 @@ static int ngx_poll_init(ngx_cycle_t *cycle)
ngx_event_actions = ngx_poll_module_ctx.actions; ngx_event_actions = ngx_poll_module_ctx.actions;
ngx_event_flags = NGX_HAVE_LEVEL_EVENT ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;
|NGX_HAVE_ONESHOT_EVENT
|NGX_USE_LEVEL_EVENT;
return NGX_OK; return NGX_OK;
} }
@ -364,7 +362,6 @@ static int ngx_poll_process_events(ngx_log_t *log)
if (ev->oneshot) { if (ev->oneshot) {
if (ev->timer_set) { if (ev->timer_set) {
ngx_del_timer(ev); ngx_del_timer(ev);
ev->timer_set = 0;
} }
if (ev->write) { if (ev->write) {

View File

@ -108,9 +108,7 @@ static int ngx_select_init(ngx_cycle_t *cycle)
ngx_event_actions = ngx_select_module_ctx.actions; ngx_event_actions = ngx_select_module_ctx.actions;
ngx_event_flags = NGX_HAVE_LEVEL_EVENT ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT;
|NGX_HAVE_ONESHOT_EVENT
|NGX_USE_LEVEL_EVENT;
#if (WIN32) #if (WIN32)
max_read = max_write = 0; max_read = max_write = 0;
@ -401,7 +399,6 @@ static int ngx_select_process_events(ngx_log_t *log)
if (ev->oneshot) { if (ev->oneshot) {
if (ev->timer_set) { if (ev->timer_set) {
ngx_del_timer(ev); ngx_del_timer(ev);
ev->timer_set = 0;
} }
if (ev->write) { if (ev->write) {

View File

@ -224,7 +224,7 @@ ngx_log_debug(cycle->log, "TYPE: %d" _ ecf->use);
/* required by poll */ /* required by poll */
wev->index = NGX_INVALID_INDEX; 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 (s[i].remain) {
if (ngx_del_event(&cycle->old_cycle->read_events[fd], 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 (WIN32)
if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
rev->event_handler = &ngx_event_acceptex; rev->event_handler = &ngx_event_acceptex;
if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) { if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {

View File

@ -24,9 +24,6 @@ struct ngx_event_s {
void *data; void *data;
void (*event_handler)(ngx_event_t *ev); void (*event_handler)(ngx_event_t *ev);
#if 0
int (*close_handler)(ngx_event_t *ev);
#endif
void *context; void *context;
char *action; char *action;
@ -35,9 +32,6 @@ struct ngx_event_s {
ngx_event_t *prev; /* queue in mutex(), aio_read(), aio_write() */ ngx_event_t *prev; /* queue in mutex(), aio_read(), aio_write() */
ngx_event_t *next; /* */ ngx_event_t *next; /* */
#if 0
int (*timer_handler)(ngx_event_t *ev);
#endif
ngx_event_t *timer_prev; ngx_event_t *timer_prev;
ngx_event_t *timer_next; ngx_event_t *timer_next;
@ -61,17 +55,26 @@ struct ngx_event_s {
#endif #endif
unsigned write:1; unsigned write:1;
unsigned instance:1; /* used to detect stale events in kqueue, /* used to detect stale events in kqueue, rt signals and epoll */
rt signals and epoll */ unsigned instance:1;
/*
* event was passed or would be passed to a kernel;
* the posted aio operation.
*/
unsigned active:1; unsigned active:1;
/* ready event; the complete aio operation */
unsigned ready:1; unsigned ready:1;
unsigned timedout:1; unsigned timedout:1;
unsigned blocked:1;
unsigned timer_set:1; unsigned timer_set:1;
#if 1
unsigned blocked:1;
#endif
unsigned delayed:1; unsigned delayed:1;
unsigned process:1;
unsigned read_discarded:1; unsigned read_discarded:1;
unsigned ignore_econnreset:1; unsigned ignore_econnreset:1;
@ -156,50 +159,68 @@ typedef struct {
} ngx_event_actions_t; } ngx_event_actions_t;
/* The event filter requires to read/write the whole data - /*
select, poll, /dev/poll, kqueue. */ * The event filter requires to read/write the whole data -
#define NGX_HAVE_LEVEL_EVENT 0x00000001 * 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. */ * The event filter is deleted after a notification without an additional
#define NGX_HAVE_ONESHOT_EVENT 0x00000002 * syscall - select, poll, kqueue.
*/
#define NGX_USE_ONESHOT_EVENT 0x00000002
/* The event filter notifies only the changes and an initial level - kqueue */ /*
#define NGX_HAVE_CLEAR_EVENT 0x00000004 * 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 */ * The event filter has kqueue features - the eof flag, errno,
* available data, etc
*/
#define NGX_HAVE_KQUEUE_EVENT 0x00000008 #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 */ * 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 #define NGX_HAVE_LOWAT_EVENT 0x00000010
/* The event filter notifies only the changes (the edges) /*
but not an initial level - epoll */ * The event filter notifies only the changes (the edges)
#define NGX_HAVE_EDGE_EVENT 0x00000020 * 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_HAVE_SIGIO_EVENT 0x00000040 * 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 */ /*
#define NGX_HAVE_AIO_EVENT 0x00000080 * 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 */ * Need to add socket or handle only once - i/o completion port.
#define NGX_HAVE_IOCP_EVENT 0x00000100 * It also requires HAVE_AIO_EVENT and NGX_HAVE_AIO_EVENT to be set.
*/
#define NGX_USE_IOCP_EVENT 0x00000100
#define NGX_USE_LEVEL_EVENT 0x00010000
#define NGX_USE_AIO_EVENT 0x00020000
/*
/* Event filter is deleted before closing file. * The event filter is deleted before the closing file.
Has no meaning for select, poll, epoll. * Has no meaning for select, poll, epoll.
*
kqueue: kqueue deletes event filters for file that closed * kqueue: kqueue deletes event filters for file that closed
so we need only to delete filters in user-level batch array * so we need only to delete filters in user-level batch array
/dev/poll: we need to flush POLLREMOVE event before closing file */ * /dev/poll: we need to flush POLLREMOVE event before closing file
*/
#define NGX_CLOSE_EVENT 1 #define NGX_CLOSE_EVENT 1
@ -209,10 +230,12 @@ typedef struct {
#define NGX_READ_EVENT EVFILT_READ #define NGX_READ_EVENT EVFILT_READ
#define NGX_WRITE_EVENT EVFILT_WRITE #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 * NGX_CLOSE_EVENT is the module flag and it would not go into a kernel
and future flags. kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR. * so we need to choose the value that would not interfere with any existent
They are reserved and cleared on a kernel entrance */ * 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 #undef NGX_CLOSE_EVENT
#define NGX_CLOSE_EVENT EV_FLAG1 #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) 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 */ /* aio, iocp, epoll */
return NGX_OK; return NGX_OK;
} }
if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
/* kqueue */ /* 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) 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 */ /* aio, iocp, epoll */
return NGX_OK; return NGX_OK;
} }
if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
/* kqueue */ /* 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;
}
/* ***************************** */ /* ***************************** */

View File

@ -20,12 +20,10 @@ int ngx_event_close_connection(ngx_event_t *ev)
if (c->read->timer_set) { if (c->read->timer_set) {
ngx_del_timer(c->read); ngx_del_timer(c->read);
c->read->timer_set = 0;
} }
if (c->write->timer_set) { if (c->write->timer_set) {
ngx_del_timer(c->write); ngx_del_timer(c->write);
c->write->timer_set = 0;
} }
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);

View File

@ -202,7 +202,7 @@ int ngx_event_connect_peer(ngx_peer_connection_t *pc)
/* TODO: epoll, aio, iocp */ /* 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; event = NGX_CLEAR_EVENT;
} else { /* select, poll, /dev/poll */ } else { /* select, poll, /dev/poll */

View 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 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_hunk_t *h;
ngx_chain_t *entry, *next, *saved_in, *saved_read; ngx_chain_t *entry, *next, *saved_in, *saved_read;

View File

@ -4,7 +4,7 @@
#include <ngx_event.h> #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 */ 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) void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
{ {
ngx_event_t *e, *queue; 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) #if (NGX_DEBUG_EVENT)
ngx_connection_t *c = ev->data; c = ev->data;
ngx_log_debug(ev->log, "set timer: %d:%d, slot: %d" _ ngx_log_debug(ev->log, "set timer: %d:%d:%d, slot: %d" _
c->fd _ timer _ ngx_timer_cur_queue); c->fd _ ev->write _ timer _ ngx_timer_cur_queue);
#endif #endif
if (ev->timer_next || ev->timer_prev) { 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->timer_next = ev;
e->timer_prev = 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) { if (timer == NGX_MAX_MSEC) {
return 0; 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; timer += ngx_temp_timer_queue.timer_next->timer_delta;
ev = ngx_temp_timer_queue.timer_next; 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_del_timer(ev);
ngx_add_timer(ev, timer); ngx_add_timer(ev, timer);
} }

View File

@ -19,7 +19,7 @@ ngx_inline static void ngx_event_del_timer(ngx_event_t *ev)
{ {
#if (NGX_DEBUG_EVENT) #if (NGX_DEBUG_EVENT)
ngx_connection_t *c = ev->data; 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 #endif
if (!ev->timer_next || !ev->timer_prev) { 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) { if (ev->timer_prev) {
ev->timer_prev = NULL; ev->timer_prev = NULL;
} }
ev->timer_set = 0;
} }

View File

@ -23,7 +23,7 @@ typedef struct {
ngx_hunk_t *out_hunk; ngx_hunk_t *out_hunk;
int hunks; int hunks;
int length; off_t length;
void *alloc; void *alloc;
unsigned flush:4; 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) #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 #if 0
ngx_test_null(ctx->alloc, ngx_alloc(200K, r->log), NGX_ERROR); ngx_test_null(ctx->alloc, ngx_alloc(200K, r->log), NGX_ERROR);
#else #else
ctx->alloc = (void *) ~NULL; ctx->alloc = (void *) -1;
#endif #endif
rc = deflateInit2(&ctx->zstream, /**/ 1, Z_DEFLATED, rc = deflateInit2(&ctx->zstream, /**/ 1, Z_DEFLATED,

View File

@ -10,10 +10,20 @@ typedef struct {
} ngx_http_index_conf_t; } ngx_http_index_conf_t;
typedef struct {
int index;
unsigned tested:1;
} ngx_http_index_ctx_t;
#define NGX_HTTP_DEFAULT_INDEX "index.html" #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 int ngx_http_index_init(ngx_cycle_t *cycle);
static void *ngx_http_index_create_conf(ngx_conf_t *cf); static void *ngx_http_index_create_conf(ngx_conf_t *cf);
static char *ngx_http_index_merge_conf(ngx_conf_t *cf, static char *ngx_http_index_merge_conf(ngx_conf_t *cf,
@ -58,13 +68,13 @@ ngx_module_t ngx_http_index_module = {
/* /*
Try to open the first index file before the directory existence test * 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. * because the valid requests should be many more than invalid ones.
If open() failed then stat() should be more quickly because some data * If open() failed then stat() should be more quickly because some data
is already cached in the kernel. * is already cached in the kernel.
Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR). * Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
Unix has ENOTDIR error, although it less helpfull - it shows only * Unix has ENOTDIR error, although it less helpfull - it shows only
that path contains the usual file in place of the directory. * that path contains the usual file in place of the directory.
*/ */
int ngx_http_index_handler(ngx_http_request_t *r) int ngx_http_index_handler(ngx_http_request_t *r)
@ -74,16 +84,29 @@ int ngx_http_index_handler(ngx_http_request_t *r)
ngx_str_t redirect, *index; ngx_str_t redirect, *index;
ngx_err_t err; ngx_err_t err;
ngx_fd_t fd; ngx_fd_t fd;
ngx_http_index_ctx_t *ctx;
ngx_http_index_conf_t *icf; ngx_http_index_conf_t *icf;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf;
if (r->uri.data[r->uri.len - 1] != '/') {
return NGX_DECLINED;
}
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);
}
icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
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_test_null(r->path.data,
ngx_palloc(r->pool, ngx_palloc(r->pool, r->path_allocated),
clcf->doc_root.len + r->uri.len
+ icf->max_index_len),
NGX_HTTP_INTERNAL_SERVER_ERROR); NGX_HTTP_INTERNAL_SERVER_ERROR);
redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data, redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data,
@ -91,21 +114,28 @@ int ngx_http_index_handler(ngx_http_request_t *r)
file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1); file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1);
r->path.len = file - r->path.data; r->path.len = file - r->path.data;
test_dir = 1; } else{
path_not_found = 1; redirect.data = r->path.data + r->path.len;
file = redirect.data + r->uri.len;
}
index = icf->indices.elts; 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] != '/') { if (index[ctx->index].data[0] == '/') {
ngx_memcpy(file, index[i].data, index[i].len + 1); name = index[ctx->index].data;
name = r->path.data;
} else { } 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); fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
if (fd == NGX_AGAIN) {
return NGX_AGAIN;
}
if (fd == NGX_INVALID_FILE) { if (fd == NGX_INVALID_FILE) {
err = ngx_errno; 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); "DEBUG: " ngx_open_file_n " %s failed", name);
if (err == NGX_ENOTDIR) { if (err == NGX_ENOTDIR) {
path_not_found = 1; return ngx_http_index_error(r, ctx, err);
} else if (err == NGX_EACCES) { } else if (err == NGX_EACCES) {
r->path_err = err; return ngx_http_index_error(r, ctx, err);
return NGX_HTTP_FORBIDDEN;
} }
if (test_dir) { if (!ctx->tested) {
if (path_not_found) { rc = ngx_http_index_test_dir(r, ctx);
r->path_err = err;
return NGX_HTTP_NOT_FOUND;
}
rc = ngx_http_index_test_dir(r);
if (rc != NGX_OK) { if (rc != NGX_OK) {
return rc; return rc;
} }
test_dir = 0; ctx->tested = 1;
} }
if (err == NGX_ENOENT) { 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.name.data = name;
r->file.fd = fd; r->file.fd = fd;
if (index[i].data[0] == '/') { if (index[ctx->index].data[0] == '/') {
r->file.name.len = index[i].len; r->file.name.len = index[ctx->index].len;
redirect.len = index[i].len; redirect.len = index[ctx->index].len;
redirect.data = index[i].data; redirect.data = index[ctx->index].data;
} else { } else {
redirect.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[i].len; r->file.name.len = clcf->doc_root.len + r->uri.len
+ index[ctx->index].len;
} }
return ngx_http_internal_redirect(r, &redirect, NULL); 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 - 1] = '\0';
r->path.data[r->path.len] = '\0'; r->path.data[r->path.len] = '\0';
ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data); 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) { 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] = '/'; 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); ngx_file_type_n " %s failed", r->path.data);
return NGX_HTTP_INTERNAL_SERVER_ERROR; 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)) { if (ngx_is_dir(r->file.info)) {
return NGX_OK; 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]; ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
cmcf = ctx->main_conf[ngx_http_core_module.ctx_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; *h = ngx_http_index_handler;
return NGX_OK; return NGX_OK;

View File

@ -292,10 +292,8 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
if (chain) { if (chain) {
ngx_add_timer(c->write, p->lcf->send_timeout); ngx_add_timer(c->write, p->lcf->send_timeout);
c->write->timer_set = 1;
} else { } else {
c->write->timer_set = 0;
/* TODO: del event */ /* TODO: del event */
} }
@ -376,7 +374,6 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
/* rc == NGX_AGAIN */ /* rc == NGX_AGAIN */
ngx_add_timer(c->write, p->lcf->connect_timeout); ngx_add_timer(c->write, p->lcf->connect_timeout);
c->write->timer_set = 1;
return; return;
} }
@ -600,30 +597,12 @@ static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
p->header_in->end - p->header_in->last); p->header_in->end - p->header_in->last);
if (n == NGX_AGAIN) { 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); ngx_add_timer(rev, p->lcf->read_timeout);
if (!rev->active) { if (ngx_handle_read_event(rev) == NGX_ERROR) {
if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
/* 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; return NGX_ERROR;
} }
}
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -1052,12 +1031,10 @@ static void ngx_http_proxy_close_connection(ngx_connection_t *c)
if (c->read->timer_set) { if (c->read->timer_set) {
ngx_del_timer(c->read); ngx_del_timer(c->read);
c->read->timer_set = 0;
} }
if (c->write->timer_set) { if (c->write->timer_set) {
ngx_del_timer(c->write); ngx_del_timer(c->write);
c->write->timer_set = 0;
} }
/* TODO: move connection to the connection pool */ /* TODO: move connection to the connection pool */

View 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, ngx_init_array(cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), 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; 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 /* create the lists of the ports, the addresses and the server names
to allow quickly find the server core module configuration at run-time */ to allow quickly find the server core module configuration at run-time */

View File

@ -8,12 +8,11 @@
/* STUB */ /* STUB */
int ngx_http_static_handler(ngx_http_request_t *r); 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_phase_event_handler(ngx_event_t *rev);
static void ngx_http_run_phases(ngx_http_request_t *r); 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 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 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); 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->connection->write->event_handler = ngx_http_phase_event_handler;
r->phase = 0;
r->phase_handler = 0;
ngx_http_run_phases(r); ngx_http_run_phases(r);
return; return;
@ -238,6 +234,8 @@ static void ngx_http_phase_event_handler(ngx_event_t *ev)
c = ev->data; c = ev->data;
r = c->data; r = c->data;
ngx_log_debug(ev->log, "phase event handler");
ngx_http_run_phases(r); ngx_http_run_phases(r);
return; return;
@ -263,6 +261,10 @@ static void ngx_http_run_phases(ngx_http_request_t *r)
{ {
rc = h[r->phase_handler](r); rc = h[r->phase_handler](r);
if (r->closed) {
return;
}
if (rc == NGX_DECLINED) { if (rc == NGX_DECLINED) {
continue; 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); cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (r->uri.data[r->uri.len - 1] == '/') { if (r->uri.data[r->uri.len - 1] == '/') {
r->content_handler = ngx_http_core_index_handler; if (r->path.data == NULL) {
return NGX_OK; 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' */ /* "+ 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) #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. * There is no way to open a file or a directory in Win9X with
so we need to check its type before the opening */ * 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); r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data);
if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { 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) int ngx_http_send_header(ngx_http_request_t *r)
{ {
return (*ngx_http_top_header_filter)(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); ngx_http_handler(r);
return NGX_OK; 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) static int ngx_http_core_init(ngx_cycle_t *cycle)
{ {
ngx_http_handler_pt *h; 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( ngx_test_null(h, ngx_push_array(
&cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
NGX_ERROR); NGX_ERROR);
*h = ngx_http_core_translate_handler; *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; return NGX_OK;
} }

View 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) { } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
/* 3XX */ /* 3XX */
status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 8; status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 8;
if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
r->header_only = 1; r->header_only = 1;
}
} else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) { } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
/* 4XX */ /* 4XX */

View 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_lingering_close_handler(ngx_event_t *ev);
static void ngx_http_empty_handler(ngx_event_t *wev); 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); 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) void ngx_http_init_connection(ngx_connection_t *c)
{ {
int event;
ngx_event_t *rev; ngx_event_t *rev;
ngx_http_log_ctx_t *lctx; 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); 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 */ /* aio, iocp, epoll */
ngx_http_init_request(rev); ngx_http_init_request(rev);
return; return;
@ -116,25 +115,6 @@ void ngx_http_init_connection(ngx_connection_t *c)
ngx_http_close_connection(c); ngx_http_close_connection(c);
return; 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,11 +133,17 @@ static void ngx_http_init_request(ngx_event_t *rev)
c = rev->data; c = rev->data;
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)); r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
if (r == NULL) { if (r == NULL) {
ngx_http_close_connection(c); ngx_http_close_connection(c);
return; return;
} }
}
/* find the server configuration for the address:port */ /* 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_start;
r->request_line.data[r->request_line.len] = '\0'; r->request_line.data[r->request_line.len] = '\0';
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST); ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST,
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); NGX_HTTP_BAD_REQUEST);
return; 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 */ /* 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_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); NGX_HTTP_REQUEST_URI_TOO_LARGE);
return; return;
} }
@ -459,8 +445,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
/* there was error while a request line parsing */ /* there was error while a request line parsing */
ngx_http_header_parse_error(r, rc); ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return; 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 (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. * If it's a pipelined request and a request line is not complete
We need to copy it here only if the large client headers * then we need to copy it to the start of the r->header_in hunk.
are enabled otherwise a request line had been already copied * We need to copy it here only if the large client headers
to the start of the r->header_in hunk in ngx_http_set_keepalive() */ * 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); 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; offset = r->request_start - r->header_in->start;
if (offset == 0) { if (offset == 0) {
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); 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_REQUEST_URI_TOO_LARGE);
return; return;
} }
@ -504,8 +490,8 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
} }
} else { } else {
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); 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_REQUEST_URI_TOO_LARGE);
} }
} }
@ -651,8 +637,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
} else { } else {
if (r->http_version > NGX_HTTP_VERSION_10) { if (r->http_version > NGX_HTTP_VERSION_10) {
ngx_http_header_parse_error(r, ngx_http_header_parse_error(r,
NGX_HTTP_PARSE_NO_HOST_HEADER); NGX_HTTP_PARSE_NO_HOST_HEADER,
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); NGX_HTTP_BAD_REQUEST);
return; return;
} }
r->headers_in.host_name_len = 0; 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 = r->headers_in.content_length_n =
ngx_atoi(r->headers_in.content_length->value.data, ngx_atoi(r->headers_in.content_length->value.data,
r->headers_in.content_length->value.len); r->headers_in.content_length->value.len);
if (r->headers_in.content_length_n == NGX_ERROR) { if (r->headers_in.content_length_n == NGX_ERROR) {
ngx_http_header_parse_error(r, ngx_http_header_parse_error(r,
NGX_HTTP_PARSE_INVALID_CL_HEADER); NGX_HTTP_PARSE_INVALID_CL_HEADER,
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); NGX_HTTP_BAD_REQUEST);
return; return;
} }
} }
if (r->header_timeout_set) {
ngx_del_timer(rev);
}
rev->event_handler = ngx_http_block_read; rev->event_handler = ngx_http_block_read;
c->write->event_handler = ngx_http_writer;
ngx_http_handler(r); ngx_http_handler(r);
return; return;
@ -679,9 +669,7 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
/* there was error while a header line parsing */ /* there was error while a header line parsing */
ngx_http_header_parse_error(r, rc); ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return; return;
} }
@ -697,8 +685,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
if (offset == 0) { if (offset == 0) {
ngx_http_header_parse_error(r, ngx_http_header_parse_error(r,
NGX_HTTP_PARSE_TOO_LONG_HEADER); NGX_HTTP_PARSE_TOO_LONG_HEADER,
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); NGX_HTTP_BAD_REQUEST);
return; return;
} }
@ -713,8 +701,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
r->header_end -= offset; r->header_end -= offset;
} else { } else {
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER); ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); NGX_HTTP_BAD_REQUEST);
return; 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) static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
{ {
int event;
ssize_t n; ssize_t n;
ngx_event_t *rev; ngx_event_t *rev;
ngx_http_core_srv_conf_t *cscf; 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 (n == NGX_AGAIN) {
if (!r->header_timeout_set) { 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); cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
ngx_add_timer(rev, cscf->client_header_timeout); ngx_add_timer(rev, cscf->client_header_timeout);
r->header_timeout_set = 1; 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; 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; 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) 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) { if (r->main || r->closed) {
return; return;
@ -810,16 +771,12 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
rev = r->connection->read; if (r->connection->read->timer_set) {
if (rev->timer_set) { ngx_del_timer(r->connection->read);
ngx_del_timer(rev);
rev->timer_set = 0;
} }
wev = r->connection->write; if (r->connection->write->timer_set) {
if (wev->timer_set) { ngx_del_timer(r->connection->write);
ngx_del_timer(wev);
wev->timer_set = 0;
} }
ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc)); 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; return;
} }
rev = r->connection->read; if (r->connection->read->timer_set) {
if (rev->timer_set) { ngx_del_timer(r->connection->read);
ngx_del_timer(rev);
rev->timer_set = 0;
} }
wev = r->connection->write; if (r->connection->write->timer_set) {
if (wev->timer_set) { ngx_del_timer(r->connection->write);
ngx_del_timer(wev);
wev->timer_set = 0;
} }
if (r->keepalive != 0) { 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) static void ngx_http_set_write_handler(ngx_http_request_t *r)
{ {
int event;
ngx_event_t *wev; ngx_event_t *wev;
ngx_http_core_loc_conf_t *clcf; 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, clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_core_module); ngx_http_core_module);
ngx_add_timer(wev, clcf->send_timeout); ngx_add_timer(wev, clcf->send_timeout);
wev->timer_set = 1;
if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
ngx_http_close_request(r, 0); ngx_http_close_request(r, 0);
ngx_http_close_connection(r->connection); 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; 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) void ngx_http_writer(ngx_event_t *wev)
{ {
int rc; int rc;
ngx_event_t *rev;
ngx_connection_t *c; ngx_connection_t *c;
ngx_http_request_t *r; ngx_http_request_t *r;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf;
@ -937,48 +856,13 @@ void ngx_http_writer(ngx_event_t *wev)
ngx_log_debug(c->log, "writer output filter: %d" _ rc); ngx_log_debug(c->log, "writer output filter: %d" _ rc);
if (rc == NGX_AGAIN) { if (rc == NGX_AGAIN) {
if (!wev->ready) {
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r, clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_core_module); ngx_http_core_module);
if (wev->timer_set) {
ngx_del_timer(wev);
} else {
wev->timer_set = 1;
}
ngx_add_timer(wev, clcf->send_timeout); ngx_add_timer(wev, clcf->send_timeout);
return;
} }
if (rc == NGX_ERROR) { if (ngx_handle_level_write_event(wev) == 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_request(r, 0);
ngx_http_close_connection(r->connection); ngx_http_close_connection(r->connection);
} }
@ -986,6 +870,11 @@ void ngx_http_writer(ngx_event_t *wev)
return; return;
} }
ngx_log_debug(c->log, "http writer done");
ngx_http_finalize_request(r, rc);
}
static void ngx_http_block_read(ngx_event_t *rev) static void ngx_http_block_read(ngx_event_t *rev)
{ {
@ -996,22 +885,15 @@ static void ngx_http_block_read(ngx_event_t *rev)
/* aio does not call this handler */ /* aio does not call this handler */
if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
/* select, poll, /dev/poll */
rev->blocked = 1;
if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
c = (ngx_connection_t *) rev->data; c = rev->data;
r = (ngx_http_request_t *) c->data; r = c->data;
ngx_http_close_request(r, 0); ngx_http_close_request(r, 0);
ngx_http_close_connection(c); ngx_http_close_connection(c);
} }
} }
/* kqueue, epoll */
return; return;
} }
@ -1027,10 +909,11 @@ int ngx_http_discard_body(ngx_http_request_t *r)
if (rev->timer_set) { if (rev->timer_set) {
ngx_del_timer(rev); 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;
@ -1047,18 +930,11 @@ int ngx_http_discard_body(ngx_http_request_t *r)
rev->event_handler = ngx_http_read_discarded_body_event; rev->event_handler = ngx_http_read_discarded_body_event;
if (rev->blocked) { if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
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; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
}
rev->blocked = 0;
return ngx_http_read_discarded_body(r); return ngx_http_read_discarded_body(r);
}
}
return NGX_OK; 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); 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) { if (rc != NGX_OK) {
ngx_http_close_request(r, rc); ngx_http_close_request(r, rc);
ngx_http_close_connection(c); 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"); 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); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->discarded_buffer == NULL) { 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; size = r->headers_in.content_length_n;
if (size > clcf->discarded_buffer_size) { if (size > clcf->discarded_buffer_size) {
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) { if (n == NGX_AGAIN) {
return NGX_OK; return NGX_AGAIN;
} }
r->headers_in.content_length_n -= n; 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) static void ngx_http_set_keepalive(ngx_http_request_t *r)
{ {
int len, blocked; int len;
ngx_hunk_t *h; ngx_hunk_t *h;
ngx_event_t *rev, *wev; ngx_event_t *rev, *wev;
ngx_connection_t *c; ngx_connection_t *c;
@ -1139,39 +1026,26 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
ctx->action = "closing request"; ctx->action = "closing request";
ngx_http_close_request(r, 0); 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); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
ngx_add_timer(rev, clcf->keepalive_timeout); ngx_add_timer(rev, clcf->keepalive_timeout);
if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
ngx_http_close_connection(c); ngx_http_close_connection(c);
return; return;
} }
blocked = 1;
rev->blocked = 0;
} else {
blocked = 0;
}
h = c->buffer; h = c->buffer;
/* pipelined request */
if (h->pos < h->last) { if (h->pos < h->last) {
/* We do not know here whether a pipelined request is complete /* Pipelined request.
so if the large client headers are not enabled *
we need to copy the data to the start of c->buffer. * We do not know here whether a pipelined request is complete
This copy should be rare because clients that support * so if the large client headers are not enabled
pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */ * 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); cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
@ -1195,17 +1069,13 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
h->pos = h->last = h->start; h->pos = h->last = h->start;
rev->event_handler = ngx_http_keepalive_handler; rev->event_handler = ngx_http_keepalive_handler;
wev = c->write; wev = c->write;
wev->event_handler = ngx_http_empty_handler;
if (wev->active) { if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && wev->active) {
if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
ngx_http_close_connection(c); ngx_http_close_connection(c);
return; return;
} }
} else if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0) {
wev->event_handler = ngx_http_empty_handler;
}
} }
ctx->action = "keepalive"; ctx->action = "keepalive";
@ -1220,7 +1090,7 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
c->tcp_nopush = 0; 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); ngx_http_keepalive_handler(rev);
} }
} }
@ -1241,8 +1111,10 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev)
return; 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; rev->ignore_econnreset = 1;
ngx_set_socket_errno(0); ngx_set_socket_errno(0);
@ -1278,45 +1150,34 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev)
static void ngx_http_set_lingering_close(ngx_http_request_t *r) 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_connection_t *c;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf;
c = r->connection; c = r->connection;
rev = c->read;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 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; rev->event_handler = ngx_http_lingering_close_handler;
if (rev->timer_set) { r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
ngx_del_timer(rev);
} else {
rev->timer_set = 1;
}
ngx_add_timer(rev, clcf->lingering_timeout); ngx_add_timer(rev, clcf->lingering_timeout);
if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == 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_request(r, 0);
ngx_http_close_connection(c); ngx_http_close_connection(c);
return; return;
} }
} else if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0) { wev = c->write;
c->write->event_handler = ngx_http_empty_handler; 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_request(r, 0);
ngx_http_close_connection(c);
return;
} }
} }
@ -1328,7 +1189,7 @@ static void ngx_http_set_lingering_close(ngx_http_request_t *r)
return; 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); 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; timer = clcf->lingering_timeout;
} }
if (rev->timer_set) {
ngx_del_timer(rev);
} else {
rev->timer_set = 1;
}
ngx_add_timer(rev, timer); ngx_add_timer(rev, timer);
return; 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) 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; 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->url was allocated from r->pool */
ctx = (ngx_http_log_ctx_t *) r->connection->log->data; ctx = r->connection->log->data;
ctx->url = NULL; ctx->url = NULL;
ngx_destroy_pool(r->pool); ngx_destroy_pool(r->pool);
@ -1479,12 +1335,10 @@ void ngx_http_close_connection(ngx_connection_t *c)
if (c->read->timer_set) { if (c->read->timer_set) {
ngx_del_timer(c->read); ngx_del_timer(c->read);
c->read->timer_set = 0;
} }
if (c->write->timer_set) { if (c->write->timer_set) {
ngx_del_timer(c->write); ngx_del_timer(c->write);
c->write->timer_set = 0;
} }
if (ngx_del_conn) { 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; 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; r->connection->log->handler = ngx_http_log_error;
ngx_http_finalize_request(r, error);
} }

View File

@ -157,6 +157,8 @@ struct ngx_http_request_s {
ngx_str_t args; ngx_str_t args;
ngx_str_t exten; ngx_str_t exten;
ngx_str_t unparsed_uri; ngx_str_t unparsed_uri;
ngx_str_t path;
int path_allocated;
ngx_http_request_t *main; ngx_http_request_t *main;
@ -172,9 +174,6 @@ struct ngx_http_request_s {
char *discarded_buffer; char *discarded_buffer;
ngx_str_t path;
int path_err;
/* URI is not started with '/' - "GET http://" */ /* URI is not started with '/' - "GET http://" */
unsigned unusual_uri:1; unsigned unusual_uri:1;
/* URI with "/.", "%" and on Win32 with "//" */ /* URI with "/.", "%" and on Win32 with "//" */

View 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[] = static char error_302_page[] =
"<html>" CRLF "<html>" CRLF
"<head><title>302 Found</title></head>" CRLF "<head><title>302 Found</title></head>" CRLF
@ -111,8 +119,8 @@ static char error_504_page[] =
static ngx_str_t error_pages[] = { static ngx_str_t error_pages[] = {
ngx_null_string, /* 300 */ /* ngx_null_string, */ /* 300 */
ngx_null_string, /* 301 */ ngx_string(error_301_page),
ngx_string(error_302_page), ngx_string(error_302_page),
ngx_null_string, /* 303 */ 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->pos = error_tail;
h->last = error_tail + sizeof(error_tail) - 1; 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) { if (ngx_http_output_filter(r, h) == NGX_ERROR) {
return NGX_ERROR; return NGX_ERROR;
} }

View File

@ -139,7 +139,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_OK; return NGX_OK;
} }
if (!r->connection->write->ready || r->connection->write->delayed) { if (r->connection->write->delayed) {
return NGX_AGAIN; return NGX_AGAIN;
} }
@ -161,10 +161,9 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
if (chain == NULL) { if (chain == NULL) {
return NGX_OK; return NGX_OK;
} else {
return NGX_AGAIN;
} }
return NGX_AGAIN;
} }

View File

@ -109,6 +109,7 @@ ngx_log_debug(ev->log, "aio: aiocb: %08x" _ &ev->aiocb);
return NGX_ERROR; return NGX_ERROR;
} }
ev->active = 0;
ngx_log_debug(ev->log, "aio_write: %d" _ rc); ngx_log_debug(ev->log, "aio_write: %d" _ rc);
return rc; return rc;

View File

@ -1,6 +1,7 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_aio.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; ce = in;
while (ce) { while (ce) {
/* we can post the single aio operation only */
if (c->write->active) {
return ce;
}
buf = prev = ce->hunk->pos; buf = prev = ce->hunk->pos;
size = 0; size = 0;
/* coalesce the neighbouring chain entries */ /* coalesce the neighbouring chain entries */
while (ce && prev == ce->hunk->pos) { while (ce && prev == ce->hunk->pos) {
size += ce->hunk->last - ce->hunk->pos; size += ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last; prev = ce->hunk->last;
@ -33,16 +42,13 @@ 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); ngx_log_debug(c->log, "aio_write rc: %d" _ rc);
#endif #endif
if (rc == NGX_ERROR) {
return NGX_CHAIN_ERROR;
}
if (rc > 0) { if (rc > 0) {
sent += rc; sent += rc;
c->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) #if (NGX_DEBUG_WRITE_CHAIN)
@ -62,6 +68,7 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in)
break; break;
} }
}
return ce; return ce;
} }

View File

@ -19,8 +19,13 @@ ngx_os_io_t ngx_os_io = {
ngx_unix_recv, ngx_unix_recv,
ngx_readv_chain, ngx_readv_chain,
NULL, NULL,
#if (HAVE_FREEBSD_SENDFILE)
ngx_freebsd_sendfile_chain, ngx_freebsd_sendfile_chain,
NGX_HAVE_SENDFILE|NGX_HAVE_ZEROCOPY NGX_HAVE_SENDFILE|NGX_HAVE_ZEROCOPY
#else
ngx_writev_chain,
NULL
#endif
}; };

View 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_hunk_t *file;
ngx_chain_t *ce, *tail; ngx_chain_t *ce, *tail;
if (!c->write->ready) {
return in;
}
do { do {
ce = in; ce = in;
file = NULL; file = NULL;

View File

@ -43,8 +43,11 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
if (n >= 0) { if (n >= 0) {
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
rev->available -= n; rev->available -= n;
if (rev->available == 0) { if (rev->available <= 0) {
rev->ready = 0; rev->ready = 0;
if (rev->available < 0) {
rev->available = 0;
}
} }
return n; return n;

View File

@ -1,6 +1,7 @@
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_event.h>
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in) 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_array_t iovecs;
ngx_chain_t *ce; ngx_chain_t *ce;
if (!c->write->ready) {
return in;
}
ngx_init_array(iovecs, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); ngx_init_array(iovecs, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
prev = NULL; prev = NULL;

View File

@ -36,4 +36,8 @@
#endif #endif
/* STUB */
#define HAVE_LITTLE_ENDIAN 1
#endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */ #endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */

View File

@ -17,12 +17,12 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
rev = c->read; rev = c->read;
bytes = 0; 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; rev->ready = 0;
/* the overlapped WSARecv() completed */ /* the overlapped WSARecv() completed */
if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
if (rev->ovlp.error) { if (rev->ovlp.error) {
ngx_log_error(NGX_LOG_ERR, c->log, rev->ovlp.error, ngx_log_error(NGX_LOG_ERR, c->log, rev->ovlp.error,
"WSARecv() failed"); "WSARecv() failed");
@ -44,7 +44,7 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
return bytes; return bytes;
} }
if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { if (ngx_event_flags & NGX_USE_AIO_EVENT) {
ovlp = (LPWSAOVERLAPPED) &c->read->ovlp; ovlp = (LPWSAOVERLAPPED) &c->read->ovlp;
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); 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 * If a socket was bound with I/O completion port

View File

@ -65,8 +65,8 @@ non-block
wev = c->write; wev = c->write;
if (((ngx_event_flags & NGX_HAVE_AIO_EVENT) && !wev->ready) if (((ngx_event_flags & NGX_USE_AIO_EVENT) && !wev->ready)
|| ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0)) || ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0))
{ {
/* /*
* WSABUFs must be 4-byte aligned otherwise * 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; ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
@ -120,7 +120,7 @@ non-block
} else { } 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 * If a socket was bound with I/O completion port then
@ -133,7 +133,7 @@ non-block
} }
} else { } else {
if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
wev->ready = 0; wev->ready = 0;
/* the overlapped WSASend() completed */ /* the overlapped WSASend() completed */