# HG changeset patch # User Igor Sysoev # Date 1067355941 0 # Node ID fb61ba77bebae5cbcc3ec3c164e70bc876146965 # Parent 96993d4d50679e838d0c9ec7c0af087cb8663616 nginx-0.0.1-2003-10-28-18:45:41 import diff --git a/src/core/ngx_alloc.h b/src/core/ngx_alloc.h --- a/src/core/ngx_alloc.h +++ b/src/core/ngx_alloc.h @@ -17,8 +17,6 @@ #define ngx_test_null(p, alloc, rc) if ((p = alloc) == NULL) { return rc; } -#define ngx_is_null(p, alloc) if ((p = alloc) == NULL) - typedef struct ngx_pool_large_s ngx_pool_large_t; 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 @@ -422,8 +422,8 @@ static int ngx_kqueue_process_events(ngx ev->available = event_list[i].data; if (event_list[i].flags & EV_EOF) { - ev->eof = 1; - ev->error = event_list[i].fflags; + ev->kq_eof = 1; + ev->kq_errno = event_list[i].fflags; } if (ev->oneshot && ev->timer_set) { 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 @@ -29,8 +29,9 @@ struct ngx_event_s { unsigned int index; - ngx_event_t *prev; /* queue in mutex(), aio_read(), aio_write() */ - ngx_event_t *next; /* */ + /* queue in mutex(), aio_read(), aio_write() */ + ngx_event_t *prev; + ngx_event_t *next; ngx_event_t *timer_prev; ngx_event_t *timer_next; @@ -40,22 +41,22 @@ struct ngx_event_s { ngx_log_t *log; - int available; /* kqueue only: */ - /* accept: number of sockets that wait */ - /* to be accepted */ - /* read: bytes to read */ - /* write: available space in buffer */ - /* otherwise: */ - /* accept: 1 if accept many, 0 otherwise */ + /* + * kqueue only: + * accept: number of sockets that wait to be accepted + * read: bytes to read + * write: available space in buffer + * + * otherwise: + * accept: 1 if accept many, 0 otherwise + */ + int available; unsigned oneshot:1; -#if 0 - unsigned listening:1; -#endif unsigned write:1; - /* used to detect stale events in kqueue, rt signals and epoll */ + /* used to detect the stale events in kqueue, rt signals and epoll */ unsigned instance:1; /* @@ -67,12 +68,12 @@ struct ngx_event_s { /* ready event; the complete aio operation */ unsigned ready:1; + unsigned eof:1; + unsigned error:1; + unsigned timedout:1; unsigned timer_set:1; -#if 1 - unsigned blocked:1; -#endif unsigned delayed:1; unsigned read_discarded:1; @@ -87,8 +88,8 @@ struct ngx_event_s { #endif #if (HAVE_KQUEUE) - unsigned eof:1; - int error; + unsigned kq_eof:1; + int kq_errno; #endif #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ @@ -108,41 +109,27 @@ struct ngx_event_s { #if 0 - void *thr_ctx; /* event thread context if $(CC) doesn't - understand __thread declaration - and pthread_getspecific() is too costly */ + + /* the threads support */ + + /* + * the event thread context, we store it here + * if $(CC) does not understand __thread declaration + * and pthread_getspecific() is too costly + */ + + void *thr_ctx; #if (NGX_EVENT_T_PADDING) - int padding[NGX_EVENT_T_PADDING]; /* event should not cross - cache line in SMP */ + + /* event should not cross cache line in SMP */ + + int padding[NGX_EVENT_T_PADDING]; #endif #endif }; -#if 1 -typedef enum { - NGX_SELECT_EVENT_N = 0, -#if (HAVE_POLL) - NGX_POLL_EVENT_N, -#endif -#if (HAVE_DEVPOLL) - NGX_DEVPOLL_EVENT_N, -#endif -#if (HAVE_KQUEUE) - NGX_KQUEUE_EVENT_N, -#endif -#if (HAVE_AIO) - NGX_AIO_EVENT_N, -#endif -#if (HAVE_IOCP) - NGX_IOCP_EVENT_N, -#endif - NGX_DUMMY_EVENT_N /* avoid comma at end of enumerator list */ -} ngx_event_type_e ; -#endif - - typedef struct { int (*add)(ngx_event_t *ev, int event, u_int flags); int (*del)(ngx_event_t *ev, int event, u_int flags); @@ -159,6 +146,9 @@ typedef struct { } ngx_event_actions_t; +extern ngx_event_actions_t ngx_event_actions; + + /* * The event filter requires to read/write the whole data - * select, poll, /dev/poll, kqueue. @@ -243,12 +233,8 @@ typedef struct { #define NGX_ONESHOT_EVENT EV_ONESHOT #define NGX_CLEAR_EVENT EV_CLEAR -#ifndef HAVE_CLEAR_EVENT -#define HAVE_CLEAR_EVENT 1 -#endif - -#elif (HAVE_POLL) || (HAVE_DEVPOLL) +#elif (HAVE_POLL) #define NGX_READ_EVENT POLLIN #define NGX_WRITE_EVENT POLLOUT @@ -256,7 +242,16 @@ typedef struct { #define NGX_LEVEL_EVENT 0 #define NGX_ONESHOT_EVENT 1 -#else + +#elif (HAVE_DEVPOLL) + +#define NGX_READ_EVENT POLLIN +#define NGX_WRITE_EVENT POLLOUT + +#define NGX_LEVEL_EVENT 0 + + +#else /* select */ #define NGX_READ_EVENT 0 #define NGX_WRITE_EVENT 1 @@ -266,84 +261,35 @@ typedef struct { #endif /* HAVE_KQUEUE */ -#ifndef NGX_CLEAR_EVENT -#define NGX_CLEAR_EVENT 0 /* dummy */ + +#if (HAVE_IOCP_EVENT) +#define NGX_IOCP_ACCEPT 0 +#define NGX_IOCP_IO 1 #endif -#if (USE_KQUEUE) -#define ngx_init_events ngx_kqueue_init -#define ngx_process_events ngx_kqueue_process_events -#define ngx_add_event ngx_kqueue_add_event -#define ngx_del_event ngx_kqueue_del_event -#if 0 -#define ngx_add_timer ngx_kqueue_add_timer -#else -#define ngx_add_timer ngx_event_add_timer +#ifndef NGX_CLEAR_EVENT +#define NGX_CLEAR_EVENT 0 /* dummy declaration */ #endif -#define ngx_event_recv ngx_event_recv_core -#else -#define ngx_init_events (ngx_event_init[ngx_event_type]) #define ngx_process_events ngx_event_actions.process #define ngx_add_event ngx_event_actions.add #define ngx_del_event ngx_event_actions.del #define ngx_add_conn ngx_event_actions.add_conn #define ngx_del_conn ngx_event_actions.del_conn -#if 0 -#if (HAVE_IOCP_EVENT) -#define ngx_event_recv ngx_event_wsarecv -#elif (HAVE_AIO_EVENT) -#define ngx_event_recv ngx_event_aio_read -#else -#define ngx_event_recv ngx_io.recv -#define ngx_write_chain ngx_io.send_chain -#endif -#endif +#define ngx_add_timer ngx_event_add_timer +#define ngx_del_timer ngx_event_del_timer -#endif - - - - - -/* ***************************** */ #define ngx_recv ngx_io.recv #define ngx_recv_chain ngx_io.recv_chain #define ngx_write_chain ngx_io.send_chain -#define ngx_add_timer ngx_event_add_timer -#define ngx_del_timer ngx_event_del_timer - - -#if (HAVE_IOCP_EVENT) -#define NGX_IOCP_ACCEPT 0 -#define NGX_IOCP_IO 1 -#endif - -/* ***************************** */ - - - - - - -#if !(USE_KQUEUE) -extern ngx_event_actions_t ngx_event_actions; -extern ngx_event_type_e ngx_event_type; -extern int ngx_event_flags; -#endif - - - -/* ***************************** */ #define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */ - #define NGX_EVENT_CONF 0x00200000 @@ -364,8 +310,10 @@ typedef struct { } ngx_event_module_t; -extern ngx_module_t ngx_events_module; -extern ngx_module_t ngx_event_core_module; + +extern int ngx_event_flags; +extern ngx_module_t ngx_events_module; +extern ngx_module_t ngx_event_core_module; #define ngx_event_get_conf(conf_ctx, module) \ @@ -380,24 +328,10 @@ void ngx_event_acceptex(ngx_event_t *ev) int ngx_event_post_acceptex(ngx_listening_t *ls, int n); #endif -/* ***************************** */ - - - - - -ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size); -int ngx_event_close_connection(ngx_event_t *ev); - - -int ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log); -void ngx_worker(ngx_cycle_t *cycle); - - -/* ***************************** */ #include + #if (WIN32) #include #endif @@ -437,8 +371,9 @@ ngx_inline static int ngx_handle_read_ev return NGX_OK; } - if (rev->active && rev->ready) { - if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { + if (rev->active && (rev->ready || rev->eof)) { + if (ngx_del_event(rev, NGX_READ_EVENT, rev->eof ? NGX_CLOSE_EVENT : 0) + == NGX_ERROR) { return NGX_ERROR; } @@ -551,7 +486,4 @@ ngx_inline static int ngx_handle_level_w } -/* ***************************** */ - - #endif /* _NGX_EVENT_H_INCLUDED_ */ diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -98,20 +98,46 @@ int ngx_event_pipe_read_upstream(ngx_eve if (ngx_event_flags == NGX_HAVE_KQUEUE_EVENT) { - if (p->upstream->read->error) { - ngx_log_error(NGX_LOG_ERR, p->log, p->upstream->read->error, + if (p->upstream->read->available == 0) { + if (p->upstream->read->kq_eof) { + p->upstream->read->ready = 0; + p->upstream->read->eof = 0; + p->upstream_eof = 1; + p->read = 1; + + if (p->upstream->read->kq_errno) { + p->upstream->read->error = 1; + p->upstream_error = 1; + p->upstream_eof = 0; + + ngx_log_error(NGX_LOG_ERR, p->log, + p->upstream->read->kq_errno, + /* TODO: ngx_readv_chain_n */ + "readv() failed"); + } + + break; + } + } + +#if 0 + if (p->upstream->read->kq_errno) { + ngx_log_error(NGX_LOG_ERR, p->log, + p->upstream->read->kq_errno, "readv() failed"); p->upstream_error = 1; break; - } else if (p->upstream->read->eof + } else if (p->upstream->read->kq_eof && p->upstream->read->available == 0) { p->upstream_eof = 1; p->read = 1; break; } +#endif + } #endif diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -110,6 +110,13 @@ static ngx_command_t ngx_http_proxy_comm offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size), NULL}, + {ngx_string("proxy_pass_server"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, pass_server), + NULL}, + ngx_null_command }; @@ -237,19 +244,11 @@ ngx_log_debug(r->connection->log, "timer ngx_del_timer(r->connection->read); } - ngx_is_null(cl, ngx_http_proxy_create_request(p)) { + if (!(cl = ngx_http_proxy_create_request(p))) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } -#if 0 - cl = ngx_http_proxy_create_request(p); - if (cl == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } -#endif - if (r->request_hunks) { cl->next = r->request_hunks; } @@ -266,6 +265,7 @@ ngx_log_debug(r->connection->log, "timer out_ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)); if (out_ctx == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; } p->output_chain_ctx = out_ctx; @@ -288,6 +288,7 @@ ngx_log_debug(r->connection->log, "timer write_ctx = ngx_pcalloc(r->pool, sizeof(ngx_chain_write_ctx_t)); if (write_ctx == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; } out_ctx->output_ctx = write_ctx; @@ -767,7 +768,7 @@ static void ngx_http_proxy_process_upstr return; } - /* NGX_AGAIN: a header line parsing is still not complete */ + /* rc == NGX_AGAIN: a header line parsing is still not complete */ if (p->header_in->last == p->header_in->end) { ngx_log_error(NGX_LOG_ERR, rev->log, 0, @@ -835,6 +836,8 @@ static void ngx_http_proxy_send_response r = p->request; + r->headers_out.status = p->status; + r->headers_out.content_length_n = -1; r->headers_out.content_length = NULL; @@ -852,6 +855,16 @@ static void ngx_http_proxy_send_response || &ph[i] == p->headers_in.accept_ranges) { continue; } + + if (&ph[i] == p->headers_in.server && !p->lcf->pass_server) { + continue; + } + } + + if (&ph[i] == p->headers_in.content_type) { + r->headers_out.content_type = &ph[i]; + r->headers_out.content_type->key.len = 0; + continue; } ch = ngx_push_table(r->headers_out.headers); @@ -862,13 +875,26 @@ static void ngx_http_proxy_send_response *ch = ph[i]; - if (&ph[i] == p->headers_in.content_type) { - r->headers_out.content_type = ch; - r->headers_out.content_type->key.len = 0; + /* + * ngx_http_header_filter() output the following headers + * from r->headers_out.headers if they are set: + * r->headers_out.server, + * r->headers_out.date, + * r->headers_out.content_length + */ + + if (&ph[i] == p->headers_in.server) { + r->headers_out.server = ch; + continue; + } + + if (&ph[i] == p->headers_in.date) { + r->headers_out.date = ch; continue; } if (&ph[i] == p->headers_in.content_length) { + r->headers_out.content_length_n = ngx_atoi(p->headers_in.content_length->value.data, p->headers_in.content_length->value.len); @@ -877,23 +903,9 @@ static void ngx_http_proxy_send_response } } - /* STUB */ - - if (p->headers_in.server) { - r->headers_out.server = p->headers_in.server; - } - - if (!p->accel && p->headers_in.date) { - r->headers_out.date = p->headers_in.date; - } - - /* */ - /* TODO: preallocate event_pipe hunks, look "Content-Length" */ - r->headers_out.status = p->status; - rc = ngx_http_send_header(r); p->header_sent = 1; @@ -1413,6 +1425,8 @@ static void *ngx_http_proxy_create_loc_c conf->next_upstream = NGX_CONF_UNSET; + conf->pass_server = NGX_CONF_UNSET; + return conf; } @@ -1451,6 +1465,8 @@ static char *ngx_http_proxy_merge_loc_co ngx_conf_merge_path_value(conf->temp_path, prev->temp_path, "temp", 1, 2, 0, cf->pool); + ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0); + return NULL; } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -32,6 +32,8 @@ typedef struct { ssize_t temp_file_write_size; int cyclic_temp_file; + int pass_server; + int next_upstream; ngx_path_t *temp_path; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -138,7 +138,7 @@ static ngx_command_t ngx_http_core_comm NULL}, {ngx_string("sendfile"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, sendfile), @@ -173,7 +173,7 @@ static ngx_command_t ngx_http_core_comm NULL}, {ngx_string("msie_padding"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, msie_padding), diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -25,8 +25,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( { int rc, eintr, eagain; char *prev; + off_t sent, fprev; ssize_t hsize, fsize, size; - off_t sent, fprev; struct iovec *iov; struct sf_hdtr hdtr; ngx_err_t err; @@ -67,15 +67,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( if (prev == cl->hunk->pos) { iov->iov_len += cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } else { ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); iov->iov_base = cl->hunk->pos; iov->iov_len = cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } + prev = cl->hunk->last; hsize += cl->hunk->last - cl->hunk->pos; } @@ -118,14 +117,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( if (prev == cl->hunk->pos) { iov->iov_len += cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } else { ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR); iov->iov_base = cl->hunk->pos; iov->iov_len = cl->hunk->last - cl->hunk->pos; - prev = cl->hunk->last; } + + prev = cl->hunk->last; } /* @@ -182,6 +181,7 @@ ngx_log_debug(c->log, "NOPUSH"); "sendfile() sent only %qd bytes", sent); } else { + c->write->error = 1; ngx_log_error(NGX_LOG_CRIT, c->log, err, "sendfile() failed"); return NGX_CHAIN_ERROR; @@ -206,6 +206,7 @@ ngx_log_debug(c->log, "NOPUSH"); ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR"); } else { + c->write->error = 1; ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed"); return NGX_CHAIN_ERROR; } diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -6,23 +6,30 @@ ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) { + char *prev; ssize_t n; struct iovec *iov; ngx_err_t err; ngx_array_t io; -#if (NGX_SUPPRESS_WARN) + prev = NULL; iov = NULL; -#endif ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR); - /* TODO: coalesce the neighbouring chain entries */ + /* coalesce the neighbouring hunks */ while (chain) { - ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR); - iov->iov_base = chain->hunk->last; - iov->iov_len = chain->hunk->end - chain->hunk->last; + if (prev == chain->hunk->last) { + iov->iov_len += chain->hunk->end - chain->hunk->last; + + } else { + ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR); + iov->iov_base = chain->hunk->last; + iov->iov_len = chain->hunk->end - chain->hunk->last; + } + + prev = chain->hunk->end; chain = chain->next; } @@ -30,8 +37,12 @@ ngx_log_debug(c->log, "recv: %d:%d" _ io n = readv(c->fd, (struct iovec *) io.elts, io.nelts); - if (n == -1) { + if (n == 0) { + c->read->eof = 1; + + } else if (n == -1) { c->read->ready = 0; + c->read->error = 1; err = ngx_errno; if (err == NGX_EAGAIN) { diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -18,15 +18,19 @@ ssize_t ngx_unix_recv(ngx_connection_t * if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _ - rev->eof _ rev->available _ rev->error); + rev->kq_eof _ rev->available _ rev->kq_errno); if (rev->available == 0) { - if (rev->eof) { + if (rev->kq_eof) { rev->ready = 0; - if (rev->error) { - ngx_set_socket_errno(rev->error); - return ngx_unix_recv_error(rev, rev->error); + rev->eof = 1; + + if (rev->kq_errno) { + rev->error = 1; + ngx_set_socket_errno(rev->kq_errno); + return ngx_unix_recv_error(rev, rev->kq_errno); } + return 0; } else { @@ -43,8 +47,14 @@ ssize_t ngx_unix_recv(ngx_connection_t * if (n >= 0) { if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { rev->available -= n; + + /* + * rev->available can be negative here because some additional + * bytes can be received between kevent() and recv() + */ + if (rev->available <= 0) { - if (!rev->eof) { + if (!rev->kq_eof) { rev->ready = 0; } @@ -60,10 +70,15 @@ ssize_t ngx_unix_recv(ngx_connection_t * rev->ready = 0; } + if (n == 0) { + rev->eof = 1; + } + return n; } rev->ready = 0; + rev->error = 1; n = ngx_unix_recv_error(rev, ngx_socket_errno); } while (n == NGX_EINTR); @@ -89,10 +104,16 @@ ssize_t ngx_unix_recv(ngx_connection_t * if ((size_t) n < size) { rev->ready = 0; } + + if (n == 0) { + rev->eof = 1; + } + return n; } rev->ready = 0; + rev->error = 1; n = ngx_unix_recv_error(rev, ngx_socket_errno); } while (n == NGX_EINTR);