# HG changeset patch # User Igor Sysoev # Date 1039933509 0 # Node ID 53cb81681040be0db09f888aa3b731a7bfebaae5 # Parent a8b156554dfe8e00d4600c9d84447ddfc7943494 nginx-0.0.1-2002-12-15-09:25:09 import diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -32,6 +32,8 @@ ngx_log_t ngx_log; ngx_pool_t *ngx_pool; +int ngx_connection_counter; + ngx_array_t *ngx_listening_sockets; @@ -43,7 +45,9 @@ int main(int argc, char *const *argv) ngx_pool = ngx_create_pool(16 * 1024, &ngx_log); /* */ +#if !(WIN32) ngx_set_signals(&ngx_log); +#endif ngx_init_sockets(&ngx_log); @@ -73,6 +77,7 @@ int main(int argc, char *const *argv) return 0; } +#if !(WIN32) static void ngx_set_signals(ngx_log_t *log) { struct sigaction sa; @@ -86,6 +91,7 @@ static void ngx_set_signals(ngx_log_t *l exit(1); } } +#endif static void ngx_open_listening_sockets(ngx_log_t *log) { diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -5,4 +5,7 @@ #define NGINX_VER "nginx/0.0.1" +extern int ngx_connection_counter; + + #endif /* _NGINX_H_INCLUDED_ */ diff --git a/src/core/ngx_alloc.c b/src/core/ngx_alloc.c --- a/src/core/ngx_alloc.c +++ b/src/core/ngx_alloc.c @@ -3,6 +3,7 @@ #include #include +#include #include @@ -15,7 +16,7 @@ void *ngx_alloc(size_t size, ngx_log_t * ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "malloc() %d bytes failed", size); - ngx_log_debug(log, "malloc: %x:%d" _ p _ size); + ngx_log_debug(log, "malloc: %08x:%d" _ p _ size); return p; } @@ -52,12 +53,12 @@ void ngx_destroy_pool(ngx_pool_t *pool) ngx_pool_large_t *l; for (l = pool->large; l; l = l->next) { - ngx_log_debug(pool->log, "free: %x" _ l->alloc); + ngx_log_debug(pool->log, "free: %08x" _ l->alloc); free(l->alloc); } for (p = pool, n = pool->next; /* void */; p = n, n = n->next) { - ngx_log_debug(pool->log, "free: %x" _ p); + ngx_log_debug(pool->log, "free: %08x" _ p); free(p); if (n == NULL) @@ -74,9 +75,10 @@ void *ngx_palloc(ngx_pool_t *pool, size_ if (size <= NGX_MAX_ALLOC_FROM_POOL) { for (p = pool, n = pool->next; /* void */; p = n, n = n->next) { - if ((size_t) (p->end - p->last) >= size) { - m = p->last; - p->last += size; + if ((size_t) (p->end - ngx_align(p->last)) >= size) { + m = ngx_align(p->last); + p->last = ngx_align(p->last); + p->last += size ; return m; } diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -12,6 +12,13 @@ #define FD_SETSIZE 1024 +/* auto_conf */ +#define NGX_ALIGN (4 - 1) +#define NGX_ALIGN_TYPE unsigned + +#define ngx_align(p) (char *) (((NGX_ALIGN_TYPE) p + NGX_ALIGN) & ~NGX_ALIGN) + + #ifdef _WIN32 #define WIN32 1 @@ -25,9 +32,6 @@ #define ngx_inline __inline -#define ngx_memzero ZeroMemory - -#define ngx_close_socket closesocket #ifndef HAVE_INHERITED_NONBLOCK #define HAVE_INHERITED_NONBLOCK 1 @@ -66,9 +70,6 @@ #define ngx_inline inline -#define ngx_memzero bzero - -#define ngx_close_socket close #endif /* POSIX */ diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -44,6 +44,8 @@ struct ngx_connection_s { ngx_hunk_t *buffer; unsigned int post_accept_timeout; + int number; + unsigned unexpected_eof:1; }; diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -4,12 +4,18 @@ #include #include +#include typedef struct ngx_file_s ngx_file_t; struct ngx_file_s { - ngx_fd_t fd; - ngx_log_t *log; + ngx_fd_t fd; + ngx_str_t name; + ngx_file_info_t info; + + ngx_log_t *log; + + unsigned info_valid:1; }; diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c new file mode 100644 --- /dev/null +++ b/src/core/ngx_inet.c @@ -0,0 +1,18 @@ + +#include +#include +#include + + +size_t ngx_inet_ntop(int family, char *addr, char *text, size_t len) +{ + if (family != AF_INET) + return 0; + + return ngx_snprintf(text, len > INET_ADDRSTRLEN ? INET_ADDRSTRLEN : len, + "%u.%u.%u.%u", + (unsigned char) addr[0], + (unsigned char) addr[1], + (unsigned char) addr[2], + (unsigned char) addr[3]); +} diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_inet.h @@ -0,0 +1,8 @@ +#ifndef _NGX_INET_H_INCLUDED_ +#define _NGX_INET_H_INCLUDED_ + + +size_t ngx_inet_ntop(int family, char *addr, char *text, size_t len); + + +#endif /* _NGX_INET_H_INCLUDED_ */ diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -6,17 +6,24 @@ typedef struct { - int len; - char *data; + size_t len; + char *data; } ngx_str_t; #if (WIN32) + +#define ngx_memzero ZeroMemory + +#define strcasecmp stricmp + #define ngx_snprintf _snprintf #define ngx_vsnprintf _vsnprintf #else +#define ngx_memzero bzero + #define ngx_snprintf snprintf #define ngx_vsnprintf vsnprintf diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -16,12 +16,14 @@ #endif - +/* should be per-thread */ static int kq; static struct kevent *change_list, *event_list; static int nchanges, nevents; static ngx_event_t timer_queue; +/* */ + int ngx_kqueue_init(int max_connections, ngx_log_t *log) { @@ -53,6 +55,7 @@ int ngx_kqueue_init(int max_connections, return NGX_OK; } + int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) { ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; @@ -60,22 +63,33 @@ int ngx_kqueue_add_event(ngx_event_t *ev return ngx_kqueue_set_event(ev, event, EV_ADD | flags); } -int ngx_kqueue_del_event(ngx_event_t *ev, int event) + +int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) { ngx_event_t *e; - if (ev->index <= nchanges && change_list[ev->index].udata == ev) { - change_list[ev->index] = change_list[nchanges]; - e = (ngx_event_t *) change_list[ev->index].udata; - e->index = ev->index; - nchanges--; + if (ev->index < nchanges && change_list[ev->index].udata == ev) { + + ngx_connection_t *cn = (ngx_connection_t *) ev->data; + ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ + cn->fd _ event); + + if (ev->index < --nchanges) { + e = (ngx_event_t *) change_list[nchanges].udata; + change_list[ev->index] = change_list[nchanges]; + e->index = ev->index; + } return NGX_OK; } + if (flags & NGX_CLOSE_EVENT) + return NGX_OK; + return ngx_kqueue_set_event(ev, event, EV_DELETE); } + int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) { struct timespec ts = { 0, 0 }; @@ -110,13 +124,18 @@ int ngx_kqueue_set_event(ngx_event_t *ev return NGX_OK; } + int ngx_kqueue_process_events(ngx_log_t *log) { int events, i; - u_int timer = 0, delta = 0; + u_int timer, delta; ngx_event_t *ev; struct timeval tv; - struct timespec ts, *tp = NULL; + struct timespec ts, *tp; + + timer = 0; + delta = 0; + tp = NULL; if (timer_queue.timer_next != &timer_queue) { timer = timer_queue.timer_next->timer_delta; @@ -212,6 +231,7 @@ int ngx_kqueue_process_events(ngx_log_t return NGX_OK; } + void ngx_kqueue_add_timer(ngx_event_t *ev, ngx_msec_t timer) { ngx_event_t *e; diff --git a/src/event/modules/ngx_kqueue_module.h b/src/event/modules/ngx_kqueue_module.h --- a/src/event/modules/ngx_kqueue_module.h +++ b/src/event/modules/ngx_kqueue_module.h @@ -8,7 +8,7 @@ int ngx_kqueue_init(int max_connections, ngx_log_t *log); int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags); -int ngx_kqueue_del_event(ngx_event_t *ev, int event); +int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags); int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags); void ngx_kqueue_add_timer(ngx_event_t *ev, ngx_msec_t timer); int ngx_kqueue_process_events(ngx_log_t *log); diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -8,24 +8,26 @@ #include #include -static fd_set master_read_fd_set; -static fd_set master_write_fd_set; -static fd_set work_read_fd_set; -static fd_set work_write_fd_set; + +/* should be per-thread */ +static fd_set master_read_fd_set; +static fd_set master_write_fd_set; +static fd_set work_read_fd_set; +static fd_set work_write_fd_set; #if (WIN32) -static int max_read; -static int max_write; +static int max_read; +static int max_write; #else -static int max_fd; +static int max_fd; #endif -static int nevents; +static int nevents; static ngx_event_t **event_index; static ngx_event_t **ready_index; static ngx_event_t timer_queue; - +/* */ static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event, ngx_log_t *log); @@ -121,12 +123,15 @@ int ngx_select_add_event(ngx_event_t *ev return NGX_OK; } -int ngx_select_del_event(ngx_event_t *ev, int event) +int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags) { ngx_connection_t *c; c = (ngx_connection_t *) ev->data; - ngx_log_debug(c->log, "del event: %d" _ c->fd); + if (ev->index == NGX_INVALID_INDEX) + return NGX_OK; + + ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event); #if (WIN32) if (event == NGX_READ_EVENT) { @@ -148,13 +153,13 @@ int ngx_select_del_event(ngx_event_t *ev max_fd = -1; #endif - nevents--; - - if (ev->index < nevents) { + if (ev->index < --nevents) { event_index[ev->index] = event_index[nevents]; event_index[ev->index]->index = ev->index; } + ev->index = NGX_INVALID_INDEX; + return NGX_OK; } @@ -162,7 +167,7 @@ int ngx_select_process_events(ngx_log_t { int i, ready, found, nready; u_int timer, delta; - ngx_event_t *ev, *nx; + ngx_event_t *ev; ngx_connection_t *c; struct timeval tv, *tp; @@ -195,6 +200,15 @@ int ngx_select_process_events(ngx_log_t } #endif +#if 1 + /* DEBUG */ + for (i = 0; i < nevents; i++) { + ev = event_index[i]; + c = (ngx_connection_t *) ev->data; + ngx_log_debug(log, "select: %d" _ c->fd); + } +#endif + ngx_log_debug(log, "select timer: %d" _ timer); #if (WIN32) @@ -222,17 +236,17 @@ int ngx_select_process_events(ngx_log_t if (timer) { if (delta >= timer) { - for (ev = timer_queue.timer_next; - ev != &timer_queue && delta >= ev->timer_delta; - /* void */) - { + for ( ;; ) { + ev = timer_queue.timer_next; + + if (ev == &timer_queue || delta < ev->timer_delta) + break; + delta -= ev->timer_delta; - nx = ev->timer_next; ngx_del_timer(ev); ev->timedout = 1; - if (ev->event_handler(ev) == -1) + if (ev->event_handler(ev) == NGX_ERROR) ev->close_handler(ev); - ev = nx; } } else { @@ -249,15 +263,13 @@ int ngx_select_process_events(ngx_log_t if (ev->write) { if (FD_ISSET(c->fd, &work_write_fd_set)) { - ngx_log_debug(log, "select write %d" _ - c->fd); + ngx_log_debug(log, "select write %d" _ c->fd); found = 1; } } else { if (FD_ISSET(c->fd, &work_read_fd_set)) { - ngx_log_debug(log, "select read %d" _ - c->fd); + ngx_log_debug(log, "select read %d" _ c->fd); found = 1; } } @@ -274,13 +286,14 @@ int ngx_select_process_events(ngx_log_t if (ev->oneshot) { ngx_del_timer(ev); + if (ev->write) - ngx_select_del_event(ev, NGX_WRITE_EVENT); + ngx_select_del_event(ev, NGX_WRITE_EVENT, 0); else - ngx_select_del_event(ev, NGX_READ_EVENT); + ngx_select_del_event(ev, NGX_READ_EVENT, 0); } - if (ev->event_handler(ev) == -1) + if (ev->event_handler(ev) == NGX_ERROR) ev->close_handler(ev); ready--; diff --git a/src/event/modules/ngx_select_module.h b/src/event/modules/ngx_select_module.h --- a/src/event/modules/ngx_select_module.h +++ b/src/event/modules/ngx_select_module.h @@ -8,7 +8,7 @@ int ngx_select_init(int max_connections, ngx_log_t *log); int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags); -int ngx_select_del_event(ngx_event_t *ev, int event); +int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags); int ngx_select_set_event(ngx_event_t *ev, int filter, u_int flags); void ngx_select_add_timer(ngx_event_t *ev, ngx_msec_t timer); int ngx_select_process_events(ngx_log_t *log); diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -21,7 +21,7 @@ ngx_event_t *ngx_read_events, *n #if !(USE_KQUEUE) -#if 0 +#if 1 ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; #else ngx_event_type_e ngx_event_type = NGX_KQUEUE_EVENT; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -10,6 +10,8 @@ #include #include +#define NGX_INVALID_INDEX 0x80000000 + typedef struct ngx_event_s ngx_event_t; struct ngx_event_s { @@ -79,7 +81,7 @@ typedef enum { typedef struct { int (*add)(ngx_event_t *ev, int event, u_int flags); - int (*del)(ngx_event_t *ev, int event); + int (*del)(ngx_event_t *ev, int event, u_int flags); void (*timer)(ngx_event_t *ev, ngx_msec_t timer); int (*process)(ngx_log_t *log); int (*read)(ngx_event_t *ev, char *buf, size_t size); @@ -96,8 +98,12 @@ NGX_ONESHOT_EVENT select, poll, NGX_CLEAR_EVENT kqueue NGX_AIO_EVENT overlapped, aio_read, aioread no need to add or delete events + +NGX_CLOSE_EVENT kqueue: kqueue deletes events for file that closed */ +#define NGX_CLOSE_EVENT 1 + #if (HAVE_KQUEUE) #define NGX_READ_EVENT EVFILT_READ @@ -124,15 +130,12 @@ NGX_AIO_EVENT overlapped, a #endif - #if (USE_KQUEUE) #define ngx_init_events ngx_kqueue_init #define ngx_process_events ngx_kqueue_process_events -#define ngx_kqueue_add_event(ev, event) \ - ngx_kqueue_set_event(ev, event, EV_ADD | flags) -#define ngx_kqueue_del_event(ev, event) \ - ngx_kqueue_set_event(ev, event, EV_DELETE) +#define ngx_add_event ngx_kqueue_add_event +#define ngx_del_event ngx_kqueue_add_event #define ngx_add_timer ngx_kqueue_add_timer #define ngx_event_recv ngx_event_recv_core diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -1,3 +1,5 @@ + +#include #include #include @@ -11,11 +13,12 @@ int ngx_event_accept(ngx_event_t *ev) { - ngx_err_t err; - ngx_socket_t s; - struct sockaddr_in addr; - int addrlen = sizeof(struct sockaddr_in); - ngx_connection_t *cn = (ngx_connection_t *) ev->data; + ngx_err_t err; + ngx_socket_t s; + ngx_event_t *rev, *wev; + ngx_connection_t *c, *ac; + + ac = (ngx_connection_t *) ev->data; ngx_log_debug(ev->log, "ngx_event_accept: accept ready: %d" _ ev->available); @@ -23,69 +26,73 @@ int ngx_event_accept(ngx_event_t *ev) ev->ready = 0; do { - if ((s = accept(cn->fd, cn->sockaddr, &cn->socklen)) == -1) { + if ((s = accept(ac->fd, ac->sockaddr, &ac->socklen)) == -1) { err = ngx_socket_errno; if (err == NGX_EAGAIN) { ngx_log_error(NGX_LOG_INFO, ev->log, err, "ngx_event_accept: EAGAIN while accept %s", - cn->addr_text); + ac->addr_text); return NGX_OK; } ngx_log_error(NGX_LOG_ERR, ev->log, err, - "ngx_event_accept: accept %s failed", cn->addr_text); + "ngx_event_accept: accept %s failed", ac->addr_text); /* if we return NGX_ERROR listen socket would be closed */ return NGX_OK; } - ngx_log_debug(ev->log, "ngx_event_accept: accept: %d" _ s); - #if !(HAVE_INHERITED_NONBLOCK) if (ngx_nonblocking(s) == -1) ngx_log_error(NGX_LOG_ERR, log, ngx_socket_errno, ngx_nonblocking_n "failed"); #endif - ngx_memzero(&ngx_read_events[s], sizeof(ngx_event_t)); - ngx_memzero(&ngx_write_events[s], sizeof(ngx_event_t)); - ngx_memzero(&ngx_connections[s], sizeof(ngx_connection_t)); + rev = &ngx_read_events[s]; + wev = &ngx_write_events[s]; + c = &ngx_connections[s]; + + ngx_memzero(rev, sizeof(ngx_event_t)); + ngx_memzero(wev, sizeof(ngx_event_t)); + ngx_memzero(c, sizeof(ngx_connection_t)); - ngx_connections[s].sockaddr = cn->sockaddr; - ngx_connections[s].family = cn->family; - ngx_connections[s].socklen = cn->socklen; - ngx_connections[s].addr = cn->addr; - ngx_connections[s].addr_text.len = cn->addr_text.len; - ngx_connections[s].post_accept_timeout = cn->post_accept_timeout; + c->sockaddr = ac->sockaddr; + c->family = ac->family; + c->socklen = ac->socklen; + c->addr = ac->addr; + c->addr_text.len = ac->addr_text.len; + c->post_accept_timeout = ac->post_accept_timeout; - ngx_read_events[s].data = ngx_write_events[s].data - = &ngx_connections[s]; - ngx_connections[s].read = &ngx_read_events[s]; - ngx_connections[s].write = &ngx_write_events[s]; + rev->index = wev->index = NGX_INVALID_INDEX; - ngx_connections[s].fd = s; - ngx_connections[s].unexpected_eof = 1; - ngx_write_events[s].write = 1; - ngx_write_events[s].ready = 1; + rev->data = wev->data = c; + c->read = rev; + c->write = wev; - ngx_write_events[s].timer = ngx_read_events[s].timer = 10000; + c->fd = s; + c->unexpected_eof = 1; + wev->write = 1; + wev->ready = 1; - ngx_write_events[s].timer_handler = - ngx_read_events[s].timer_handler = ngx_event_close_connection; + wev->timer = rev->timer = 10000; + wev->timer_handler = rev->timer_handler = ngx_event_close_connection; + wev->close_handler = rev->close_handler = ngx_event_close_connection; - ngx_write_events[s].close_handler = - ngx_read_events[s].close_handler = ngx_event_close_connection; + c->server = ac->server; + c->servers = ac->servers; + c->log = rev->log = wev->log = ev->log; - ngx_connections[s].server = cn->server; - ngx_connections[s].servers = cn->servers; - ngx_connections[s].log = - ngx_read_events[s].log = ngx_write_events[s].log = ev->log; + /* STUB: x86: SP: xadd, MT: lock xadd, MP: lock xadd, shared */ + c->number = ngx_connection_counter++; + + ngx_log_debug(ev->log, "ngx_event_accept: accept: %d, %d" _ + s _ c->number); #if (HAVE_DEFERRED_ACCEPT) if (ev->accept_filter) - ngx_read_events[s].ready = 1; + rev->ready = 1; #endif - cn->handler(&ngx_connections[s]); + ac->handler(c); #if (HAVE_KQUEUE) #if !(USE_KQUEUE) diff --git a/src/event/ngx_event_close.c b/src/event/ngx_event_close.c --- a/src/event/ngx_event_close.c +++ b/src/event/ngx_event_close.c @@ -11,21 +11,20 @@ int ngx_event_close_connection(ngx_event int rc; ngx_connection_t *c = (ngx_connection_t *) ev->data; + ngx_log_debug(c->log, "CLOSE: %d" _ c->fd); + ngx_assert((c->fd != -1), return NGX_ERROR, c->log, "ngx_event_close: already closed"); ngx_destroy_pool(c->pool); + ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); + ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); + if ((rc = ngx_close_socket(c->fd)) == -1) ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno, "ngx_event_close: close failed"); - if (c->read->next) - ngx_del_event(c->read, NGX_READ_EVENT); - - if (c->write->next) - ngx_del_event(c->write, NGX_WRITE_EVENT); - c->fd = -1; return rc; diff --git a/src/event/ngx_event_write.c b/src/event/ngx_event_write.c --- a/src/event/ngx_event_write.c +++ b/src/event/ngx_event_write.c @@ -98,8 +98,7 @@ ngx_chain_t *ngx_event_write(ngx_connect (ngx_iovec_t *) trailer->elts, trailer->nelts, &sent, c->log); } else { - rc = ngx_sendv(c, (ngx_iovec_t *) header->elts, - header->nelts); + rc = ngx_sendv(c, (ngx_iovec_t *) header->elts, header->nelts); sent = rc > 0 ? rc: 0; diff --git a/src/http/modules/ngx_http_event_proxy_handler.c b/src/http/modules/ngx_http_event_proxy_handler.c --- a/src/http/modules/ngx_http_event_proxy_handler.c +++ b/src/http/modules/ngx_http_event_proxy_handler.c @@ -309,7 +309,9 @@ static int ngx_http_proxy_read_response_ if (n == 0) { ngx_log_debug(c->log, "CLOSE proxy"); - ngx_del_event(ev, NGX_READ_EVENT); +#if 0 + ngx_del_event(ev, NGX_READ_EVENT, NGX_CLOSE_EVENT); +#endif ngx_event_close_connection(ev); p->hunk_n = 0; @@ -439,7 +441,9 @@ static int ngx_http_proxy_read_response_ if (n == 0) { ngx_log_debug(c->log, "CLOSE proxy"); - ngx_del_event(ev, NGX_READ_EVENT); +#if 0 + ngx_del_event(ev, NGX_READ_EVENT, NGX_CLOSE_EVENT); +#endif ngx_event_close_connection(ev); p->hunk_n = 0; diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -16,7 +16,16 @@ static void *ngx_http_index_merge_conf(n static char *ngx_http_index_set_index(ngx_pool_t *p, void *conf, ngx_str_t *value); -static ngx_command_t ngx_http_index_commands[]; + +static ngx_command_t ngx_http_index_commands[] = { + + {"index", ngx_http_index_set_index, NULL, + NGX_HTTP_LOC_CONF, NGX_CONF_ITERATE, + "set index files"}, + + {NULL} + +}; ngx_http_module_t ngx_http_index_module = { @@ -33,17 +42,6 @@ ngx_http_module_t ngx_http_index_module }; -static ngx_command_t ngx_http_index_commands[] = { - - {"index", ngx_http_index_set_index, NULL, - NGX_HTTP_LOC_CONF, NGX_CONF_ITERATE, - "set index files"}, - - {NULL} - -}; - - int ngx_http_index_handler(ngx_http_request_t *r) { int i; @@ -71,10 +69,14 @@ int ngx_http_index_handler(ngx_http_requ ngx_memcpy(file, index[i].data, index[i].len + 1); fd = ngx_open_file(name, NGX_FILE_RDONLY); - if (fd == -1) { + if (fd == NGX_INVALID_FILE) { err = ngx_errno; if (err == NGX_ENOENT) continue; +#if (WIN32) + if (err == ERROR_PATH_NOT_FOUND) + continue; +#endif ngx_log_error(NGX_LOG_ERR, r->connection->log, err, ngx_open_file_n " %s failed", name); @@ -82,9 +84,9 @@ int ngx_http_index_handler(ngx_http_requ return NGX_HTTP_INTERNAL_SERVER_ERROR; } - r->filename.len = r->server->doc_root_len + r->uri.len + index[i].len; - r->filename.data = name; - r->fd = fd; + r->file.name.len = r->server->doc_root_len + r->uri.len + index[i].len; + r->file.name.data = name; + r->file.fd = fd; loc.len = r->uri.len + index[i].len; return ngx_http_internal_redirect(r, loc); diff --git a/src/http/modules/ngx_http_log_handler.c b/src/http/modules/ngx_http_log_handler.c new file mode 100644 --- /dev/null +++ b/src/http/modules/ngx_http_log_handler.c @@ -0,0 +1,79 @@ + +#include +#include +#include +#include +#include +#include + + +ngx_http_module_t ngx_http_log_module; + + +static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + +int ngx_http_log_handler(ngx_http_request_t *r) +{ + size_t len; + char *line, *p; + ngx_tm_t tm; + +#if (WIN32) + len = 2 + 22 + 3 + 20 + 5 + 20 + 2; +#else + len = 2 + 22 + 3 + 20 + 5 + 20 + 1; +#endif + + len += r->connection->addr_text.len; + len += r->request_line.len; + + + ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR); + p = line; + + ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); + p += r->connection->addr_text.len; + + *p++ = ' '; + + ngx_localtime(&tm); + + *p++ = '['; + p += ngx_snprintf(p, 21, "%02d/%s/%d:%02d:%02d:%02d", + tm.ngx_tm_mday, months[tm.ngx_tm_mon], + tm.ngx_tm_year + 1900, + tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); + + *p++ = ']'; + + *p++ = ' '; + + *p++ = '"'; + ngx_memcpy(p, r->request_line.data, r->request_line.len); + p += r->request_line.len; + *p++ = '"'; + + *p++ = ' '; + + p += ngx_snprintf(p, 4, "%d", r->headers_out.status); + + *p++ = ' '; + + p += ngx_snprintf(p, 21, QD_FMT, r->connection->sent); + + *p++ = ' '; + + p += ngx_snprintf(p, 21, "%u", r->connection->number); + +#if (WIN32) + *p++ = CR; *p++ = LF; +#else + *p++ = LF; +#endif + + write(1, line, len); + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -24,51 +24,84 @@ void ngx_http_static_init() int ngx_http_static_handler(ngx_http_request_t *r) { - int rc; + int rc; + ngx_err_t err; ngx_hunk_t *h; ngx_http_log_ctx_t *ctx; -/* +#if 0 ngx_http_event_static_handler_loc_conf_t *cf; cf = (ngx_http_event_static_handler_loc_conf_t *) ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module); -*/ +#endif ngx_http_discard_body(r); ctx = r->connection->log->data; ctx->action = "sending response"; - if (r->fd != -1) - r->fd = ngx_open_file(r->filename.data, NGX_FILE_RDONLY); + if (r->file.fd == NGX_INVALID_FILE) + r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY); - if (r->fd == -1) { + if (r->file.fd == NGX_INVALID_FILE) { + err = ngx_errno; ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, "ngx_http_static_handler: " - ngx_open_file_n " %s failed", r->filename.data); + ngx_open_file_n " %s failed", r->file.name.data); - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (err == NGX_ENOENT) + return NGX_HTTP_NOT_FOUND; +#if (WIN32) + else if (err == ERROR_PATH_NOT_FOUND) + return NGX_HTTP_NOT_FOUND; +#endif + else + return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (ngx_stat_fd(r->fd, &r->fileinfo) == -1) { + if (!r->file.info_valid) { + if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_stat_fd_n " %s failed", r->file.name.data); + + if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_close_file_n " %s failed", r->file.name.data); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + r->file.info_valid = 1; + } + +#if !(WIN32) /* it's probably Unix specific */ + + if (!ngx_is_file(r->file.info)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, "ngx_http_static_handler: " - ngx_stat_fd_n " %s failed", r->filename.data); + "%s is not regular file", r->file.name.data); - /* close fd */ - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_close_file_n " %s failed", r->file.name.data); + + return NGX_HTTP_NOT_FOUND; } +#endif + r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length = ngx_file_size(r->fileinfo); -/* - r->headers_out.last_modified = ngx_file_mtime(r->fileinfo); -*/ + r->headers_out.content_length = ngx_file_size(r->file.info); + r->headers_out.last_modified_time = ngx_file_mtime(r->file.info); ngx_test_null(r->headers_out.content_type, ngx_push_table(r->headers_out.headers), NGX_HTTP_INTERNAL_SERVER_ERROR); + r->headers_out.content_type->key.len = 12; r->headers_out.content_type->key.data = "Content-Type"; @@ -90,83 +123,29 @@ int ngx_http_static_handler(ngx_http_req r->headers_out.content_type->value.len = 25; r->headers_out.content_type->value.data = "text/html; charset=koi8-r"; } + /**/ - /* STUB */ - rc = ngx_http_header_filter(r); -/* - rc = ngx_send_http_header(r); -*/ + /* we need to allocate them before header would be sent */ + ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + rc = ngx_http_send_header(r); if (r->header_only) return rc; - /* TODO: NGX_HTTP_INTERNAL_SERVER_ERROR is too late */ - - /* STUB */ - ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), - NGX_HTTP_INTERNAL_SERVER_ERROR); - h->type = NGX_HUNK_FILE|NGX_HUNK_LAST; h->pos.file = 0; - h->last.file = ngx_file_size(r->fileinfo); + h->last.file = ngx_file_size(r->file.info); - /* STUB */ - ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)), - NGX_HTTP_INTERNAL_SERVER_ERROR); - h->file->fd = r->fd; + h->file->fd = r->file.fd; h->file->log = r->connection->log; rc = ngx_http_output_filter(r, h); + ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc); + return rc; } - -#if 0 - -static void *ngx_create_index_config() -{ - ngx_http_index_handler_loc_conf_t *cf; - - ngx_check_null(cf, ngx_alloc(p, sizeof(ngx_http_index_handler_loc_conf)), - NULL); - - cf->indices = ngx_create_array(p, sizeof(ngx_http_index_t), 5); - if (cf->indices == NULL) - return NULL; - - cf->max_index_len = 0; - - return cf; -} - -static void *ngx_merge_index_config() -{ - if (p->indices->nelts > 0) { - - copy and check dups - - if (c->max_index_len < c->max_index_len) - c->max_index_len < c->max_index_len); - } -} - -static void *ngx_set_index() -{ - if (*conf == NULL) { - cf = ngx_create_index_conf(); - if (cf == NULL) - return "can not create config"; - } - - while (args) { - index = ngx_push_array(cf->indices); - index->name = arg; - index->len = ngx_strlen(arg) + 1; - - if (cf->max_index_len < index->len) - cf->max_index_len = index->len; - } - - *conf = cf; -} - -#endif diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -32,11 +32,13 @@ #define NGX_HTTP_OK 200 #define NGX_HTTP_SPECIAL_RESPONSE 300 -#define NGX_HTTP_MOVED_PERMANENTLY 302 +#define NGX_HTTP_MOVED_PERMANENTLY 301 +#define NGX_HTTP_MOVED_TEMPORARILY 302 +#define NGX_HTTP_NOT_MODIFIED 304 #define NGX_HTTP_BAD_REQUEST 400 #define NGX_HTTP_NOT_FOUND 404 #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 -#define NGX_HTTP_INTERNAL_SERVER_ERROR 503 +#define NGX_HTTP_INTERNAL_SERVER_ERROR 500 #define NGX_HTTP_STATIC_HANDLER 0 @@ -59,21 +61,25 @@ typedef struct { time_t lingering_time; } ngx_http_server_t; + typedef struct { int len; char *data; int offset; } ngx_http_header_t; + typedef struct { ngx_table_elt_t *host; ngx_table_elt_t *connection; + ngx_table_elt_t *if_modified_since; ngx_table_elt_t *user_agent; ngx_table_elt_t *accept_encoding; ngx_table_t *headers; } ngx_http_headers_in_t; + typedef struct { int status; ngx_str_t status_line; @@ -93,12 +99,18 @@ typedef struct { time_t last_modified_time; } ngx_http_headers_out_t; + typedef struct ngx_http_request_s ngx_http_request_t; struct ngx_http_request_s { - ngx_str_t filename; + ngx_file_t file; +#if 0 + ngx_str_t filename; + ngx_file_info_t fileinfo; ngx_fd_t fd; + int filename_len; +#endif void **ctx; void **loc_conf; @@ -110,11 +122,8 @@ struct ngx_http_request_s { ngx_http_headers_in_t headers_in; ngx_http_headers_out_t headers_out; - int filename_len; int (*handler)(ngx_http_request_t *r); - ngx_file_info_t fileinfo; - int method; time_t lingering_time; @@ -146,7 +155,7 @@ struct ngx_http_request_s { unsigned header_only:1; unsigned unusual_uri:1; /* URI is not started with '/' - "GET http://" */ - unsigned complex_uri:1; /* URI with "./" or with "//" */ + unsigned complex_uri:1; /* URI with "/." or with "//" (WIN32) */ int state; char *uri_start; @@ -163,6 +172,7 @@ struct ngx_http_request_s { #endif }; + typedef struct { char *action; char *client; @@ -181,10 +191,20 @@ typedef struct { int (*translate_handler)(ngx_http_request_t *r); - int (*init_output_body_filter)(int (**next_filter) + int (*output_header_filter) (ngx_http_request_t *r); + int (*next_output_header_filter) (ngx_http_request_t *r); + + int (*output_body_filter)(); + int (*next_output_body_filter) + (ngx_http_request_t *r, ngx_chain_t *ch); + +#if 0 + int (*next_output_body_filter)(int (**next_filter) (ngx_http_request_t *r, ngx_chain_t *ch)); +#endif } ngx_http_module_t; + #define NGX_HTTP_MODULE 0 #define ngx_get_module_loc_conf(r, module) r->loc_conf[module.index] @@ -204,10 +224,14 @@ typedef struct { /* STUB */ int ngx_http_init(ngx_pool_t *pool, ngx_log_t *log); +/**/ int ngx_http_init_connection(ngx_connection_t *c); +int ngx_http_discard_body(ngx_http_request_t *r); + + extern int ngx_max_module; extern ngx_http_module_t *ngx_http_modules[]; diff --git a/src/http/ngx_http_config.c b/src/http/ngx_http_config.c --- a/src/http/ngx_http_config.c +++ b/src/http/ngx_http_config.c @@ -9,6 +9,8 @@ int ngx_max_module; +int (*ngx_http_top_header_filter) (ngx_http_request_t *r); + /* STUB: gobal srv and loc conf */ void **ngx_srv_conf; void **ngx_loc_conf; @@ -53,13 +55,27 @@ int ngx_http_init_modules(ngx_pool_t *po int ngx_http_init_filters(ngx_pool_t *pool, ngx_http_module_t **modules) { int i; - int (*filter)(ngx_http_request_t *r, ngx_chain_t *ch); + int (*ohf)(ngx_http_request_t *r); + int (*obf)(ngx_http_request_t *r, ngx_chain_t *ch); - filter = ngx_http_write_filter; + ohf = NULL; for (i = 0; modules[i]; i++) { - if (modules[i]->init_output_body_filter) - modules[i]->init_output_body_filter(&filter); + if (modules[i]->output_header_filter) { + modules[i]->next_output_header_filter = ohf; + ohf = modules[i]->output_header_filter; + } + } + + ngx_http_top_header_filter = ohf; + + obf = NULL; + + for (i = 0; modules[i]; i++) { + if (modules[i]->output_body_filter) { + modules[i]->next_output_body_filter = obf; + obf = modules[i]->output_body_filter; + } } } diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h --- a/src/http/ngx_http_config.h +++ b/src/http/ngx_http_config.h @@ -10,6 +10,8 @@ int ngx_http_config_modules(ngx_pool_t *pool, ngx_http_module_t **modules); +extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r); + extern void **ngx_srv_conf; extern void **ngx_loc_conf; diff --git a/src/http/ngx_http_core.c b/src/http/ngx_http_core.c --- a/src/http/ngx_http_core.c +++ b/src/http/ngx_http_core.c @@ -18,7 +18,16 @@ static void *ngx_http_core_create_loc_co static int ngx_http_core_translate_handler(ngx_http_request_t *r); -static ngx_command_t ngx_http_core_commands[]; +static ngx_command_t ngx_http_core_commands[] = { + + {"send_timeout", ngx_conf_set_time_slot, + offsetof(ngx_http_core_loc_conf_t, send_timeout), + NGX_HTTP_LOC_CONF, NGX_CONF_TAKE1, + "set timeout for sending response"}, + + {NULL} + +}; ngx_http_module_t ngx_http_core_module = { @@ -35,18 +44,6 @@ ngx_http_module_t ngx_http_core_module }; -static ngx_command_t ngx_http_core_commands[] = { - - {"send_timeout", ngx_conf_set_time_slot, - offsetof(ngx_http_core_loc_conf_t, send_timeout), - NGX_HTTP_LOC_CONF, NGX_CONF_TAKE1, - "set timeout for sending response"}, - - {NULL} - -}; - - int ngx_http_handler(ngx_http_request_t *r) { int rc, i; @@ -95,22 +92,54 @@ static int ngx_http_core_translate_handl return NGX_OK; } - r->filename.len = r->server->doc_root_len + r->uri.len + 2; + r->file.name.len = r->server->doc_root_len + r->uri.len + 2; - ngx_test_null(r->filename.data, - ngx_palloc(r->pool, r->filename.len + 1), + ngx_test_null(r->file.name.data, + ngx_palloc(r->pool, r->file.name.len + 1), NGX_HTTP_INTERNAL_SERVER_ERROR); - loc = ngx_cpystrn(r->filename.data, r->server->doc_root, + loc = ngx_cpystrn(r->file.name.data, r->server->doc_root, r->server->doc_root_len); last = ngx_cpystrn(loc, r->uri.data, r->uri.len + 1); - ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->filename.data); + ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ + r->file.name.data); + +#if (WIN32) - if (ngx_file_type(r->filename.data, &r->fileinfo) == -1) { + /* There is no way to open file or directory in Win32 with + one syscall: CreateFile() returns ERROR_ACCESS_DENIED on directory, + so we need to check its type before opening */ + +#if 0 /* OLD: ngx_file_type() is to be removed */ + if (ngx_file_type(r->file.name.data, &r->file.info) == -1) { +#endif + + r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data); + if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { err = ngx_errno; ngx_log_error(NGX_LOG_ERR, r->connection->log, err, - ngx_file_type_n " %s failed", r->filename.data); + "ngx_http_core_translate_handler: " + ngx_file_type_n " %s failed", r->file.name.data); + + if (err == ERROR_FILE_NOT_FOUND) + return NGX_HTTP_NOT_FOUND; + else if (err == ERROR_PATH_NOT_FOUND) + return NGX_HTTP_NOT_FOUND; + else + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + +#else + + if (r->file.fd == NGX_INVALID_FILE) + r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY); + + if (r->file.fd == NGX_INVALID_FILE) { + err = ngx_errno; + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_open_file_n " %s failed", r->file.name.data); if (err == NGX_ENOENT) return NGX_HTTP_NOT_FOUND; @@ -118,8 +147,33 @@ static int ngx_http_core_translate_handl return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (ngx_is_dir(r->fileinfo)) { - ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->filename.data); + if (!r->file.info_valid) { + if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_stat_fd_n " %s failed", r->file.name.data); + + if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_close_file_n " %s failed", r->file.name.data); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + r->file.info_valid = 1; + } +#endif + + if (ngx_is_dir(r->file.info)) { + ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); + +#if !(WIN32) + if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + "ngx_http_static_handler: " + ngx_close_file_n " %s failed", r->file.name.data); +#endif /* BROKEN: need to include server name */ @@ -144,6 +198,11 @@ static int ngx_http_core_translate_handl } +int ngx_http_send_header(ngx_http_request_t *r) +{ + return (*ngx_http_top_header_filter)(r); +} + int ngx_http_redirect(ngx_http_request_t *r, int redirect) { @@ -162,17 +221,27 @@ int ngx_http_error(ngx_http_request_t *r /* log request */ + ngx_http_special_response(r, error); return ngx_http_close_request(r); } int ngx_http_close_request(ngx_http_request_t *r) { - ngx_assert((r->fd != -1), /* void */; , r->connection->log, - "file already closed"); + ngx_log_debug(r->connection->log, "CLOSE#: %d" _ r->file.fd); + + ngx_http_log_handler(r); + + ngx_assert((r->file.fd != NGX_INVALID_FILE), /* void */ ; , + r->connection->log, "file already closed"); - if (r->fd != -1) { - if (ngx_close_file(r->fd) == -1) + if (r->file.fd != NGX_INVALID_FILE) { +/* STUB WIN32 */ +#if (WIN32) + if (ngx_close_file(r->file.fd) == 0) +#else + if (ngx_close_file(r->file.fd) == -1) +#endif ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, ngx_close_file_n " failed"); } diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c --- a/src/http/ngx_http_event.c +++ b/src/http/ngx_http_event.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -33,19 +34,14 @@ static int ngx_http_process_request_line static int ngx_http_process_request_headers(ngx_http_request_t *r); static int ngx_http_process_request_header_line(ngx_http_request_t *r); -static int ngx_http_event_handler(ngx_http_request_t *r); -static int ngx_http_block_read(ngx_event_t *ev); - - -static int ngx_http_read_discarded_body(ngx_event_t *ev); - -int ngx_http_handler(ngx_http_request_t *r); -static int ngx_http_set_default_handler(ngx_http_request_t *r); +static int ngx_http_event_request_handler(ngx_http_request_t *r); static int ngx_http_writer(ngx_event_t *ev); -static int ngx_http_set_lingering_close(ngx_http_request_t *r); +static int ngx_http_block_read(ngx_event_t *ev); +static int ngx_http_read_discarded_body(ngx_event_t *ev); static int ngx_http_keepalive_handler(ngx_event_t *ev); -static int ngx_http_lingering_close(ngx_event_t *ev); +static int ngx_http_set_lingering_close(ngx_http_request_t *r); +static int ngx_http_lingering_close_handler(ngx_event_t *ev); #if 0 int ngx_http_special_response(ngx_http_request_t *r, int error); @@ -70,6 +66,8 @@ static char *header_errors[] = { static ngx_http_header_t headers_in[] = { { 4, "Host", offsetof(ngx_http_headers_in_t, host) }, { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) }, + { 17, "If-Modified-Since", + offsetof(ngx_http_headers_in_t,if_modified_since) }, { 10, "User-Agent", offsetof(ngx_http_headers_in_t, user_agent) }, @@ -106,15 +104,11 @@ int ngx_http_init_connection(ngx_connect ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text.len), NGX_ERROR); - /* STUB: should be ngx_inet_ntop() */ -#if (WIN32) - c->addr_text.data = inet_ntoa((struct in_addr *) - ((char *)c->sockaddr + c->addr)); -#else - inet_ntop(c->family, (char *)c->sockaddr + c->addr, - c->addr_text.data, c->addr_text.len); -#endif - /**/ + ngx_test_null(c->addr_text.len, + ngx_inet_ntop(c->family, + (char *)c->sockaddr + c->addr, + c->addr_text.data, c->addr_text.len), + NGX_ERROR); ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)), NGX_ERROR); @@ -166,6 +160,7 @@ static int ngx_http_init_request(ngx_eve c->data = r; r->connection = c; r->server = srv; + r->file.fd = NGX_INVALID_FILE; /* STUB */ r->srv_conf = ngx_srv_conf; @@ -189,6 +184,10 @@ static int ngx_http_init_request(ngx_eve ngx_test_null(r->ctx, ngx_pcalloc(r->pool, sizeof(void *) * ngx_max_module), ngx_http_close_request(r)); + r->headers_out.headers = ngx_create_table(r->pool, 10); + r->headers_out.content_length = -1; + r->headers_out.last_modified_time = -1; + ev->event_handler = ngx_http_process_request_header; r->state_handler = ngx_http_process_request_line; r->header_timeout = 1; @@ -262,7 +261,7 @@ static int ngx_http_process_request_head } if (rc == NGX_OK) - return ngx_http_event_handler(r); + return ngx_http_event_request_handler(r); else return rc; } @@ -280,7 +279,8 @@ static int ngx_http_process_request_line c = r->connection; if (rc == NGX_OK) { - r->uri.len = r->uri_end - r->uri_start; + r->uri.len = (r->args_start ? r->args_start - 1 : r->uri_end) + - r->uri_start; ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), ngx_http_close_request(r)); ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); @@ -309,7 +309,8 @@ static int ngx_http_process_request_line /* */ if (r->uri_ext) { - r->exten.len = r->uri_end - r->uri_ext; + r->exten.len = (r->args_start ? r->args_start - 1 : r->uri_end) + - r->uri_ext; ngx_test_null(r->exten.data, ngx_palloc(r->pool, r->exten.len + 1), ngx_http_close_request(r)); @@ -326,8 +327,6 @@ static int ngx_http_process_request_line /* TODO: check too long URI - no space for header, compact buffer */ r->headers_in.headers = ngx_create_table(r->pool, 10); - /* THINK: when to create out.headers ? */ - r->headers_out.headers = ngx_create_table(r->pool, 10); r->state_handler = ngx_http_process_request_headers; ctx = r->connection->log->data; @@ -372,7 +371,14 @@ static int ngx_http_process_request_head } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { ngx_log_debug(r->connection->log, "HTTP header done"); - return NGX_OK; + + if (r->http_version > NGX_HTTP_VERSION_10 + && r->headers_in.host == NULL) + { + return ngx_http_error(r, NGX_HTTP_BAD_REQUEST); + } else { + return NGX_OK; + } } else if (rc == NGX_AGAIN) { return NGX_AGAIN; @@ -422,7 +428,7 @@ static int ngx_http_process_request_head } -static int ngx_http_event_handler(ngx_http_request_t *r) +static int ngx_http_event_request_handler(ngx_http_request_t *r) { int rc; ngx_msec_t timeout; @@ -494,181 +500,6 @@ static int ngx_http_event_handler(ngx_ht } -static int ngx_http_block_read(ngx_event_t *ev) -{ - ngx_log_debug(ev->log, "http read blocked"); - - ev->blocked = 1; - return ngx_del_event(ev, NGX_READ_EVENT); -} - - - -/* FIND PLACE ******************** */ - -void ngx_http_discard_body(ngx_http_request_t *r) -{ - ngx_log_debug(r->connection->log, "set discard body"); - - ngx_del_timer(r->connection->read); - - if (r->client_content_length) - r->connection->read->event_handler = ngx_http_read_discarded_body; -} - - -static int ngx_http_read_discarded_body(ngx_event_t *ev) -{ - size_t size; - ssize_t n; - ngx_connection_t *c; - ngx_http_request_t *r; - - c = (ngx_connection_t *) ev->data; - r = (ngx_http_request_t *) c->data; - - ngx_log_debug(ev->log, "http read discarded body"); - - if (ev->timedout) - return NGX_ERROR; - - if (r->discarded_buffer == NULL) - ngx_test_null(r->discarded_buffer, - ngx_palloc(r->pool, r->server->discarded_buffer_size), - NGX_ERROR); - - size = r->client_content_length; - if (size > r->server->discarded_buffer_size) - size = r->server->discarded_buffer_size; - - n = ngx_event_recv(c, r->discarded_buffer, size); - if (n == NGX_ERROR) - return NGX_ERROR; - - if (n == NGX_AGAIN) - return NGX_OK; - - r->client_content_length -= n; - /* XXX: what if r->client_content_length == 0 ? */ - return NGX_OK; -} - - -static int ngx_http_discarded_read(ngx_event_t *ev) -{ - ssize_t n; - ngx_connection_t *c; - ngx_http_request_t *r; - - c = (ngx_connection_t *) ev->data; - r = (ngx_http_request_t *) c->data; - - ngx_log_debug(ev->log, "http discarded read"); - - if (ev->timedout) - return NGX_ERROR; - - if (r->discarded_buffer == NULL) - ngx_test_null(r->discarded_buffer, - ngx_palloc(r->pool, r->server->discarded_buffer_size), - NGX_ERROR); - - n = ngx_event_recv(c, r->discarded_buffer, - r->server->discarded_buffer_size); - - return n; -} - -/* ******************** */ - - -#if 0 -int ngx_http_handler(ngx_http_request_t *r) -{ - int rc; - - r->connection->unexpected_eof = 0; - r->lingering_close = 1; - - /* STUB: should find handler */ -#if 1 - r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; -#endif - rc = ngx_http_set_default_handler(r); - - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) - return ngx_http_special_response(r, rc); - - rc = r->handler(r); - - return rc; -} -#endif - - -#if 0 -static int ngx_http_set_default_handler(ngx_http_request_t *r) -{ - ngx_err_t err; - char *name, *loc, *file; - -#if 0 - /* STUB */ - r->handler = ngx_http_proxy_handler; - return NGX_OK; -#endif - -/* NO NEEDED - ngx_test_null(r->headers_out, - ngx_pcalloc(r->pool, sizeof(ngx_http_headers_out_t)), - NGX_HTTP_INTERNAL_SERVER_ERROR); -*/ - - if (*(r->uri_end - 1) == '/') { - r->handler = ngx_http_index_handler; - return NGX_OK; - } - - /* 20 bytes is spare space for some index name, i.e. index.html */ - r->filename_len = r->uri_end - r->uri_start + r->server->doc_root_len + 20; - - ngx_test_null(r->filename, - ngx_palloc(r->pool, r->filename_len), - NGX_HTTP_INTERNAL_SERVER_ERROR); - - r->location = ngx_cpystrn(r->filename, r->server->doc_root, - r->server->doc_root_len); - file = ngx_cpystrn(r->location, r->uri_start, - r->uri_end - r->uri_start + 1); - - ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->filename); - - if (ngx_file_type(r->filename, &r->fileinfo) == -1) { - err = ngx_errno; - ngx_log_error(NGX_LOG_ERR, r->connection->log, err, - ngx_file_type_n " %s failed", r->filename); - - if (err == NGX_ENOENT) - return NGX_HTTP_NOT_FOUND; - else - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (ngx_is_dir(r->fileinfo)) { - ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->filename); - *file++ = '/'; - *file = '\0'; - r->headers_out.location = r->location; - return NGX_HTTP_MOVED_PERMANENTLY; - } - - r->handler = ngx_http_static_handler; - - return NGX_OK; -} -#endif - - static int ngx_http_writer(ngx_event_t *ev) { int rc; @@ -735,35 +566,93 @@ static int ngx_http_writer(ngx_event_t * } -static int ngx_http_set_lingering_close(ngx_http_request_t *r) +static int ngx_http_block_read(ngx_event_t *ev) { - r->lingering_time = ngx_time() + r->server->lingering_time; - r->connection->read->event_handler = ngx_http_lingering_close; + ngx_log_debug(ev->log, "http read blocked"); + + ev->blocked = 1; + return ngx_del_event(ev, NGX_READ_EVENT, 0); +} + + +int ngx_http_discard_body(ngx_http_request_t *r) +{ + ngx_log_debug(r->connection->log, "set discard body"); ngx_del_timer(r->connection->read); - ngx_add_timer(r->connection->read, r->server->lingering_timeout); -#if (HAVE_CLEAR_EVENT) - if (ngx_add_event(r->connection->read, NGX_READ_EVENT, - NGX_CLEAR_EVENT) == NGX_ERROR) { -#else - if (ngx_add_event(r->connection->read, NGX_READ_EVENT, - NGX_ONESHOT_EVENT) == NGX_ERROR) { -#endif - return ngx_http_close_request(r); - } - - if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == NGX_ERROR) - { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno, - ngx_shutdown_socket_n " failed"); - return ngx_http_close_request(r); - } + if (r->client_content_length) + r->connection->read->event_handler = ngx_http_read_discarded_body; return NGX_OK; } +static int ngx_http_read_discarded_body(ngx_event_t *ev) +{ + size_t size; + ssize_t n; + ngx_connection_t *c; + ngx_http_request_t *r; + + c = (ngx_connection_t *) ev->data; + r = (ngx_http_request_t *) c->data; + + ngx_log_debug(ev->log, "http read discarded body"); + + if (ev->timedout) + return NGX_ERROR; + + if (r->discarded_buffer == NULL) + ngx_test_null(r->discarded_buffer, + ngx_palloc(r->pool, r->server->discarded_buffer_size), + NGX_ERROR); + + size = r->client_content_length; + if (size > r->server->discarded_buffer_size) + size = r->server->discarded_buffer_size; + + n = ngx_event_recv(c, r->discarded_buffer, size); + if (n == NGX_ERROR) + return NGX_ERROR; + + if (n == NGX_AGAIN) + return NGX_OK; + + r->client_content_length -= n; + /* XXX: what if r->client_content_length == 0 ? */ + return NGX_OK; +} + + +#if 0 +static int ngx_http_discarded_read(ngx_event_t *ev) +{ + ssize_t n; + ngx_connection_t *c; + ngx_http_request_t *r; + + c = (ngx_connection_t *) ev->data; + r = (ngx_http_request_t *) c->data; + + ngx_log_debug(ev->log, "http discarded read"); + + if (ev->timedout) + return NGX_ERROR; + + if (r->discarded_buffer == NULL) + ngx_test_null(r->discarded_buffer, + ngx_palloc(r->pool, r->server->discarded_buffer_size), + NGX_ERROR); + + n = ngx_event_recv(c, r->discarded_buffer, + r->server->discarded_buffer_size); + + return n; +} +#endif + + static int ngx_http_keepalive_handler(ngx_event_t *ev) { ssize_t n; @@ -772,7 +661,7 @@ static int ngx_http_keepalive_handler(ng c = (ngx_connection_t *) ev->data; - ngx_log_debug(ev->log, "http keepalive"); + ngx_log_debug(ev->log, "http keepalive handler"); if (ev->timedout) return NGX_DONE; @@ -800,17 +689,46 @@ static int ngx_http_keepalive_handler(ng } -static int ngx_http_lingering_close(ngx_event_t *ev) +static int ngx_http_set_lingering_close(ngx_http_request_t *r) { - ssize_t n; - ngx_msec_t timer; + r->lingering_time = ngx_time() + r->server->lingering_time; + r->connection->read->event_handler = ngx_http_lingering_close_handler; + + ngx_del_timer(r->connection->read); + ngx_add_timer(r->connection->read, r->server->lingering_timeout); + +#if (HAVE_CLEAR_EVENT) + if (ngx_add_event(r->connection->read, NGX_READ_EVENT, + NGX_CLEAR_EVENT) == NGX_ERROR) { +#else + if (ngx_add_event(r->connection->read, NGX_READ_EVENT, + NGX_ONESHOT_EVENT) == NGX_ERROR) { +#endif + return ngx_http_close_request(r); + } + + if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == -1) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno, + ngx_shutdown_socket_n " failed"); + return ngx_http_close_request(r); + } + + return NGX_OK; +} + + +static int ngx_http_lingering_close_handler(ngx_event_t *ev) +{ + ssize_t n; + ngx_msec_t timer; ngx_connection_t *c; ngx_http_request_t *r; c = (ngx_connection_t *) ev->data; r = (ngx_http_request_t *) c->data; - ngx_log_debug(ev->log, "http lingering close"); + ngx_log_debug(ev->log, "http lingering close handler"); if (ev->timedout) return NGX_DONE; diff --git a/src/http/ngx_http_get_time.c b/src/http/ngx_http_get_time.c --- a/src/http/ngx_http_get_time.c +++ b/src/http/ngx_http_get_time.c @@ -2,6 +2,7 @@ #include #include +#include ngx_http_get_time(char *buf, time_t t) diff --git a/src/http/ngx_http_header.h b/src/http/ngx_http_header.h deleted file mode 100644 --- a/src/http/ngx_http_header.h +++ /dev/null @@ -1,2 +0,0 @@ - -gx_chunk_t *gx_http_header(gx_http_request_t *r, gx_http_header_out_t *out); diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c --- a/src/http/ngx_http_header_filter.c +++ b/src/http/ngx_http_header_filter.c @@ -9,7 +9,7 @@ #include -#if 0 +static int ngx_http_header_filter(ngx_http_request_t *r); ngx_http_module_t ngx_http_header_filter_module = { NGX_HTTP_MODULE, @@ -21,33 +21,40 @@ ngx_http_module_t ngx_http_header_filte NULL, /* init module */ NULL, /* translate handler */ - ngx_http_header_filter_init /* init output header filter */ - NULL /* init output body filter */ + ngx_http_header_filter, /* output header filter */ + NULL, /* next output header filter */ + NULL, /* output body filter */ + NULL /* next output body filter */ }; -#endif - static char server_string[] = "Server: " NGINX_VER CRLF; static ngx_str_t http_codes[] = { + { 6, "200 OK" }, { 21, "301 Moved Permanently" }, + { 21, "302 Moved Temporarily" }, + { 0, NULL }, + { 16, "304 Not Modified" }, { 15, "400 Bad Request" }, { 0, NULL }, { 0, NULL }, { 13, "403 Forbidden" }, - { 13, "404 Not Found" } + { 13, "404 Not Found" }, + + { 25, "500 Internal Server Error" } }; -int ngx_http_header_filter(ngx_http_request_t *r) +static int ngx_http_header_filter(ngx_http_request_t *r) { int len, status, i; + time_t ims; ngx_hunk_t *h; ngx_chain_t *ch; ngx_table_elt_t *header; @@ -55,10 +62,30 @@ int ngx_http_header_filter(ngx_http_requ if (r->http_version < NGX_HTTP_VERSION_10) return NGX_OK; - /* 9 is for "HTTP/1.1 ", 2 is for trailing "\r\n" + /* 9 is for "HTTP/1.x ", 2 is for trailing "\r\n" and 2 is for end of header */ len = 9 + 2 + 2; + if (r->headers_in.if_modified_since && r->headers_out.status == NGX_HTTP_OK) + { + /* TODO: check LM header */ + if (r->headers_out.last_modified_time) { + ims = ngx_http_parse_time( + r->headers_in.if_modified_since->value.data, + r->headers_in.if_modified_since->value.len); + + ngx_log_debug(r->connection->log, "%d %d" _ + ims _ r->headers_out.last_modified_time); + + if (ims != NGX_ERROR && ims >= r->headers_out.last_modified_time) { + r->headers_out.status = NGX_HTTP_NOT_MODIFIED; + r->headers_out.content_length = -1; + r->headers_out.content_type->key.len = 0; + r->header_only = 1; + } + } + } + /* status line */ if (r->headers_out.status_line.len) { len += r->headers_out.status_line.len; @@ -69,8 +96,12 @@ int ngx_http_header_filter(ngx_http_requ else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 1; + else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) + status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 1 + 4; + else - status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 1 + 1; + status = r->headers_out.status + - NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 5; len += http_codes[status].len; } @@ -99,6 +130,14 @@ int ngx_http_header_filter(ngx_http_requ len += r->headers_out.content_type.len + 16; #endif + if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) { + len += r->headers_out.last_modified->key.len + + r->headers_out.last_modified->value.len + 2; + } else if (r->headers_out.last_modified_time != -1) { + /* "Last-Modified: ... \r\n"; */ + len += 46; + } + if (r->keepalive) len += 24; else @@ -114,7 +153,7 @@ int ngx_http_header_filter(ngx_http_requ ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 64), NGX_ERROR); - /* "HTTP/1.1 " */ + /* "HTTP/1.x " */ ngx_memcpy(h->last.mem, "HTTP/1.1 ", 9); h->last.mem += 9; @@ -159,6 +198,17 @@ int ngx_http_header_filter(ngx_http_requ } #endif + if (!(r->headers_out.last_modified + && r->headers_out.last_modified->key.len) + && r->headers_out.last_modified_time != -1) + { + ngx_memcpy(h->last.mem, "Last-Modified: ", 15); + h->last.mem += 15; + h->last.mem += ngx_http_get_time(h->last.mem, + r->headers_out.last_modified_time); + *(h->last.mem++) = CR; *(h->last.mem++) = LF; + } + if (r->keepalive) { ngx_memcpy(h->last.mem, "Connection: keep-alive" CRLF, 24); h->last.mem += 24; @@ -181,9 +231,17 @@ int ngx_http_header_filter(ngx_http_requ *(h->last.mem++) = CR; *(h->last.mem++) = LF; } + /* STUB */ + *(h->last.mem) = '\0'; + ngx_log_debug(r->connection->log, "%s\n" _ h->pos.mem); + /**/ + /* end of HTTP header */ *(h->last.mem++) = CR; *(h->last.mem++) = LF; + if (r->header_only) + h->type |= NGX_HUNK_LAST; + ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR); ch->hunk = h; diff --git a/src/http/ngx_http_modules.c b/src/http/ngx_http_modules.c --- a/src/http/ngx_http_modules.c +++ b/src/http/ngx_http_modules.c @@ -1,12 +1,18 @@ #include +extern ngx_http_module_t ngx_http_header_filter_module; + extern ngx_http_module_t ngx_http_write_filter_module; extern ngx_http_module_t ngx_http_output_filter_module; + extern ngx_http_module_t ngx_http_core_module; extern ngx_http_module_t ngx_http_index_module; ngx_http_module_t *ngx_http_modules[] = { + + &ngx_http_header_filter_module, + &ngx_http_write_filter_module, &ngx_http_output_filter_module, diff --git a/src/http/ngx_http_output_filter.c b/src/http/ngx_http_output_filter.c --- a/src/http/ngx_http_output_filter.c +++ b/src/http/ngx_http_output_filter.c @@ -9,29 +9,15 @@ #include +int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk); static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src); +#if 0 static int ngx_http_output_filter_init( int (**next_filter)(ngx_http_request_t *r, ngx_chain_t *ch)); +#endif static void *ngx_http_output_filter_create_conf(ngx_pool_t *pool); -static ngx_command_t ngx_http_output_filter_commands[]; - - -ngx_http_module_t ngx_http_output_filter_module = { - NGX_HTTP_MODULE, - - NULL, /* create server config */ - ngx_http_output_filter_create_conf, /* create location config */ - ngx_http_output_filter_commands, /* module directives */ - - NULL, /* init module */ - NULL, /* translate handler */ - - ngx_http_output_filter_init /* init output body filter */ -}; - - static ngx_command_t ngx_http_output_filter_commands[] = { {"output_buffer", ngx_conf_set_size_slot, @@ -44,8 +30,27 @@ static ngx_command_t ngx_http_output_fil }; +ngx_http_module_t ngx_http_output_filter_module = { + NGX_HTTP_MODULE, + + NULL, /* create server config */ + ngx_http_output_filter_create_conf, /* create location config */ + ngx_http_output_filter_commands, /* module directives */ + + NULL, /* init module */ + NULL, /* translate handler */ + + NULL, /* output header filter */ + NULL, /* next output header filter */ + ngx_http_output_filter, /* output body filter */ + NULL /* next output body filter */ +}; + + +#if 0 static int (*ngx_http_output_next_filter)(ngx_http_request_t *r, ngx_chain_t *ch); +#endif int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) @@ -66,7 +71,9 @@ int ngx_http_output_filter(ngx_http_requ ngx_http_output_filter_module, sizeof(ngx_http_output_filter_ctx_t)); +#if 0 ctx->next_filter = ngx_http_output_next_filter; +#endif } if (hunk && (hunk->type & NGX_HUNK_LAST)) @@ -87,7 +94,11 @@ int ngx_http_output_filter(ngx_http_requ /* our hunk is still busy */ if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { + rc = ngx_http_output_filter_module. + next_output_body_filter(r, NULL); +#if 0 rc = ctx->next_filter(r, NULL); +#endif /* our hunk is free */ } else { @@ -110,7 +121,7 @@ int ngx_http_output_filter(ngx_http_requ if (ce->hunk->type & NGX_HUNK_FILE) break; - if ((ce->hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP) + if ((ce->hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)) && (r->filter & NGX_HTTP_FILTER_NEED_TEMP)) break; } @@ -121,7 +132,11 @@ int ngx_http_output_filter(ngx_http_requ ctx->out.next = NULL; } + rc = ngx_http_output_filter_module. + next_output_body_filter(r, &ctx->out); +#if 0 rc = ctx->next_filter(r, &ctx->out); +#endif; } /* delete completed hunks from input chain */ @@ -139,7 +154,11 @@ int ngx_http_output_filter(ngx_http_requ } else { if (hunk == NULL) { + rc = ngx_http_output_filter_module. + next_output_body_filter(r, NULL); +#if 0 rc = ctx->next_filter(r, NULL); +#endif; } else { @@ -147,7 +166,7 @@ int ngx_http_output_filter(ngx_http_requ if (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) && (hunk->type & NGX_HUNK_FILE)) || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) - && (hunk->type & NGX_HUNK_MEMORY|NGX_HUNK_MMAP)) + && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))) ) { /* out hunk is still busy */ @@ -155,7 +174,11 @@ int ngx_http_output_filter(ngx_http_requ ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); + rc = ngx_http_output_filter_module. + next_output_body_filter(r, NULL); +#if 0 rc = ctx->next_filter(r, NULL); +#endif } else { if (ctx->hunk == NULL) { @@ -201,7 +224,11 @@ int ngx_http_output_filter(ngx_http_requ ctx->out.hunk = ctx->hunk; ctx->out.next = NULL; + rc = ngx_http_output_filter_module. + next_output_body_filter(r, &ctx->out); +#if 0 rc = ctx->next_filter(r, &ctx->out); +#endif } } @@ -209,7 +236,11 @@ int ngx_http_output_filter(ngx_http_requ ctx->out.hunk = hunk; ctx->out.next = NULL; + rc = ngx_http_output_filter_module. + next_output_body_filter(r, &ctx->out); +#if 0 rc = ctx->next_filter(r, &ctx->out); +#endif } } } @@ -269,6 +300,11 @@ static int ngx_http_output_filter_copy_h dst->last.mem += size; } +#if 1 + if (src->type & NGX_HUNK_LAST) + dst->type |= NGX_HUNK_LAST; +#endif + return NGX_OK; } @@ -286,6 +322,7 @@ static void *ngx_http_output_filter_crea return conf; } +#if 0 static int ngx_http_output_filter_init( int (**next_filter)(ngx_http_request_t *r, ngx_chain_t *ch)) { @@ -294,3 +331,4 @@ static int ngx_http_output_filter_init( return NGX_OK; } +#endif diff --git a/src/http/ngx_http_output_filter.h b/src/http/ngx_http_output_filter.h --- a/src/http/ngx_http_output_filter.h +++ b/src/http/ngx_http_output_filter.h @@ -15,7 +15,9 @@ typedef struct { } ngx_http_output_filter_conf_t; typedef struct { +#if 0 int (*next_filter)(ngx_http_request_t *r, ngx_chain_t *ch); +#endif ngx_hunk_t *hunk; ngx_chain_t *in; ngx_chain_t out; diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -110,7 +110,7 @@ printf("\nstate: %d, pos: %x, end: %x, c } break; - /* check dot after slash */ + /* check "/." or "//" */ case sw_after_slash_in_uri: switch (ch) { case CR: @@ -132,8 +132,9 @@ printf("\nstate: %d, pos: %x, end: %x, c state = sw_uri; break; case '/': +#if (WIN32) r->complex_uri = 1; - state = sw_uri; +#endif break; case '?': r->args_start = p; diff --git a/src/http/ngx_http_parse_time.c b/src/http/ngx_http_parse_time.c --- a/src/http/ngx_http_parse_time.c +++ b/src/http/ngx_http_parse_time.c @@ -1,7 +1,8 @@ -#include +#include +#include +#include -#define NGX_ERROR -1 static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -16,6 +17,7 @@ time_t ngx_http_parse_time(char *value, isoc /* Tue Dec 10 23:50:13 2002 */ } fmt; + fmt = 0; end = value + len; for (p = value; p < end; p++) { @@ -182,31 +184,38 @@ time_t ngx_http_parse_time(char *value, + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; } +#if 0 printf("%d.%d.%d %d:%d:%d\n", day, month + 1, year, hour, min, sec); +#endif - if (hour > 23 || min > 60 || sec > 60) + if (hour > 23 || min > 59 || sec > 59) return NGX_ERROR; if (day == 29 && month == 1) { if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) return NGX_ERROR; - } else if (day > mday[month]) + } else if (day > mday[month]) { return NGX_ERROR; } if (sizeof(time_t) <= 4 && year >= 2038) return NGX_ERROR; + /* shift new year to 1st March, needed for Gauss's formula */ if (--month <= 0) { month += 12; year -= 1; } - - return year / 4 - year / 100 + year / 400 - + 367 * month / 12 + day + year * 365 - 719499; + /* Gauss's formula for days from 1 March 1 BC */ + return (365 * year + year / 4 - year / 100 + year / 400 + + 367 * month / 12 + day - 31 + /* 719527 days are between 1 March 1 BC and 1 March 1970, + 31 and 28 days in Jan and Feb 1970 */ + - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; } +#if 0 char zero[] = "Sun, 01 Jan 1970 08:49:30"; char one[] = "Sunday, 11-Dec-02 08:49:30"; char two[] = "Sun Mar 1 08:49:37 2000"; @@ -228,3 +237,5 @@ main() rc = ngx_http_parse_time(thr, sizeof(thr) - 1); printf("rc: %d\n", rc); } + +#endif diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -1,21 +1,91 @@ +#include #include -#if 0 #include -#endif +#include #include +static char error_tail[] = +"
" NGINX_VER "
" CRLF +"" CRLF +"" CRLF +; + +static char error_400_page[] = +"" CRLF +"400 Bad Request" CRLF +"" CRLF +"

400 Bad Request

" CRLF +; + +static char error_404_page[] = +"" CRLF +"404 Not Found" CRLF +"" CRLF +"

404 Not Found

" CRLF +; + + +static ngx_str_t error_pages[] = { + { 0, NULL}, /* 301 */ + { 0, NULL}, /* 302 */ + { 0, NULL}, /* 303 */ + { 0, NULL}, /* 304 */ + + { sizeof(error_400_page) - 1, error_400_page }, + { 0, NULL}, /* 401 */ + { 0, NULL}, /* 402 */ + { 0, NULL}, /* 403 */ + { sizeof(error_404_page) - 1, error_404_page }, + + { 0, NULL} /* 500 */ +}; int ngx_http_special_response(ngx_http_request_t *r, int error) { - switch (error) { + int rc, err, len; + ngx_hunk_t *message, *tail; + + len = 0; + + r->headers_out.status = error; + + if (error < NGX_HTTP_BAD_REQUEST) + err = error - NGX_HTTP_MOVED_PERMANENTLY; + + else if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) + err = error - NGX_HTTP_BAD_REQUEST + 4; + + else + err = NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 5; + + if (error_pages[err].len == 0) + r->headers_out.content_length = -1; + else + r->headers_out.content_length = error_pages[err].len + + len + sizeof(error_tail); - default: - r->headers_out.status = error; - return ngx_http_header_filter(r); + ngx_http_send_header(r); + + if (error_pages[err].len == 0) + return NGX_OK; + + ngx_test_null(message, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + message->type = NGX_HUNK_MEMORY; + message->pos.mem = error_pages[err].data; + message->last.mem = error_pages[err].data + error_pages[err].len; - } + rc = ngx_http_output_filter(r, message); + + ngx_test_null(tail, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), + NGX_HTTP_INTERNAL_SERVER_ERROR); - return ngx_http_error(r, error); + tail->type = NGX_HUNK_MEMORY|NGX_HUNK_LAST; + tail->pos.mem = error_tail; + tail->last.mem = error_tail + sizeof(error_tail); + + rc = ngx_http_output_filter(r, tail); } diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c --- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -9,10 +9,23 @@ #include -static ngx_command_t ngx_http_write_filter_commands[]; +int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in); static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool); + +static ngx_command_t ngx_http_write_filter_commands[] = { + + {"write_buffer", ngx_conf_set_size_slot, + offsetof(ngx_http_write_filter_conf_t, buffer_output), + NGX_HTTP_LOC_CONF, NGX_CONF_TAKE1, + "set write filter size to buffer output"}, + + {NULL} + +}; + + ngx_http_module_t ngx_http_write_filter_module = { NGX_HTTP_MODULE, @@ -23,19 +36,10 @@ ngx_http_module_t ngx_http_write_filter NULL, /* init module */ NULL, /* translate handler */ - NULL /* init output body filter */ -}; - - -static ngx_command_t ngx_http_write_filter_commands[] = { - - {"write_buffer", ngx_conf_set_size_slot, - offsetof(ngx_http_write_filter_conf_t, buffer_output), - NGX_HTTP_LOC_CONF, NGX_CONF_TAKE1, - "set write filter size to buffer output"}, - - {NULL} - + NULL, /* output header filter */ + NULL, /* next output header filter */ + ngx_http_write_filter, /* output body filter */ + NULL, /* next output body filter */ }; @@ -69,7 +73,7 @@ int ngx_http_write_filter(ngx_http_reque ch->hunk->type _ ch->hunk->pos.file _ ch->hunk->last.file - ch->hunk->pos.file); - if (ch->hunk->type & NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED) + if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) flush = size; if (ch->hunk->type & NGX_HUNK_LAST) @@ -90,7 +94,7 @@ int ngx_http_write_filter(ngx_http_reque ch->hunk->type _ ch->hunk->pos.file _ ch->hunk->last.file - ch->hunk->pos.file); - if (ch->hunk->type & NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED) + if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) flush = size; if (ch->hunk->type & NGX_HUNK_LAST) @@ -101,6 +105,8 @@ int ngx_http_write_filter(ngx_http_reque ngx_get_module_loc_conf(r->main ? r->main : r, ngx_http_write_filter_module); + ngx_log_debug(r->connection->log, "l:%d f:%d" _ last _ flush); + if (!last && flush == 0 && size < conf->buffer_output) return NGX_OK; diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -6,6 +6,9 @@ #include typedef int ngx_fd_t; +#define NGX_INVALID_FILE -1 +#define NGX_FILE_ERROR -1 + typedef struct stat ngx_file_info_t; @@ -27,6 +30,7 @@ typedef struct stat ngx_fil #define ngx_stat_fd_n "fstat()" #define ngx_is_dir(sb) (S_ISDIR(sb.st_mode)) +#define ngx_is_file(sb) (S_ISREG(sb.st_mode)) #define ngx_file_size(sb) sb.st_size #define ngx_file_mtime(sb) sb.st_mtime diff --git a/src/os/unix/ngx_sendv.c b/src/os/unix/ngx_sendv.c --- a/src/os/unix/ngx_sendv.c +++ b/src/os/unix/ngx_sendv.c @@ -8,21 +8,21 @@ ssize_t ngx_sendv(ngx_connection_t *c, ngx_iovec_t *iovec, int n) { - ssize_t rc; - ngx_err_t err; + ssize_t rc; + ngx_err_t err; - rc = writev(c->fd, iovec, n); + rc = writev(c->fd, iovec, n); - if (rc == -1) { - err = ngx_socket_errno; - if (err == NGX_EAGAIN) { - ngx_log_error(NGX_LOG_INFO, c->log, err, "sendv() eagain"); - return NGX_AGAIN; - } + if (rc == -1) { + err = ngx_socket_errno; + if (err == NGX_EAGAIN) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "sendv() eagain"); + return NGX_AGAIN; + } - ngx_log_error(NGX_LOG_ERR, c->log, err, "sendv() failed"); - return NGX_ERROR; - } + ngx_log_error(NGX_LOG_ERR, c->log, err, "sendv() failed"); + return NGX_ERROR; + } - return rc; + return rc; } diff --git a/src/os/win32/ngx_files.c b/src/os/win32/ngx_files.c --- a/src/os/win32/ngx_files.c +++ b/src/os/win32/ngx_files.c @@ -14,5 +14,3 @@ ssize_t ngx_read_file(ngx_file_t *file, return n; } - - diff --git a/src/os/win32/ngx_files.h b/src/os/win32/ngx_files.h --- a/src/os/win32/ngx_files.h +++ b/src/os/win32/ngx_files.h @@ -11,6 +11,9 @@ #endif typedef HANDLE ngx_fd_t; +#define NGX_INVALID_FILE INVALID_HANDLE_VALUE +#define NGX_FILE_ERROR 0 + typedef unsigned __int64 off_t; typedef BY_HANDLE_FILE_INFORMATION ngx_file_info_t; @@ -25,33 +28,32 @@ typedef BY_HANDLE_FILE_INFORMATION ngx_ #define NGX_FILE_RDONLY GENERIC_READ +#define ngx_close_file CloseHandle +#define ngx_close_file_n "CloseHandle()" int ngx_file_type(char *filename, ngx_file_info_t *fi); -#define ngx_file_type_n "GetFileAttributes" +#define ngx_file_type_n "GetFileAttributes" -#define ngx_stat_fd(fd, fi) GetFileInformationByHandle(fd, fi) -#define ngx_stat_fd_n "GetFileInformationByHandle" +#define ngx_stat_fd(fd, fi) GetFileInformationByHandle(fd, fi) +#define ngx_stat_fd_n "GetFileInformationByHandle" -#define ngx_is_dir(fi) (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) +#define ngx_is_dir(fi) (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) +#define ngx_is_file(fi) !(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) #define ngx_file_size(fi) \ - fi.nFileSizeLow - -/* -#define ngx_file_size(fi) \ - ((off_t) fi.nFileSizeHigh << 32 & fi.nFileSizeLow) -*/ - -#define ngx_file_mtime(fi) fi.ftLastWriteTime - -/* -1970 - 1601: - 116444736000000000 - 19DB1DED53E8000 -*/ + (((off_t) fi.nFileSizeHigh << 32) | fi.nFileSizeLow) -#define ngx_read_file_n "ReadFile()" +/* There are 134774 days between 1 Jan 1970 and 1 Jan 1601, + 11644473600 seconds or 11644473600,000,000,0 100-nanosecond intervals */ + +#define ngx_file_mtime(fi) \ + (time_t) (((((unsigned __int64) fi.ftLastWriteTime.dwHighDateTime << 32) \ + | fi.ftLastWriteTime.dwLowDateTime) \ + - 116444736000000000) / 10000000) + + +#define ngx_read_file_n "ReadFile()" #endif /* _NGX_FILES_H_INCLUDED_ */ diff --git a/src/os/win32/ngx_sendv.c b/src/os/win32/ngx_sendv.c --- a/src/os/win32/ngx_sendv.c +++ b/src/os/win32/ngx_sendv.c @@ -6,29 +6,39 @@ #include #include +#include + ssize_t ngx_sendv(ngx_connection_t *c, ngx_iovec_t *iovec, int n) { - int rc; - size_t sent; - ngx_err_t err; + int rc; + size_t sent; + ngx_err_t err; - ngx_log_debug(c->log, "WSASend() start"); +#if 0 + /* STUB: WSABUF must be 4-byte aligned. Undocumented WSAEINVAL error */ + ngx_iovec_t iov[10]; + ngx_memcpy(iov, iovec, n * sizeof(ngx_iovec_t)); +#endif - rc = WSASend(c->fd, iovec, n, &sent, 0, NULL, NULL); + sent = 0; - ngx_log_debug(c->log, "WSASend() done"); + ngx_log_debug(c->log, "WSASend: %d, %d, %08x" _ c->fd _ n _ iovec); + + rc = WSASend(c->fd, iovec, n, &sent, 0, NULL, NULL); - if (rc == -1) { - err = ngx_socket_errno; + ngx_log_debug(c->log, "WSASend() done"); + + if (rc == SOCKET_ERROR) { + err = ngx_socket_errno; - if (err == NGX_EAGAIN) { - ngx_log_error(NGX_LOG_INFO, c->log, err, "WSASend() eagain"); - return NGX_AGAIN; - } + if (err == NGX_EAGAIN) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "WSASend() eagain"); + return NGX_AGAIN; + } - ngx_log_error(NGX_LOG_ERR, c->log, err, "WSASend() failed"); - return NGX_ERROR; - } + ngx_log_error(NGX_LOG_ERR, c->log, err, "WSASend() failed"); + return NGX_ERROR; + } - return sent; + return sent; } diff --git a/src/os/win32/ngx_time.h b/src/os/win32/ngx_time.h --- a/src/os/win32/ngx_time.h +++ b/src/os/win32/ngx_time.h @@ -21,5 +21,8 @@ typedef FILETIME ngx_mtime_t; #define ngx_localtime GetLocalTime #define ngx_msec GetTickCount +/* STUB */ +#define ngx_time() time(NULL) + #endif /* _NGX_TIME_H_INCLUDED_ */