# HG changeset patch # User Igor Sysoev # Date 1049816410 0 # Node ID 59229033ae9397e157d5f43a09251e160ea4cf37 # Parent e320bf51c4e32f1b5da0d10516c973ffce53e1ac nginx-0.0.1-2003-04-08-19:40:10 import diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -36,6 +36,8 @@ ngx_log_t ngx_log; ngx_pool_t *ngx_pool; +int ngx_max_module; + int ngx_connection_counter; ngx_array_t ngx_listening_sockets; @@ -68,6 +70,11 @@ int main(int argc, char *const *argv) ngx_init_array(ngx_listening_sockets, ngx_pool, 10, sizeof(ngx_listen_t), 1); + ngx_max_module = 0; + for (i = 0; ngx_modules[i]; i++) { + ngx_modules[i]->index = ngx_max_module++; + } + ngx_memzero(&conf, sizeof(ngx_conf_t)); ngx_test_null(conf.args, ngx_create_array(ngx_pool, 10, sizeof(ngx_str_t)), 1); diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -5,6 +5,7 @@ #define NGINX_VER "nginx/0.0.1" +extern int ngx_max_module; extern int ngx_connection_counter; diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -130,7 +130,7 @@ ngx_log_debug(cf->log, "command '%s'" _ pconf = *(void **) ((char *) cf->ctx + cmd->conf); if (pconf) { - conf = pconf[ngx_modules[i]->index]; + conf = pconf[*(int *)(ngx_modules[i]->ctx)]; } } diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -31,8 +31,8 @@ #define NGX_CONF_FILE_DONE 2 -#define NGX_CORE_MODULE_TYPE 0x45524f43 /* "CORE" */ -#define NGX_CONF_MODULE_TYPE 0x464E4f43 /* "CONF" */ +#define NGX_CORE_MODULE_TYPE 0x45524F43 /* "CORE" */ +#define NGX_CONF_MODULE_TYPE 0x464E4F43 /* "CONF" */ typedef struct ngx_conf_s ngx_conf_t; 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 @@ -93,6 +93,7 @@ #include #include #include +#include #ifndef HAVE_POLL diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -4,11 +4,15 @@ #define NGX_OK 0 #define NGX_ERROR -1 -#define NGX_DONE NGX_ERROR #define NGX_AGAIN -2 +#define NGX_DONE -3 +/* #define NGX_BUSY -3 +*/ #define NGX_DECLINED -4 +/* #define NGX_ALERT -5 +*/ #define NGX_MAXHOSTNAMELEN 32 diff --git a/src/core/ngx_modules.c b/src/core/ngx_modules.c --- a/src/core/ngx_modules.c +++ b/src/core/ngx_modules.c @@ -4,28 +4,32 @@ #include -extern ngx_module_t ngx_http_header_filter_module; +extern ngx_module_t ngx_http_module; +extern ngx_module_t ngx_http_core_module; extern ngx_module_t ngx_http_write_filter_module; extern ngx_module_t ngx_http_output_filter_module; +extern ngx_module_t ngx_http_header_filter_module; -extern ngx_module_t ngx_http_core_module; extern ngx_module_t ngx_http_index_module; - -extern ngx_module_t ngx_http_module; +extern ngx_module_t ngx_http_proxy_module; ngx_module_t *ngx_modules[] = { - &ngx_http_header_filter_module, + &ngx_http_module, + &ngx_http_core_module, &ngx_http_write_filter_module, &ngx_http_output_filter_module, + &ngx_http_header_filter_module, + + /* &ngx_http_gzip_filter_module, */ + /* &ngx_http_range_filter_module, */ + /* &ngx_http_ssi_filter_module, */ &ngx_http_index_module, - &ngx_http_core_module, - - &ngx_http_module, + &ngx_http_proxy_module, NULL }; 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 @@ -35,13 +35,13 @@ static ngx_command_t ngx_http_index_comm ngx_http_module_t ngx_http_index_module_ctx = { + NGX_HTTP_MODULE, + NULL, /* create server config */ NULL, /* init server config */ ngx_http_index_create_conf, /* create location config */ - ngx_http_index_merge_conf, /* merge location config */ - - NULL /* init filters */ + ngx_http_index_merge_conf /* merge location config */ }; @@ -74,10 +74,10 @@ int ngx_http_index_handler(ngx_http_requ ngx_http_core_loc_conf_t *core_cf; cf = (ngx_http_index_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_index_module); + ngx_http_get_module_loc_conf(r, ngx_http_index_module_ctx); core_cf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); ngx_test_null(r->path.data, ngx_palloc(r->pool, diff --git a/src/http/modules/ngx_http_event_proxy_handler.c b/src/http/modules/proxy/ngx_http_event_proxy_handler.c rename from src/http/modules/ngx_http_event_proxy_handler.c rename to src/http/modules/proxy/ngx_http_event_proxy_handler.c --- a/src/http/modules/ngx_http_event_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_event_proxy_handler.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -14,25 +15,44 @@ #include -static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r); -static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p, - struct sockaddr_in *addr, - char *addr_text); -static int ngx_http_proxy_send_request(ngx_event_t *ev); +static int ngx_http_proxy_handler(ngx_http_request_t *r); -static int ngx_http_proxy_init_response(ngx_event_t *ev); -static int ngx_http_proxy_read_response_header(ngx_event_t *ev); -static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, - ngx_http_proxy_ctx_t *p); +static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); +static int ngx_http_proxy_process_upstream(ngx_http_proxy_ctx_t *p, + ngx_event_t *ev); +static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p); +static int ngx_http_proxy_process_upstream_event(ngx_event_t *ev); +static int ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); +static int ngx_http_proxy_init_upstream(ngx_http_proxy_ctx_t *p); +static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p); +static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p); + static int ngx_http_proxy_read_response_body(ngx_event_t *ev); static int ngx_http_proxy_write_to_client(ngx_event_t *ev); static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx); +static int ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int error); +static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); + +static void *ngx_http_proxy_create_loc_conf(ngx_pool_t *pool); + +static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, + char *conf); + +static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, + ngx_http_proxy_upstream_url_t *uu); + static ngx_command_t ngx_http_proxy_commands[] = { + {ngx_string("proxy_pass"), + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_proxy_set_pass, + NGX_HTTP_LOC_CONF_OFFSET, + 0}, + {ngx_string("proxy_large_header"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, @@ -44,13 +64,13 @@ static ngx_command_t ngx_http_proxy_com static ngx_http_module_t ngx_http_proxy_module_ctx = { + NGX_HTTP_MODULE, + NULL, /* create server config */ NULL, /* init server config */ - NULL, /* create location config */ - NULL, /* merge location config */ - - NULL /* init filters */ + ngx_http_proxy_create_loc_conf, /* create location config */ + NULL /* merge location config */ }; @@ -78,24 +98,35 @@ static char conn_close_header[] = "Conne /* AF_INET only */ -int ngx_http_proxy_handler(ngx_http_request_t *r) +static int ngx_http_proxy_handler(ngx_http_request_t *r) { - struct sockaddr_in addr; - ngx_chain_t *chain; - ngx_http_proxy_ctx_t *p; - ngx_http_log_ctx_t *hcx; - ngx_http_proxy_log_ctx_t *lcx; + int rc; + struct sockaddr_in addr; + ngx_chain_t *chain; + ngx_http_proxy_ctx_t *p; + ngx_http_log_ctx_t *hcx; + ngx_http_proxy_log_ctx_t *lcx; + ngx_http_proxy_loc_conf_t *lcf; p = (ngx_http_proxy_ctx_t *) - ngx_http_get_module_ctx(r, ngx_http_proxy_module); + ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); if (p == NULL) { - ngx_http_create_ctx(r, p, ngx_http_proxy_module, + ngx_http_create_ctx(r, p, ngx_http_proxy_module_ctx, sizeof(ngx_http_proxy_ctx_t), NGX_HTTP_INTERNAL_SERVER_ERROR); } - p->request = r; + if (p->upstream_url == NULL) { + lcf = (ngx_http_proxy_loc_conf_t *) + ngx_http_get_module_loc_conf(r, ngx_http_proxy_module_ctx); + + p->lcf = lcf; + p->request = r; + p->upstream_url = lcf->upstream_url; + p->upstreams = lcf->upstreams; + p->tries = lcf->upstreams->number; + } ngx_test_null(p->log, ngx_palloc(r->pool, sizeof(ngx_log_t)), NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -106,56 +137,55 @@ int ngx_http_proxy_handler(ngx_http_requ p->log->data = lcx; hcx = r->connection->log->data; lcx->client = hcx->client; + lcx->url = hcx->url; - /* - if (!resolved) { - return ngx_dns_resolve(name, handler, p, r->pool, p->log); - } - */ + p->method = r->method; - chain = ngx_http_proxy_create_request(r); + /* TODO: read a client's body */ + + chain = ngx_http_proxy_create_request(p); if (chain == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } - /* TODO: duplicate hunks and chain if there is backend farm */ + /* TODO: duplicate the hunks and chain if there is backend farm */ p->out = chain; - ngx_memzero(&addr, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; -#if 0 - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); -#else - addr.sin_addr.s_addr = inet_addr("192.168.10.2"); -#endif - addr.sin_port = htons(9000); + p->last_error = NGX_HTTP_BAD_GATEWAY; + ngx_http_proxy_process_upstream(p, NULL); - return ngx_http_proxy_connect(p, &addr, "connecting to 127.0.0.1:9000"); + /* On an error ngx_http_proxy_process_upstream() calls + ngx_http_proxy_finalize_request() so we return NGX_DONE to avoid + the additional NGX_HTTP_INTERNAL_SERVER_ERROR error + that would be generated by ngx_http_process_request() */ + + return NGX_DONE; } -static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r) +static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) { - int i; - size_t len; - ngx_hunk_t *hunk; - ngx_chain_t *chain; - ngx_table_elt_t *header; + int i; + size_t len; + ngx_hunk_t *hunk; + ngx_chain_t *chain; + ngx_table_elt_t *header; + ngx_http_request_t *r; - /* 2 is for "\r\n" after request line - and 2 is for "\r\n" at the header end */ - - /* STUB: "method p->url HTTP/1.0" length */ + r = p->request; - len = r->request_line.len + 2 + 2; - - /* TODO: Host length */ - - /* "Connection: close\r\n" */ - len += sizeof(conn_close_header) - 1; + len = http_methods[p->method - 1].len + + p->upstream_url->uri.len + + (r->uri.len - p->upstream_url->location->len) + + r->args.len + 1 /* 1 is for "?" */ + + sizeof(http_version) - 1 + + sizeof(host_header) - 1 + p->upstream_url->host.len + 2 + + sizeof(conn_close_header) - 1 + + 2; /* 2 is for "\r\n" at the header end */ header = (ngx_table_elt_t *) r->headers_in.headers->elts; for (i = 0; i < r->headers_in.headers->nelts; i++) { + if (&header[i] == r->headers_in.host) { continue; } @@ -173,56 +203,46 @@ static ngx_chain_t *ngx_http_proxy_creat ngx_test_null(hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL); ngx_add_hunk_to_chain(chain, hunk, r->pool, NULL); -#if 0 - /* the request line */ ngx_memcpy(hunk->last, http_methods[p->method - 1].data, http_methods[p->method - 1].len); hunk->last += http_methods[p->method - 1].len; - ngx_memcpy(hunk->last, p->uri_start.data, p->uri_start.len); - hunk->last += p->uri_start.len; + ngx_memcpy(hunk->last, p->upstream_url->uri.data, p->upstream_url->uri.len); + hunk->last += p->upstream_url->uri.len; - ngx_memcpy(hunk->last, p->uri_rest.data, p->uri_rest.len); - hunk->last += p->uri_rest.len; + ngx_memcpy(hunk->last, r->uri.data + p->upstream_url->location->len, + r->uri.len - p->upstream_url->location->len); + hunk->last += r->uri.len - p->upstream_url->location->len; - if (r->args) { + if (r->args.len > 0) { *(hunk->last++) = '?'; - ngx_memcpy(hunk->last, r->uri_args.data, r->uri_args.len); - hunk->last += r->uri_args.len; + ngx_memcpy(hunk->last, r->args.data, r->args.len); + hunk->last += r->args.len; } ngx_memcpy(hunk->last, http_version, sizeof(http_version) - 1); hunk->last += sizeof(http_version) - 1; - /* the 'Host' header */ + /* the "Host" header */ ngx_memcpy(hunk->last, host_header, sizeof(host_header) - 1); hunk->last += sizeof(host_header) - 1; - ngx_memcpy(hunk->last, p->host.data, p->host.len); - hunk->last += p->host.len; + ngx_memcpy(hunk->last, p->upstream_url->host.data, + p->upstream_url->host.len); + hunk->last += p->upstream_url->host.len; *(hunk->last++) = CR; *(hunk->last++) = LF; - /* the 'Connection: close' header */ + /* the "Connection: close" header */ ngx_memcpy(hunk->last, conn_close_header, sizeof(conn_close_header) - 1); hunk->last += sizeof(conn_close_header) - 1; -#else - - ngx_memcpy(hunk->last, r->request_line.data, r->request_line.len); - hunk->last += r->request_line.len; - *(hunk->last++) = CR; *(hunk->last++) = LF; + for (i = 0; i < r->headers_in.headers->nelts; i++) { - ngx_memcpy(hunk->last, conn_close_header, sizeof(conn_close_header) - 1); - hunk->last += sizeof(conn_close_header) - 1; - -#endif - - for (i = 0; i < r->headers_in.headers->nelts; i++) { if (&header[i] == r->headers_in.host) { continue; } @@ -255,112 +275,191 @@ static ngx_chain_t *ngx_http_proxy_creat } -#if 0 +static int ngx_http_proxy_process_upstream(ngx_http_proxy_ctx_t *p, + ngx_event_t *ev) +{ + int rc; + time_t now; + ngx_connection_t *c; + ngx_http_proxy_upstream_t *u; -client_read() - if (!ev->write) { - if error close upstream ? - else block it - } + for ( ;; ) { - -static int ngx_http_proxy_process_upstream(ngx_event_t *ev) -{ - again = 0; + if (ev == NULL) { + /* STUB: look up cached connection */ + c = NULL; - do { + if (c) { + p->cached_connection = 1; + p->connection = c; + c->write->event_handler = ngx_http_proxy_process_upstream_event; + rc = ngx_http_proxy_send_request(p); - if (p->state_write_upstream_handler == - ngx_http_proxy_connect_to_upstream) { - if (!get_cached_connection()) - get_next_upstream(p); - } + } else { + p->cached_connection = 0; + p->connection = NULL; + rc = ngx_http_proxy_connect(p); + } - if (ev->write) { - - /* ngx_http_proxy_connect_to_upstream() - ngx_http_proxy_send_request() */ - - rc = p->state_write_upstream_handler(p); + if (p->connection) { + ev = p->connection->write; + } } else { - /* ngx_http_proxy_read_response() */ + if (ev->timedout) { + rc = NGX_HTTP_GATEWAY_TIME_OUT; + + } else if (ev->write) { - rc = p->state_read_upstream_handler(p); + rc = p->state_write_upstream_handler(p); + + } else { /* ev->read */ + + rc = p->state_read_upstream_handler(p); + } } - if (rc == NGX_BUSY || rc == NGX_AGAIN || rc == NGX_OK) { + if (rc == NGX_DONE || rc == NGX_AGAIN) { return rc; } if (rc == NGX_ERROR) { return ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_DONE; } - /* This NGX_HTTP_INTERNAL_SERVER_ERROR is sent by an upstream */ - if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT - || (rc == NGX_HTTP_INTERNAL_SERVER_ERROR && lcf->retry_500) + || (rc == NGX_OK + && p->status == NGX_HTTP_INTERNAL_SERVER_ERROR + && p->lcf->retry_500_error)) { - ngx_http_close_connection(ev); - - if (p->upstream->amount > 1) { - /* Here is the race condition on SMP machine - when the upstreams are shared between threads or processes - but it's not serious */ - p->upstream->upstreams[p->cur_upstream].fails++; + if (ev) { + ngx_event_close_connection(ev); + ev = NULL; } - p->upstreams--; + if (!p->cached_connection) { + if (p->upstreams->number > 1) { + now = ngx_time(); + u = &p->upstreams->u[p->cur_upstream]; + + /* Here is the race condition when the upstreams are shared + between threads or processes but it's not serious */ - if (p->upstreams == 0) { - return ngx_http_proxy_finalize_request(p, rc); - } + u->fails++; + u->accessed = now; - p->cur_upstream++; - if (p->cur_upstream > p->upstream->amount) { - p->cur_upstream = 0; + /* */ + } + + p->tries--; + p->last_error = rc; } - p->state_read_upstream_handler = ignore; - p->state_write_upstream_handler = - ngx_http_proxy_connect_to_upstream; - again = 1; + if (p->tries == 0) { + ngx_http_proxy_finalize_request(p, p->last_error); + return NGX_ERROR; + } } - if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { - ??? + if (rc == NGX_OK) { + ngx_http_proxy_finalize_request(p, p->status); + return NGX_DONE; } - } while (again); + if (rc > NGX_OK) { + ngx_http_proxy_finalize_request(p, rc); + } - return NGX_BUSY; + return NGX_DONE; + } } static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) { - ngx_socket_t s; - ngx_connection_t *c; - ngx_http_log_ctx_t *lcx; + int rc, event; + struct sockaddr_in *addr; + ngx_err_t err; + ngx_socket_t s; + ngx_event_t *rev, *wev; + ngx_connection_t *c; + ngx_http_proxy_log_ctx_t *lcx; + ngx_http_proxy_upstream_t *u; + + if (p->upstreams->number > 1) { + if (p->tries == p->upstreams->number) { + + /* Here is the race condition + when the upstreams are shared between threads or processes + but it should not be serious */ + + p->cur_upstream = p->upstreams->current++; + + if (p->upstreams->current >= p->upstreams->number) { + p->upstreams->current = 0; + } + + /* */ + +#if (NGX_MULTITHREADED || NGX_MULTIPROCESSED) + /* eliminate the sequences of the race condition */ + if (p->cur_upstream >= p->upstreams->number) { + p->cur_upstream = 0; + } +#endif + } + + if (p->upstreams->max_fails > 0) { + + for ( ;; ) { + u = &p->upstreams->u[p->cur_upstream]; + + /* Here is the race condition + when the upstreams are shared between threads or processes + but it should not be serious */ + + if (u->fails > p->upstreams->max_fails + || u->accessed < p->upstreams->fail_timeout) + { + break; + } + + /* */ + + p->cur_upstream++; + + if (p->cur_upstream >= p->upstreams->number) { + p->cur_upstream = 0; + } + + p->tries--; + + if (p->tries == 0) { + return p->last_error; + } + } + } + } lcx = p->log->data; lcx->action = "connecting to an upstream"; - lcx->upstream = p->upstream.data; + lcx->upstream = p->upstreams->u[p->cur_upstream].addr_port_name.data; p->log->handler = ngx_http_proxy_log_error; s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); + if (s == -1) { ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, ngx_socket_n " failed"); return NGX_ERROR; } - if (lcf->rcvbuf) { + if (p->lcf->rcvbuf) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, - (const void *) &rcvbuf, sizeof(int)) == -1) { + (const void *) &p->lcf->rcvbuf, sizeof(int)) == -1) { ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, "setsockopt(SO_RCVBUF) failed"); @@ -385,7 +484,51 @@ static int ngx_http_proxy_connect(ngx_ht return NGX_ERROR; } - rc = connect(s, (struct sockaddr *) p->addr, sizeof(struct sockaddr_in)); + c = &ngx_connections[s]; + rev = &ngx_read_events[s]; + wev = &ngx_write_events[s]; + + ngx_memzero(c, sizeof(ngx_connection_t)); + ngx_memzero(rev, sizeof(ngx_event_t)); + ngx_memzero(wev, sizeof(ngx_event_t)); + + rev->index = wev->index = NGX_INVALID_INDEX; + rev->data = wev->data = c; + c->read = rev; + c->write = wev; + rev->first = wev->first = 1; + rev->log = wev->log = c->log = p->log; + c->fd = s; + wev->close_handler = rev->close_handler = ngx_event_close_connection; + +#if !(USE_KQUEUE) + +#if (HAVE_EDGE_EVENT) /* epoll */ + + if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { + if (ngx_edge_add_event(wev) != NGX_OK) { + return NGX_ERROR; + } + } + +#endif + +#endif + + ngx_test_null(c->pool, ngx_create_pool(p->lcf->conn_pool_size, p->log), + NGX_ERROR); + + ngx_test_null(p->sockaddr, + ngx_pcalloc(c->pool, sizeof(struct sockaddr_in)), + NGX_ERROR); + + addr = (struct sockaddr_in *) p->sockaddr; + + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = p->upstreams->u[p->cur_upstream].addr; + addr->sin_port = htons(p->upstreams->u[p->cur_upstream].port); + + rc = connect(s, p->sockaddr, sizeof(struct sockaddr_in)); if (rc == -1) { err = ngx_socket_errno; @@ -397,210 +540,89 @@ static int ngx_http_proxy_connect(ngx_ht ngx_close_socket_n " failed"); } - return NGX_HTTP_BAD_GATEWAY; - } - } - - c = &ngx_connections[s]; - rev = &ngx_read_events[s]; - wev = &ngx_write_events[s]; - - ngx_memzero(rev, sizeof(ngx_event_t)); - ngx_memzero(wev, sizeof(ngx_event_t)); - ngx_memzero(c, sizeof(ngx_connection_t)); - - rev->index = wev->index = NGX_INVALID_INDEX; - - rev->data = wev->data = c; - c->read = rev; - c->write = wev; - - rev->first = wev->first = 1; - - c->data = p->request; - p->connection = c; - - c->fd = s; - - rev->log = wev->log = c->log = p->log; - - ngx_test_null(c->pool, ngx_create_pool(lcf->conn_pool_size, p->log), - NGX_ERROR); - -} - -#if 0 -connect_upstream() - get next upstream - init connect to upstream - if error return error - if ok send_request(); - if inprogress p->state_handler = send_request, return busy - -send_request() - if timeout inc fail counter - p->state_handler = connect_upstream, return 504 -#endif - -#endif - - -static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p, - struct sockaddr_in *addr, - char *addr_text) -{ - int rc, event; - ngx_err_t err; - ngx_socket_t s; - ngx_event_t *rev, *wev; - ngx_connection_t *c, *pc; - ngx_http_log_ctx_t *ctx; - - c = p->request->connection; - ctx = c->log->data; - ctx->action = addr_text; - - s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); - if (s == -1) { - ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, - ngx_socket_n " failed"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - -#if 0 - if (rcvbuf) { - if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (const void *) &rcvbuf, sizeof(int)) == -1) { - ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, - "setsockopt(SO_RCVBUF) failed"); - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, - ngx_close_socket_n " failed"); - } - - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - } -#endif - - if (ngx_nonblocking(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, - ngx_nonblocking_n " failed"); - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, - ngx_close_socket_n " failed"); - } - - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - rc = connect(s, (struct sockaddr *) addr, sizeof(struct sockaddr_in)); - - if (rc == -1) { - err = ngx_socket_errno; - if (err != NGX_EINPROGRESS) { - ngx_log_error(NGX_LOG_CRIT, c->log, err, "connect() failed"); - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, - ngx_close_socket_n " failed"); - } + ngx_destroy_pool(c->pool); return NGX_HTTP_BAD_GATEWAY; } } - pc = &ngx_connections[s]; - rev = &ngx_read_events[s]; - wev = &ngx_write_events[s]; - - ngx_memzero(rev, sizeof(ngx_event_t)); - ngx_memzero(wev, sizeof(ngx_event_t)); - ngx_memzero(pc, sizeof(ngx_connection_t)); - - rev->index = wev->index = NGX_INVALID_INDEX; - - rev->data = wev->data = pc; - pc->read = rev; - pc->write = wev; + c->data = p->request; + p->connection = c; - pc->data = p->request;; - p->connection = pc; - - pc->fd = s; - pc->servers = c->servers; - - ngx_test_null(pc->log, ngx_palloc(c->pool, sizeof(ngx_log_t)), NGX_OK); - ngx_memcpy(pc->log, c->log, sizeof(ngx_log_t)); - rev->log = wev->log = pc->log; - - ngx_test_null(pc->pool, - ngx_create_pool(/* STUB */ 1024 /**/, pc->log), - NGX_HTTP_INTERNAL_SERVER_ERROR); - - wev->event_handler = ngx_http_proxy_send_request; - rev->event_handler = ngx_http_proxy_init_response; - rev->close_handler = wev->close_handler = ngx_event_close_connection; - + ngx_test_null(c->pool, ngx_create_pool(p->lcf->conn_pool_size, p->log), + NGX_ERROR); #if (USE_KQUEUE) if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } #else -#if (HAVE_CLEAR_EVENT) /* kqueue */ + if ((ngx_event_flags & NGX_HAVE_EDGE_EVENT) == 0) { /* not epoll */ - if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { - event = NGX_CLEAR_EVENT; - - } else { - event = NGX_LEVEL_EVENT; - } + if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { /* kqueue */ + event = NGX_CLEAR_EVENT; -#else /* select, poll, /dev/poll */ - - event = NGX_LEVEL_EVENT; + } else { /* select, poll, /dev/poll */ + event = NGX_LEVEL_EVENT; + } -#endif + /* TODO: aio, iocp */ - if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { + return NGX_ERROR; + } } #endif /* USE_KQUEUE */ - /* TODO: aio, iocp */ + wev->event_handler = rev->event_handler = + ngx_http_proxy_process_upstream_event; + + p->state_write_upstream_handler = ngx_http_proxy_send_request; + p->state_read_upstream_handler = ngx_http_proxy_init_upstream; /* The connection has been established */ if (rc == 0) { wev->write = 1; wev->ready = 1; - return ngx_http_proxy_send_request(wev); + return ngx_http_proxy_send_request(p); } /* The connection is in a progress */ - /* TODO: oneshot */ - if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + wev->timer_set = 1; + ngx_add_timer(wev, p->lcf->connect_timeout); + +#if (USE_KQUEUE) + + if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { + return NGX_ERROR; } - wev->timer_set = 1; - ngx_add_timer(wev, /* STUB: lcf->connect_timeout */ 10000); +#else + + /* TODO: aio, iocp */ + + if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) { + return NGX_DONE; + } - return NGX_BUSY; + if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) { + return NGX_ERROR; + } + +#endif /* USE_KQUEUE */ + + return NGX_DONE; } -static int ngx_http_proxy_send_request(ngx_event_t *ev) +static int ngx_http_proxy_process_upstream_event(ngx_event_t *ev) { - ngx_chain_t *chain; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_proxy_ctx_t *p; @@ -608,210 +630,181 @@ static int ngx_http_proxy_send_request(n c = (ngx_connection_t *) ev->data; r = (ngx_http_request_t *) c->data; p = (ngx_http_proxy_ctx_t *) - ngx_http_get_module_ctx(r, ngx_http_proxy_module); + ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); + + return ngx_http_proxy_process_upstream(p, ev); +} + - if (ev->timedout) { - return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); - } +static int ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) +{ + ngx_chain_t *chain; + ngx_event_t *wev; - chain = ngx_write_chain(c, p->out, 0); + chain = ngx_write_chain(p->connection, p->out, 0); if (chain == (ngx_chain_t *) -1) { return NGX_ERROR; } p->out = chain; - return NGX_BUSY; + wev = p->connection->write; + + ngx_del_timer(wev); + + if (chain) { + ngx_add_timer(wev, p->lcf->send_timeout); + wev->timer_set = 1; + + } else { + wev->timer_set = 0; + } + + return NGX_DONE; } -static int ngx_http_proxy_init_response(ngx_event_t *ev) +static int ngx_http_proxy_init_upstream(ngx_http_proxy_ctx_t *p) { - int n; - ngx_hunk_t **ph; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_proxy_ctx_t *p; + int n; + ngx_hunk_t **ph; + ngx_http_request_t *r; - c = (ngx_connection_t *) ev->data; - r = (ngx_http_request_t *) c->data; - - if (ev->timedout) { - return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); - } - - p = (ngx_http_proxy_ctx_t *) - ngx_http_get_module_ctx(r, ngx_http_proxy_module); + r = p->request; ngx_test_null(p->header_in, - ngx_create_temp_hunk(r->pool, - /* STUB */ 1024 /**/, 0, 0), - ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR)); + ngx_create_temp_hunk(r->pool, p->lcf->header_size, 0, 0), + NGX_ERROR); p->header_in->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; ngx_test_null(p->headers_in, ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)), - ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR)); + NGX_ERROR); - ngx_init_array(p->hunks, r->pool, - /* STUB */ 10 /**/, - sizeof(ngx_hunk_t *), - ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR)); + p->hunks_number = p->lcf->max_block_size / p->lcf->block_size; + if (p->hunks_number * p->lcf->block_size < p->lcf->max_block_size) { + p->hunks_number++; + } + + ngx_init_array(p->hunks, r->pool, p->hunks_number, sizeof(ngx_hunk_t *), + NGX_ERROR); ngx_test_null(ph, ngx_push_array(&p->hunks), NGX_ERROR); *ph = p->header_in; - p->state_handler = ngx_http_proxy_process_status_line; + p->state_handler = ngx_http_proxy_process_upstream_status_line; - return ngx_http_proxy_read_response_header(ev); + return ngx_http_proxy_read_upstream_header(p); } -static int ngx_http_proxy_read_response_header(ngx_event_t *ev) +static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) { - int n; - ngx_hunk_t **ph; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_proxy_ctx_t *p; - ngx_http_proxy_loc_conf_t *lcf; + int n, rc; + ngx_event_t *rev; - c = (ngx_connection_t *) ev->data; - r = (ngx_http_request_t *) c->data; - p = (ngx_http_proxy_ctx_t *) - ngx_http_get_module_ctx(r, ngx_http_proxy_module); - - if (ev->timedout) { - return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); - } - - lcf = (ngx_http_proxy_loc_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); - - -#if 0 + rev = p->connection->read; do { - n = ngx_event_recv(c, p->header_in->last, - p->header_in->end - p->header_in->last; + n = ngx_event_recv(p->connection, p->header_in->last, + p->header_in->end - p->header_in->last); if (n == NGX_AGAIN) { - if (ev->timer_set) { - ngx_del_timer(ev); + if (rev->timer_set) { + ngx_del_timer(rev); } else { - ev->timer_set = 1; + rev->timer_set = 1; } - ngx_add_timer(ev, lcf->timeout); + ngx_add_timer(rev, p->lcf->read_timeout); return NGX_AGAIN; } if (n == NGX_ERROR) { - ngx_http_proxy_close_request(r, p); - return ngx_http_error(r, NGX_HTTP_BAD_GATEWAY); + return NGX_HTTP_BAD_GATEWAY; } - ngx_log_debug(c->log, "http proxy read %d" _ n); + ngx_log_debug(p->log, "http proxy read %d" _ n); if (n == 0) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client has prematurely closed connection"); - ngx_http_proxy_close_request(r, p); + ngx_log_error(NGX_LOG_INFO, p->log, 0, + "upstream closed prematurely connection"); + return NGX_HTTP_BAD_GATEWAY; } p->header_in->last += n; - if (lcf->large_header && p->header_in->end == p->header_in->last) { - again = 1; - } else { - again = 0; - } - - - - -#if (HAVE_AIO_EVENT) /* aio, iocp */ - - if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { - again = 1; - } - -#endif - - } while (rc == NGX_AGAIN && again); - -#endif + /* the state handlers are called in the following order: + ngx_http_proxy_process_upstream_status_line(r) + ngx_http_proxy_process_upstream_headers(r) */ - n = ngx_event_recv(c, p->header_in->last, - p->header_in->end - p->header_in->last); - - ngx_log_debug(c->log, "READ:%d" _ n); - - p->header_in->last += n; + do { + rc = p->state_handler(p); + } while (rc == NGX_AGAIN && p->header_in->end < p->header_in->last); - /* STUB */ - *p->header_in->last = '\0'; - ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos); - /**/ + } while (rc == NGX_AGAIN + && (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT)); - if (n == 0) { - ngx_log_debug(c->log, "CLOSE proxy"); -#if 0 - ngx_del_event(ev, NGX_READ_EVENT, NGX_CLOSE_EVENT); -#endif - ngx_event_close_connection(ev); - - p->hunk_n = 0; - c->write->event_handler = ngx_http_proxy_write_to_client; - return ngx_http_proxy_write_to_client(c->write); + if (rc > NGX_OK) { + return rc; } - /* state_handlers are called in following order: - ngx_http_proxy_process_status_line(r, p) - ngx_http_proxy_process_reponse_header(r, p) */ - -#if 0 - do { - rc = (p->state_handler)(r, p); - - if (rc == NGX_ERROR) { - return rc; - } - - /* rc == NGX_OK || rc == NGX_AGAIN */ - - } while (p->header_in->pos.mem < p->header_in->last.mem); -#endif - - ev->event_handler = ngx_http_proxy_read_response_body; - if (p->header_in->end - p->header_in->last == 0) { - return ngx_http_proxy_read_response_body(ev); + if (rc == NGX_OK) { + /* STUB */ return NGX_ERROR; } - return NGX_BUSY; + /* STUB */ return NGX_ERROR; } -static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, - ngx_http_proxy_ctx_t *p) +static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p) { int rc; +#if 0 + *p->header_in->last = '\0'; + ngx_log_debug(p->log, "PROXY:\n'%s'" _ p->header_in->pos); +#endif + rc = ngx_read_http_proxy_status_line(p); if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { p->status = 200; + p->status_line.len = 0; + p->full_status_line.len = 0; } if (rc == NGX_OK) { - /* STUB */ - ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); + p->status_line.len = p->status_end - p->status_start; + p->full_status_line.len = p->status_end - p->header_in->start; + + if (p->lcf->large_header) { + ngx_test_null(p->full_status_line.data, + ngx_palloc(p->request->pool, + p->full_status_line.len + 1), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + ngx_cpystrn(p->full_status_line.data, p->header_in->start, + p->full_status_line.len + 1); + + if (p->header_in->pos == p->header_in->end) { + p->header_in->pos = p->header_in->last = p->header_in->start; + } + + } else { + p->status_line.data = p->status_start; + p->full_status_line.data = p->header_in->start; + *p->status_end = '\0'; + } + + ngx_log_debug(p->log, "upstream status: %d, '%s'" _ + p->status _ p->full_status_line.data); p->state_handler = NULL; } - if (p->header_in->last >= p->header_in->end) { + if (p->header_in->last == p->header_in->end) { rc = NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE; } else if (rc == NGX_AGAIN) { @@ -822,6 +815,14 @@ static int ngx_http_proxy_process_status } + + + + + + + + #if 0 static int ngx_http_proxy_process_response_header(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p) @@ -848,7 +849,7 @@ static int ngx_http_proxy_read_response_ c = (ngx_connection_t *) ev->data; r = (ngx_http_request_t *) c->data; p = (ngx_http_proxy_ctx_t *) - ngx_http_get_module_ctx(r, ngx_http_proxy_module); + ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); if (p->hunks.nelts > 0) { h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1]; @@ -904,7 +905,7 @@ static int ngx_http_proxy_read_response_ ngx_log_debug(c->log, "READ:%d" _ n); if (n == NGX_AGAIN) { - return NGX_BUSY; + return NGX_DONE; } if (n == NGX_ERROR) { @@ -933,7 +934,7 @@ static int ngx_http_proxy_read_response_ return ngx_http_proxy_write_to_client(c->write); } - /* STUB */ return NGX_BUSY; + /* STUB */ return NGX_DONE; } @@ -948,7 +949,7 @@ static int ngx_http_proxy_write_to_clien c = (ngx_connection_t *) ev->data; r = (ngx_http_request_t *) c->data; p = (ngx_http_proxy_ctx_t *) - ngx_http_get_module_ctx(r, ngx_http_proxy_module); + ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); do { h = ((ngx_hunk_t **) p->hunks.elts)[p->hunk_n]; @@ -970,13 +971,19 @@ static int ngx_http_proxy_write_to_clien } +static int ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int error) +{ + return ngx_http_finalize_request(p->request, error); +} + + static int ngx_http_proxy_error(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p, int error) { ngx_event_close_connection(p->connection->read); return ngx_http_error(r, error); -} +} static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) @@ -1085,7 +1092,7 @@ static int ngx_read_http_proxy_status_li if (++ctx->status_count == 3) { state = sw_space_after_status; - ctx->status_line = p - 3; + ctx->status_start = p - 3; } break; @@ -1121,7 +1128,7 @@ static int ngx_read_http_proxy_status_li /* end of request line */ case sw_almost_done: - ctx->request_end = p - 2; + ctx->status_end = p - 2; switch (ch) { case LF: state = sw_done; @@ -1136,8 +1143,8 @@ static int ngx_read_http_proxy_status_li ctx->header_in->pos = p; if (state == sw_done) { - if (ctx->request_end == NULL) { - ctx->request_end = p - 1; + if (ctx->status_end == NULL) { + ctx->status_end = p - 1; } ctx->state = sw_start; @@ -1150,43 +1157,73 @@ static int ngx_read_http_proxy_status_li } -#if 0 +static void *ngx_http_proxy_create_loc_conf(ngx_pool_t *pool) +{ + ngx_http_proxy_loc_conf_t *conf; + + ngx_test_null(conf, + ngx_pcalloc(pool, sizeof(ngx_http_proxy_loc_conf_t)), + NULL); + + /* STUB */ + conf->conn_pool_size = 16384; + conf->connect_timeout = 10000; + conf->send_timeout = 10000; + conf->read_timeout = 10000; + conf->header_size = 1024; + conf->block_size = 4096; + conf->max_block_size = 32768; + /**/ + + return conf; +} + static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, char *conf) { - ngx_http_proxy_conf_t *lcf = (ngx_http_proxy_conf_t *) conf; - char *url; - struct hostent *h; - ngx_str_t *value; - ngx_http_proxy_pass_t *pass; + ngx_http_proxy_loc_conf_t *lcf = (ngx_http_proxy_loc_conf_t *) conf; + + int i, s, len; + char *err, *host; + struct hostent *h; + u_int32_t addr; + ngx_str_t *value; + ngx_http_conf_ctx_t *ctx; + ngx_http_core_loc_conf_t *core_lcf; value = (ngx_str_t *) cf->args->elts; - url = value[1].data; - ngx_test_null(pass, ngx_push_array(lcf->proxy_pass), NGX_CONF_ERROR); - - if (ngx_strncasecmp(url, "http://", 7) == 0) { - /* STUB: "invalid prefix in URL %s", url */ - return "invalid prefix"; + if (ngx_strncasecmp(value[1].data, "http://", 7) != 0) { + return "invalid URL prefix"; } - err = ngx_http_proxy_parse_upstream(url, u); + ngx_test_null(lcf->upstream_url, + ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_url_t)), + NGX_CONF_ERROR); + + value[1].data += 7; + value[1].len -= 7; + + err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream_url); if (err) { - /* STUB: "%s %s", err, url */ return err; } - if (u.port == 0) { - u.port = 80; + if (lcf->upstream_url->port == 0) { + lcf->upstream_url->port = 80; } - ngx_test_null(host, ngx_palloc(cf->pool, u.host.len + 1), NGX_CONF_ERROR); - ngx_cpystr(host, u.host.data, u.host.len + 1); + ngx_test_null(host, ngx_palloc(cf->pool, lcf->upstream_url->host.len + 1), + NGX_CONF_ERROR); + ngx_cpystrn(host, lcf->upstream_url->host.data, + lcf->upstream_url->host.len + 1); - addr.sin_addr.s_addr = inet_addr(host); - if (addr.sin_addr.s_addr == INADDR_NONE) { + /* TODO: look up upstreams */ + + addr = inet_addr(host); + if (addr == INADDR_NONE) { h = gethostbyname(host); if (h == NULL || h->h_addr_list[0] == NULL) { @@ -1200,63 +1237,88 @@ static char *ngx_http_proxy_set_pass(ngx /* MP: ngx_shared_palloc() */ - ngx_test_null(upstreams, - ngx_palloc(cf->pool, - sizeof(ngx_http_proxy_upstreams_t) - + sizeof(ngx_http_proxy_upstream_t) * (i - 1)), + ngx_test_null(lcf->upstreams, + ngx_pcalloc(cf->pool, + sizeof(ngx_http_proxy_upstreams_t) + + sizeof(ngx_http_proxy_upstream_t) * (i - 1)), NGX_CONF_ERROR); - upstreams->num = i; + lcf->upstreams->number = i; for (i = 0; h->h_addr_list[i] != NULL; i++) { - upstreams->u[i].host.data = host; - upstreams->u[i].host.len = u.host.len; - upstreams->u[i].addr = *(struct in_addr *)(h->h_addr_list[i]); - upstreams->u[i].port = u.port; + lcf->upstreams->u[i].host.data = host; + lcf->upstreams->u[i].host.len = lcf->upstream_url->host.len; + lcf->upstreams->u[i].addr = *(u_int32_t *)(h->h_addr_list[i]); + lcf->upstreams->u[i].port = lcf->upstream_url->port; - len = INET_ADDRSTRLEN + u.port_name.len + 1; - ngx_test_null(upstreams->u[i].addr_port_name.data, + len = INET_ADDRSTRLEN + lcf->upstream_url->port_name.len + 1; + ngx_test_null(lcf->upstreams->u[i].addr_port_name.data, ngx_palloc(cf->pool, len), NGX_CONF_ERROR); - s = (ngx_inet_ntop(AF_INET, - upstreams->u[i].addr, - upstreams->u[i].addr_port_name.data, - len), + s = ngx_inet_ntop(AF_INET, + (char *) &lcf->upstreams->u[i].addr, + lcf->upstreams->u[i].addr_port_name.data, + len); + + lcf->upstreams->u[i].addr_port_name.data[s++] = ':'; - upstreams->u[i].addr_port_name.data[s++] = ':'; + ngx_cpystrn(lcf->upstreams->u[i].addr_port_name.data + s, + lcf->upstream_url->port_name.data, + lcf->upstream_url->port_name.len + 1); - ngx_cpystrn(upstreams->u[i].addr_port_name.data[s], - u.port_name.data, - u.port_name.len + 1); - - upstreams->u[i].addr_port_name.len = s + u.port_name.len + 1; + lcf->upstreams->u[i].addr_port_name.len = + s + lcf->upstream_url->port_name.len + 1; } } else { /* MP: ngx_shared_palloc() */ - ngx_test_null(upstreams, - ngx_palloc(cf->pool, sizeof(ngx_http_proxy_upstreams_t), + ngx_test_null(lcf->upstreams, + ngx_palloc(cf->pool, sizeof(ngx_http_proxy_upstreams_t)), + NGX_CONF_ERROR); + + lcf->upstreams->number = 1; + + lcf->upstreams->u[0].host.data = host; + lcf->upstreams->u[0].host.len = lcf->upstream_url->host.len; + lcf->upstreams->u[0].addr = addr; + lcf->upstreams->u[0].port = lcf->upstream_url->port; + + len = lcf->upstream_url->host.len + + lcf->upstream_url->port_name.len + 1; + + ngx_test_null(lcf->upstreams->u[0].addr_port_name.data, + ngx_palloc(cf->pool, len + 1), NGX_CONF_ERROR); - upstreams->num = 1; + ngx_memcpy(lcf->upstreams->u[0].addr_port_name.data, + lcf->upstream_url->host.data, + lcf->upstream_url->host.len); + + s = lcf->upstream_url->host.len; + + lcf->upstreams->u[0].addr_port_name.data[s++] = ':'; - upstreams->u[0].host.data = host; - upstreams->u[0].host.len = u.host.len; - upstreams->u[0].addr = *(struct in_addr *)(h->h_addr_list[i]); - upstreams->u[0].port = u.port; + ngx_cpystrn(lcf->upstreams->u[0].addr_port_name.data + s, + lcf->upstream_url->port_name.data, + lcf->upstream_url->port_name.len + 1); + + lcf->upstreams->u[0].addr_port_name.len = len; } + ctx = cf->ctx; + core_lcf = ctx->loc_conf[ngx_http_core_module_ctx.index]; + core_lcf->handler = ngx_http_proxy_handler; + lcf->upstream_url->location = &core_lcf->name; + return NULL; } -#endif - static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, - ngx_http_proxy_upstream_url_t *u) + ngx_http_proxy_upstream_url_t *uu) { size_t i; @@ -1264,33 +1326,33 @@ static char *ngx_http_proxy_parse_upstre return "invalid upstream URL"; } - u->host.data = url->data; - u->host_header.data = url->data; + uu->host.data = url->data; + uu->host_header.data = url->data; for (i = 1; i < url->len; i++) { if (url->data[i] == ':') { - u->port_name.data = &url->data[i]; - u->host.len = i; + uu->port_name.data = &url->data[i] + 1; + uu->host.len = i; } if (url->data[i] == '/') { - u->uri.data = &url->data[i]; - u->uri.len = url->len - i; - u->host_header.len = i; + uu->uri.data = &url->data[i]; + uu->uri.len = url->len - i; + uu->host_header.len = i; - if (u->host.len == 0) { - u->host.len = i; + if (uu->host.len == 0) { + uu->host.len = i; } - if (u->port_name.data == NULL) { + if (uu->port_name.data == NULL) { return NULL; } - u->port_name.len = &url->data[i] - u->port_name.data; + uu->port_name.len = &url->data[i] - uu->port_name.data; - if (u->port_name.len > 0) { - u->port = ngx_atoi(u->port_name.data, u->port_name.len); - if (u->port > 0) { + if (uu->port_name.len > 0) { + uu->port = ngx_atoi(uu->port_name.data, uu->port_name.len); + if (uu->port > 0) { return NULL; } } @@ -1299,24 +1361,24 @@ static char *ngx_http_proxy_parse_upstre } } - if (u->host.len == 0) { - u->host.len = i; + if (uu->host.len == 0) { + uu->host.len = i; } - u->host_header.len = i; + uu->host_header.len = i; - u->uri.data = "/"; - u->uri.len = 1; + uu->uri.data = "/"; + uu->uri.len = 1; - if (u->port_name.data == NULL) { + if (uu->port_name.data == NULL) { return NULL; } - u->port_name.len = &url->data[i] - u->port_name.data; + uu->port_name.len = &url->data[i] - uu->port_name.data; - if (u->port_name.len > 0) { - u->port = ngx_atoi(u->port_name.data, u->port_name.len); - if (u->port > 0) { + if (uu->port_name.len > 0) { + uu->port = ngx_atoi(uu->port_name.data, uu->port_name.len); + if (uu->port > 0) { return NULL; } } diff --git a/src/http/modules/ngx_http_event_proxy_handler.h b/src/http/modules/proxy/ngx_http_event_proxy_handler.h rename from src/http/modules/ngx_http_event_proxy_handler.h rename to src/http/modules/proxy/ngx_http_event_proxy_handler.h --- a/src/http/modules/ngx_http_event_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_event_proxy_handler.h @@ -16,31 +16,57 @@ typedef struct { typedef struct { - int large_header; -} ngx_http_proxy_loc_conf_t; + u_int32_t addr; + ngx_str_t host; + int port; + ngx_str_t addr_port_name; + + int fails; + time_t accessed; +} ngx_http_proxy_upstream_t; typedef struct { - ngx_str_t host; - ngx_str_t uri; - ngx_str_t host_header; - ngx_str_t port_name; - int port; + int current; + int number; + int max_fails; + int fail_timeout; + + /* ngx_mutex_t mutex; */ + /* ngx_connection_t *cached; ??? */ + + ngx_http_proxy_upstream_t u[1]; +} ngx_http_proxy_upstreams_t; + + +typedef struct { + ngx_str_t host; + ngx_str_t uri; + ngx_str_t *location; + ngx_str_t host_header; + ngx_str_t port_name; + int port; } ngx_http_proxy_upstream_url_t; typedef struct { - struct sockaddr_in; - ngx_str_t name; - time_t access; - int fails; -} ngx_http_proxy_upstream_t; + ngx_http_proxy_upstreams_t *upstreams; + ngx_http_proxy_upstream_url_t *upstream_url; + int rcvbuf; + int conn_pool_size; + int connect_timeout; + int send_timeout; + int read_timeout; + int header_size; + int large_header; -typedef struct { - int amount; - ngx_http_proxy_upstream_t *upstreams; -} ngx_http_proxy_upstream_farm_t; + int block_size; + int max_block_size; + + int retry_500_error; + +} ngx_http_proxy_loc_conf_t; #if 0 @@ -62,26 +88,43 @@ struct ngx_http_proxy_ctx_s { int last_hunk; ngx_array_t hunks; + int hunks_number; int hunk_n; - ngx_connection_t *connection; - ngx_http_request_t *request; - ngx_http_proxy_headers_in_t *headers_in; + ngx_connection_t *connection; + ngx_http_request_t *request; + ngx_http_proxy_headers_in_t *headers_in; - ngx_http_proxy_upstream_farm_t *upstream; - int cur_upstream; - int upstreams; + ngx_http_proxy_upstream_url_t *upstream_url; + ngx_http_proxy_upstreams_t *upstreams; + int cur_upstream; + int tries; + + struct sockaddr *sockaddr; + + ngx_http_proxy_loc_conf_t *lcf; ngx_log_t *log; + int method; + ngx_hunk_t *header_in; + int status; + ngx_str_t status_line; + ngx_str_t full_status_line; + int state; - int status; int status_count; - char *status_line; - char *request_end; - int (*state_handler)(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p); + char *status_start; + char *status_end; + int (*state_write_upstream_handler) (ngx_http_proxy_ctx_t *p); + int (*state_read_upstream_handler) (ngx_http_proxy_ctx_t *p); + int (*state_handler)(ngx_http_proxy_ctx_t *p); + + int last_error; + + unsigned cached_connection:1; }; diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -33,6 +33,7 @@ ngx_array_t ngx_http_index_handlers; int (*ngx_http_top_header_filter) (ngx_http_request_t *r); +int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch); static ngx_str_t http_name = ngx_string("http"); @@ -59,32 +60,6 @@ ngx_module_t ngx_http_module = { }; - -static void ngx_http_init_filters(ngx_pool_t *pool, ngx_module_t **modules) -{ - int i; - ngx_http_module_t *module; - ngx_http_conf_filter_t cf; - - cf.output_header_filter = NULL; - cf.output_body_filter = NULL; - - for (i = 0; modules[i]; i++) { - if (modules[i]->type != NGX_HTTP_MODULE_TYPE) { - continue; - } - - module = (ngx_http_module_t *) modules[i]->ctx; - - if (module->init_filters) { - module->init_filters(pool, &cf); - } - } - - ngx_http_top_header_filter = cf.output_header_filter; -} - - static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy) { int i, s, l, p, a, n, start; @@ -108,12 +83,15 @@ static char *ngx_http_block(ngx_conf_t * ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)), NGX_CONF_ERROR); + ngx_http_max_module = 0; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_HTTP_MODULE_TYPE) { continue; } - ngx_modules[i]->index = ngx_http_max_module++; + module = (ngx_http_module_t *) ngx_modules[i]->ctx; + + module->index = ngx_http_max_module++; } /* null loc_conf */ @@ -169,8 +147,6 @@ static char *ngx_http_block(ngx_conf_t * ngx_init_array(ngx_http_index_handlers, cf->pool, 3, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); - ngx_http_init_filters(cf->pool, ngx_modules); - /* create lists of ports, addresses and server names */ ngx_init_array(in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t), 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 @@ -147,6 +147,7 @@ struct ngx_http_request_s { ngx_str_t path; int path_err; + unsigned proxy:1; unsigned pipeline:1; unsigned keepalive:1; unsigned lingering_close:1; @@ -250,6 +251,9 @@ extern int ngx_http_url_in_error_log; extern ngx_array_t ngx_http_translate_handlers; extern ngx_array_t ngx_http_index_handlers; +extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r); +extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch); + /* STUB */ int ngx_http_log_handler(ngx_http_request_t *r); 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 @@ -19,18 +19,19 @@ typedef struct { typedef struct { + int index; + void *(*create_srv_conf)(ngx_pool_t *p); char *(*init_srv_conf)(ngx_pool_t *p, void *conf); void *(*create_loc_conf)(ngx_pool_t *p); char *(*merge_loc_conf)(ngx_pool_t *p, void *prev, void *conf); - - void (*init_filters) (ngx_pool_t *p, ngx_http_conf_filter_t *cf); } ngx_http_module_t; #define NGX_HTTP_MODULE_TYPE 0x50545448 /* "HTTP" */ +#define NGX_HTTP_MODULE 0 #define NGX_HTTP_MAIN_CONF 0x1000000 #define NGX_HTTP_SRV_CONF 0x2000000 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 @@ -24,6 +24,8 @@ static int ngx_http_core_init(ngx_pool_t static void *ngx_http_core_create_srv_conf(ngx_pool_t *pool); static char *ngx_http_core_init_srv_conf(ngx_pool_t *pool, void *conf); static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool); +static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool, + void *parent, void *child); static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy); static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, @@ -78,13 +80,13 @@ static ngx_command_t ngx_http_core_comm {ngx_string("location"), NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1, ngx_location_block, - 0, + NGX_HTTP_SRV_CONF_OFFSET, 0}, {ngx_string("listen"), NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_set_listen, - 0, + NGX_HTTP_SRV_CONF_OFFSET, 0}, {ngx_string("root"), @@ -93,6 +95,12 @@ static ngx_command_t ngx_http_core_comm NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, doc_root)}, + {ngx_string("sendfile"), + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, sendfile)}, + {ngx_string("send_timeout"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_time_slot, @@ -100,13 +108,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, send_timeout)}, {ngx_string("lingering_time"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_time_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, lingering_time)}, {ngx_string("lingering_timeout"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_time_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, lingering_timeout)}, @@ -116,13 +124,13 @@ static ngx_command_t ngx_http_core_comm ngx_http_module_t ngx_http_core_module_ctx = { + NGX_HTTP_MODULE, + ngx_http_core_create_srv_conf, /* create server config */ ngx_http_core_init_srv_conf, /* init server config */ ngx_http_core_create_loc_conf, /* create location config */ - NULL, /* merge location config */ - - NULL /* init filters */ + ngx_http_core_merge_loc_conf /* merge location config */ }; @@ -137,24 +145,26 @@ ngx_module_t ngx_http_core_module = { int ngx_http_handler(ngx_http_request_t *r) { - int rc, a, n, i; - ngx_http_handler_pt *h; - ngx_http_module_t *module; - ngx_http_conf_ctx_t *ctx; - ngx_http_in_port_t *in_port; - ngx_http_in_addr_t *in_addr; - ngx_http_server_name_t *name; + int rc, a, n, i; + ngx_http_handler_pt *h; + ngx_http_module_t *module; + ngx_http_conf_ctx_t *ctx; + ngx_http_in_port_t *in_port; + ngx_http_in_addr_t *in_addr; + ngx_http_server_name_t *name; + ngx_http_core_srv_conf_t *scf; + ngx_http_core_loc_conf_t *lcf, **plcf; r->connection->unexpected_eof = 0; r->keepalive = 1; r->lingering_close = 1; -#if 1 - r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; +#if 0 +ngx_log_debug(r->connection->log, "servers: %0x" _ r->connection->servers); #endif -ngx_log_debug(r->connection->log, "servers: %0x" _ r->connection->servers); + /* find server config */ if (r->connection->servers == NULL) { ctx = (ngx_http_conf_ctx_t *) r->connection->ctx; @@ -206,15 +216,52 @@ ngx_log_debug(r->connection->log, "serve r->srv_conf = ctx->srv_conf; r->loc_conf = ctx->loc_conf; +#if 0 ngx_log_debug(r->connection->log, "cxt: %08x" _ ctx); ngx_log_debug(r->connection->log, "srv_conf: %0x" _ r->srv_conf); ngx_log_debug(r->connection->log, "loc_conf: %0x" _ r->loc_conf); +#endif + + /* run rewrite url phase */ + + + /* find location config */ + + scf = (ngx_http_core_srv_conf_t *) + ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx); + + plcf = (ngx_http_core_loc_conf_t **) scf->locations.elts; + for (i = 0; i < scf->locations.nelts; i++) { +#if 0 +ngx_log_debug(r->connection->log, "trans: %s" _ plcf[i]->name.data); +#endif + if (r->uri.len < plcf[i]->name.len) { + continue; + } + + rc = ngx_strncmp(r->uri.data, plcf[i]->name.data, plcf[i]->name.len); + + if (rc < 0) { + break; + } + + if (rc == 0) { + r->loc_conf = plcf[i]->loc_conf; + } + } + + lcf = (ngx_http_core_loc_conf_t *) + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); + + if (lcf->sendfile == 0) { + r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; + } /* run translation phase */ h = (ngx_http_handler_pt *) ngx_http_translate_handlers.elts; - for (i = 0; i < ngx_http_translate_handlers.nelts; i++) { - rc = h[i](r); + for (i = ngx_http_translate_handlers.nelts; i > 0; /* void */) { + rc = h[--i](r); if (rc == NGX_DECLINED) { continue; @@ -241,43 +288,24 @@ int ngx_http_core_translate_handler(ngx_ ngx_table_elt_t *h; ngx_http_server_name_t *s_name; ngx_http_core_srv_conf_t *scf; - ngx_http_core_loc_conf_t *lcf, **plcf; + ngx_http_core_loc_conf_t *lcf; + + lcf = (ngx_http_core_loc_conf_t *) + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); + + if (lcf->handler) { + r->handler = lcf->handler; + return NGX_OK; + } scf = (ngx_http_core_srv_conf_t *) - ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - /* find location config */ - plcf = (ngx_http_core_loc_conf_t **) scf->locations.elts; - for (i = 0; i < scf->locations.nelts; i++) { -ngx_log_debug(r->connection->log, "trans: %s" _ plcf[i]->name.data); - if (r->uri.len < plcf[i]->name.len) { - continue; - } - - rc = ngx_strncmp(r->uri.data, plcf[i]->name.data, plcf[i]->name.len); - - if (rc < 0) { - break; - } - - if (rc == 0) { - r->loc_conf = plcf[i]->loc_conf; - } - } - -#if 0 - /* STUB */ r->handler = ngx_http_proxy_handler; - return NGX_OK; -#endif + ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx); if (r->uri.data[r->uri.len - 1] == '/') { r->handler = ngx_http_core_index_handler; return NGX_OK; } - lcf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_log_debug(r->connection->log, "doc_root: %08x" _ &lcf->doc_root); s_name = (ngx_http_server_name_t *) scf->server_names.elts; @@ -440,8 +468,7 @@ ngx_log_debug(r->connection->log, "HTTP return NGX_HTTP_MOVED_PERMANENTLY; } - /* TODO: r->handler = lcf->default_handler; */ - /* STUB */ r->handler = ngx_http_static_handler; + r->handler = ngx_http_static_handler; return NGX_OK; } @@ -453,8 +480,8 @@ static int ngx_http_core_index_handler(n ngx_http_handler_pt *h; h = (ngx_http_handler_pt *) ngx_http_index_handlers.elts; - for (i = 0; i < ngx_http_index_handlers.nelts; i++) { - rc = h[i](r); + for (i = ngx_http_index_handlers.nelts; i > 0; /* void */) { + rc = h[--i](r); if (rc != NGX_DECLINED) { @@ -545,7 +572,7 @@ int ngx_http_close_request(ngx_http_requ ngx_log_debug(c->log, "http closed"); - return NGX_DONE; + return NGX_ERROR; /* to close connection */ } @@ -608,13 +635,13 @@ static char *ngx_server_block(ngx_conf_t module = (ngx_http_module_t *) ngx_modules[i]->ctx; if (module->create_srv_conf) { - ngx_test_null(ctx->srv_conf[ngx_modules[i]->index], + ngx_test_null(ctx->srv_conf[module->index], module->create_srv_conf(cf->pool), NGX_CONF_ERROR); } if (module->create_loc_conf) { - ngx_test_null(ctx->loc_conf[ngx_modules[i]->index], + ngx_test_null(ctx->loc_conf[module->index], module->create_loc_conf(cf->pool), NGX_CONF_ERROR); } @@ -629,7 +656,7 @@ static char *ngx_server_block(ngx_conf_t return rv; - scf = ctx->srv_conf[ngx_http_core_module.index]; + scf = ctx->srv_conf[ngx_http_core_module_ctx.index]; scf->ctx = ctx; plcf = (ngx_http_core_loc_conf_t **)scf->locations.elts; @@ -643,7 +670,7 @@ static char *ngx_server_block(ngx_conf_t if (module->init_srv_conf) { if (module->init_srv_conf(cf->pool, - ctx->srv_conf[ngx_modules[i]->index]) + ctx->srv_conf[module->index]) == NGX_CONF_ERROR) { return NGX_CONF_ERROR; } @@ -651,16 +678,16 @@ static char *ngx_server_block(ngx_conf_t if (module->merge_loc_conf) { if (module->merge_loc_conf(cf->pool, - prev->loc_conf[ngx_modules[i]->index], - ctx->loc_conf[ngx_modules[i]->index]) + prev->loc_conf[module->index], + ctx->loc_conf[module->index]) == NGX_CONF_ERROR) { return NGX_CONF_ERROR; } for (j = 0; j < scf->locations.nelts; j++) { if (module->merge_loc_conf(cf->pool, - ctx->loc_conf[ngx_modules[i]->index], - plcf[j]->loc_conf[ngx_modules[i]->index]) + ctx->loc_conf[module->index], + plcf[j]->loc_conf[module->index]) == NGX_CONF_ERROR) { return NGX_CONF_ERROR; } @@ -701,21 +728,21 @@ static char *ngx_location_block(ngx_conf module = (ngx_http_module_t *) ngx_modules[i]->ctx; if (module->create_loc_conf) { - ngx_test_null(ctx->loc_conf[ngx_modules[i]->index], + ngx_test_null(ctx->loc_conf[module->index], module->create_loc_conf(cf->pool), NGX_CONF_ERROR); } } lcf = (ngx_http_core_loc_conf_t *) - ctx->loc_conf[ngx_http_core_module.index]; + ctx->loc_conf[ngx_http_core_module_ctx.index]; location = (ngx_str_t *) cf->args->elts; lcf->name.len = location[1].len; lcf->name.data = location[1].data; lcf->loc_conf = ctx->loc_conf; scf = (ngx_http_core_srv_conf_t *) - ctx->srv_conf[ngx_http_core_module.index]; + ctx->srv_conf[ngx_http_core_module_ctx.index]; ngx_test_null(plcf, ngx_push_array(&scf->locations), NGX_CONF_ERROR); *plcf = lcf; @@ -793,6 +820,8 @@ static void *ngx_http_core_create_loc_co lcf->doc_root.len = 4; lcf->doc_root.data = "html"; + lcf->sendfile = 0; + lcf->send_timeout = 10000; lcf->discarded_buffer_size = 1500; lcf->lingering_time = 30000; @@ -805,6 +834,12 @@ static void *ngx_http_core_create_loc_co return lcf; } +static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool, + void *parent, void *child) +{ + return NGX_CONF_OK; +} + static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf) { ngx_str_t *args; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -57,13 +57,17 @@ typedef struct { void **loc_conf; /* pointer to modules loc_conf, used in translation handler */ + int (*handler) (ngx_http_request_t *r); + ngx_str_t doc_root; /* root */ + int sendfile; /* sendfile */ time_t send_timeout; /* send_timeout */ size_t send_lowat; /* send_lowa */ size_t discarded_buffer_size; /* discarded_buffer_size */ time_t lingering_time; /* lingering_time */ ngx_msec_t lingering_timeout; /* lingering_timeout */ + } ngx_http_core_loc_conf_t; @@ -76,10 +80,20 @@ typedef struct { #endif +#if 0 +#define ngx_http_set_loc_handler(conf_ctx, ngx_http_handler) \ + { \ + ngx_http_conf_ctx_t *cx = conf_ctx; \ + ngx_http_core_loc_conf_t *lcf; \ + lcf = cx->loc_conf[ngx_http_core_module_ctx.index]; \ + lcf->handler = ngx_http_handler; \ + } +#endif + + extern ngx_http_module_t ngx_http_core_module_ctx; extern ngx_module_t ngx_http_core_module; -extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r); extern int ngx_http_max_module; 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 @@ -238,12 +238,12 @@ static int ngx_http_process_request(ngx_ r->header_in->last += n; } - /* the state_handlers are called in the following order: + /* the state handlers are called in the following order: ngx_http_process_request_line(r) ngx_http_process_request_headers(r) */ do { - rc = (r->state_handler)(r); + rc = r->state_handler(r); } while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last); @@ -265,8 +265,8 @@ static int ngx_http_process_request(ngx_ rc = ngx_http_handler(r); - /* a handler is still busy */ - if (rc == NGX_BUSY) { + /* a handler does its own processing */ + if (rc == NGX_DONE) { return rc; } @@ -310,6 +310,14 @@ static int ngx_http_process_request_line if (rc == NGX_OK) { + if (r->http_version >= NGX_HTTP_VERSION_10 + && ngx_http_large_client_header == 0 + && r->header_in->pos == r->header_in->end) + { + ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI); + return NGX_HTTP_REQUEST_URI_TOO_LARGE; + } + /* copy URI */ if (r->args_start) { @@ -329,7 +337,6 @@ static int ngx_http_process_request_line we need to copy a request line */ if (ngx_http_large_client_header) { - ngx_test_null(r->request_line.data, ngx_palloc(r->pool, r->request_line.len + 1), NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -651,8 +658,8 @@ int ngx_http_finalize_request(ngx_http_r but the transfer is still not completed */ lcf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_core_module); + ngx_http_get_module_loc_conf(r->main ? r->main : r, + ngx_http_core_module_ctx); wev = r->connection->write; wev->event_handler = ngx_http_writer; wev->timer_set = 1; @@ -725,8 +732,8 @@ static int ngx_http_writer(ngx_event_t * if (rc == NGX_AGAIN) { lcf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_core_module); + ngx_http_get_module_loc_conf(r->main ? r->main : r, + ngx_http_core_module_ctx); if (wev->timer_set) { ngx_del_timer(wev); } else { @@ -824,7 +831,7 @@ static int ngx_http_read_discarded_body( r = (ngx_http_request_t *) c->data; lcf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); if (r->discarded_buffer == NULL) { ngx_test_null(r->discarded_buffer, @@ -944,7 +951,7 @@ static int ngx_http_keepalive_handler(ng ngx_log_debug(c->log, "http keepalive handler"); if (rev->timedout) { - return NGX_DONE; + return NGX_ERROR; /* to close connection */ } /* MSIE closes a keepalive connection with RST flag @@ -965,7 +972,7 @@ static int ngx_http_keepalive_handler(ng if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno, "client %s closed keepalive connection", lctx->client); - return NGX_DONE; + return NGX_ERROR; /* to close connection */ } c->buffer->last += n; @@ -986,7 +993,7 @@ static int ngx_http_set_lingering_close( rev = c->read; lcf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); r->lingering_time = ngx_time() + lcf->lingering_time / 1000; r->connection->read->event_handler = ngx_http_lingering_close_handler; @@ -1063,7 +1070,7 @@ static int ngx_http_lingering_close_hand } lcf = (ngx_http_core_loc_conf_t *) - ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); if (r->discarded_buffer == NULL) { 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 @@ -14,8 +14,7 @@ #include -static void ngx_http_header_filter_init(ngx_pool_t *pool, - ngx_http_conf_filter_t *cf); +static int ngx_http_header_filter_init(ngx_pool_t *pool); static int ngx_http_header_filter(ngx_http_request_t *r); @@ -26,7 +25,7 @@ ngx_http_module_t ngx_http_header_filte NULL, /* create location config */ NULL, /* merge location config */ - ngx_http_header_filter_init /* init filters */ + NULL /* init filters */ }; @@ -35,7 +34,7 @@ ngx_module_t ngx_http_header_filter_mod &ngx_http_header_filter_module_ctx, /* module context */ NULL, /* module directives */ NGX_HTTP_MODULE_TYPE, /* module type */ - NULL /* init module */ + ngx_http_header_filter_init /* init module */ }; @@ -294,8 +293,8 @@ static int ngx_http_header_filter(ngx_ht } -static void ngx_http_header_filter_init(ngx_pool_t *pool, - ngx_http_conf_filter_t *cf) +static int ngx_http_header_filter_init(ngx_pool_t *pool) { - cf->output_header_filter = ngx_http_header_filter; + ngx_http_top_header_filter = ngx_http_header_filter; + return NGX_OK; } 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 @@ -33,13 +33,13 @@ static ngx_command_t ngx_http_output_fi static ngx_http_module_t ngx_http_output_filter_module_ctx = { + NGX_HTTP_MODULE, + NULL, /* create server config */ NULL, /* init server config */ ngx_http_output_filter_create_conf, /* create location config */ - ngx_http_output_filter_merge_conf, /* merge location config */ - - ngx_http_output_filter_init /* output body filter */ + ngx_http_output_filter_merge_conf /* merge location config */ }; @@ -52,8 +52,11 @@ ngx_module_t ngx_http_output_filter_mod }; +#define next_filter (*ngx_http_top_body_filter) +#if 0 static int (*next_filter) (ngx_http_request_t *r, ngx_chain_t *ch); +#endif #if 0 @@ -77,10 +80,10 @@ int ngx_http_output_filter(ngx_http_requ ctx = (ngx_http_output_filter_ctx_t *) ngx_http_get_module_ctx(r->main ? r->main : r, - ngx_http_output_filter_module); + ngx_http_output_filter_module_ctx); if (ctx == NULL) { - ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module, + ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module_ctx, sizeof(ngx_http_output_filter_ctx_t), NGX_ERROR); } @@ -120,8 +123,8 @@ int ngx_http_output_filter(ngx_http_requ if (ctx->hunk == NULL) { conf = (ngx_http_output_filter_conf_t *) - ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_output_filter_module); + ngx_http_get_module_loc_conf(r->main ? r->main : r, + ngx_http_output_filter_module_ctx); if (hunk->type & NGX_HUNK_LAST) { if (hunk->type & NGX_HUNK_IN_MEMORY) { @@ -303,8 +306,10 @@ static int ngx_http_output_filter_copy_h static void ngx_http_output_filter_init(ngx_pool_t *pool, ngx_http_conf_filter_t *cf) { +#if 0 next_filter = cf->output_body_filter; cf->output_body_filter = NULL; +#endif } 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 @@ -338,6 +338,7 @@ int ngx_read_http_header_line(ngx_http_r sw_space_after_value, sw_almost_done, sw_header_almost_done, + sw_ignore_line, sw_done, sw_header_done } state; @@ -404,6 +405,14 @@ int ngx_read_http_header_line(ngx_http_r break; } + if (ch == '/') { + /* IIS can send duplicate "HTTP/1.1 ..." lines */ + if (r->proxy && ngx_strncmp(r->header_start, "HTTP", 4) == 0) { + state = sw_ignore_line; + break; + } + } + return NGX_HTTP_PARSE_INVALID_HEADER; /* space* before header value */ @@ -461,6 +470,17 @@ int ngx_read_http_header_line(ngx_http_r } break; + /* ignore header line */ + case sw_ignore_line: + switch (ch) { + case LF: + state = sw_start; + break; + default: + break; + } + break; + /* end of header line */ case sw_almost_done: switch (ch) { 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 @@ -122,11 +122,22 @@ int ngx_http_special_response_handler(ng 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 + 3; + } else { + ngx_test_null(r->headers_out.content_type, + ngx_push_table(r->headers_out.headers), + NGX_HTTP_INTERNAL_SERVER_ERROR); - } else { - err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17; + r->headers_out.content_type->key.len = 12; + r->headers_out.content_type->key.data = "Content-Type"; + r->headers_out.content_type->value.len = 9; + r->headers_out.content_type->value.data = "text/html"; + + if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) { + err = error - NGX_HTTP_BAD_REQUEST + 3; + + } else { + err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17; + } } if (r->keepalive != 0) { 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 @@ -16,30 +16,29 @@ static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool); static char *ngx_http_write_filter_merge_conf(ngx_pool_t *pool, void *parent, void *child); -static void ngx_http_write_filter_init(ngx_pool_t *pool, - ngx_http_conf_filter_t *cf); +static int ngx_http_write_filter_init(ngx_pool_t *pool); static ngx_command_t ngx_http_write_filter_commands[] = { - {ngx_string("write_buffer"), + {ngx_string("buffer_output"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_write_filter_conf_t, buffer_output)}, - {ngx_string(""), 0, NULL, 0, 0} + {ngx_null_string, 0, NULL, 0, 0} }; ngx_http_module_t ngx_http_write_filter_module_ctx = { + NGX_HTTP_MODULE, + NULL, /* create server config */ NULL, /* init server config */ ngx_http_write_filter_create_conf, /* create location config */ - ngx_http_write_filter_merge_conf, /* merge location config */ - - ngx_http_write_filter_init /* init filters */ + ngx_http_write_filter_merge_conf /* merge location config */ }; @@ -48,24 +47,24 @@ ngx_module_t ngx_http_write_filter_modu &ngx_http_write_filter_module_ctx, /* module context */ ngx_http_write_filter_commands, /* module directives */ NGX_HTTP_MODULE_TYPE, /* module type */ - NULL /* init module */ + ngx_http_write_filter_init /* init module */ }; int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) { - int last; - off_t size, flush; - ngx_chain_t *ce, **le, *chain; - ngx_http_write_filter_ctx_t *ctx; - ngx_http_write_filter_conf_t *conf; + int last; + off_t size, flush; + ngx_chain_t *ce, **le, *chain; + ngx_http_write_filter_ctx_t *ctx; + ngx_http_write_filter_conf_t *conf; ctx = (ngx_http_write_filter_ctx_t *) ngx_http_get_module_ctx(r->main ? r->main : r, - ngx_http_write_filter_module); + ngx_http_write_filter_module_ctx); if (ctx == NULL) { - ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module, + ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module_ctx, sizeof(ngx_http_write_filter_ctx_t), NGX_ERROR); } @@ -73,7 +72,8 @@ int ngx_http_write_filter(ngx_http_reque last = 0; le = &ctx->out; - /* find the size, the flush point and the last entry of saved chain */ + /* find the size, the flush point and the last entry of the saved chain */ + for (ce = ctx->out; ce; ce = ce->next) { le = &ce->next; @@ -93,6 +93,7 @@ int ngx_http_write_filter(ngx_http_reque } /* add the new chain to the existent one */ + for (/* void */; in; in = in->next) { ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR); @@ -118,7 +119,7 @@ int ngx_http_write_filter(ngx_http_reque conf = (ngx_http_write_filter_conf_t *) ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_write_filter_module); + ngx_http_write_filter_module_ctx); #if (NGX_DEBUG_WRITE_FILTER) ngx_log_debug(r->connection->log, "write filter: last:%d flush:%d" _ @@ -126,7 +127,8 @@ int ngx_http_write_filter(ngx_http_reque #endif /* avoid the output if there is no last hunk, no flush point and - size of the hunks is smaller then 'write_buffer' */ + size of the hunks is smaller then "buffer_output" */ + if (!last && flush == 0 && size < conf->buffer_output) { return NGX_OK; } @@ -152,13 +154,6 @@ int ngx_http_write_filter(ngx_http_reque } -static void ngx_http_write_filter_init(ngx_pool_t *pool, - ngx_http_conf_filter_t *cf) -{ - cf->output_body_filter = ngx_http_write_filter; -} - - static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool) { ngx_http_write_filter_conf_t *conf; @@ -186,3 +181,10 @@ static char *ngx_http_write_filter_merge return NULL; } + +static int ngx_http_write_filter_init(ngx_pool_t *pool) +{ + ngx_http_top_body_filter = ngx_http_write_filter; + + return NGX_OK; +}