# HG changeset patch # User Igor Sysoev # Date 1039192353 0 # Node ID f540a63026c94bbbdc9fc9d01b36d909d4b86b07 # Parent aa3b53e747285f48d6d917daf9dee171a581016c nginx-0.0.1-2002-12-06-19:32:33 import diff -r aa3b53e74728 -r f540a63026c9 src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c Thu Dec 05 16:21:24 2002 +0000 +++ b/src/event/modules/ngx_select_module.c Fri Dec 06 16:32:33 2002 +0000 @@ -126,6 +126,8 @@ ngx_connection_t *c; c = (ngx_connection_t *) ev->data; + ngx_log_debug(c->log, "del event: %d" _ c->fd); + #if (WIN32) if (event == NGX_READ_EVENT) { FD_CLR(c->fd, &master_read_fd_set); @@ -146,13 +148,13 @@ max_fd = -1; #endif + nevents--; + if (ev->index < nevents) { event_index[ev->index] = event_index[nevents]; event_index[ev->index]->index = ev->index; } - nevents--; - return NGX_OK; } diff -r aa3b53e74728 -r f540a63026c9 src/event/ngx_event.h --- a/src/event/ngx_event.h Thu Dec 05 16:21:24 2002 +0000 +++ b/src/event/ngx_event.h Fri Dec 06 16:32:33 2002 +0000 @@ -22,8 +22,8 @@ int index; - ngx_event_t *prev; /* queue in select(), poll(), mutex(), */ - ngx_event_t *next; /* aio_read(), aio_write() */ + ngx_event_t *prev; /* queue in mutex(), aio_read(), aio_write() */ + ngx_event_t *next; /* */ int (*timer_handler)(ngx_event_t *ev); ngx_event_t *timer_prev; @@ -43,9 +43,9 @@ /* accept: 1 if accept many, 0 otherwise */ /* flags - int are probably faster on write then bits ??? */ -#if !(USE_KQUEUE) + unsigned oneshot:1; -#endif + unsigned listening:1; unsigned write:1; diff -r aa3b53e74728 -r f540a63026c9 src/http/modules/ngx_http_event_proxy_handler.c --- a/src/http/modules/ngx_http_event_proxy_handler.c Thu Dec 05 16:21:24 2002 +0000 +++ b/src/http/modules/ngx_http_event_proxy_handler.c Fri Dec 06 16:32:33 2002 +0000 @@ -16,8 +16,15 @@ struct sockaddr_in *addr, char *addr_text); static int ngx_http_proxy_send_request(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 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 char conn_close[] = "Connection: close" CRLF; @@ -250,7 +257,8 @@ static int ngx_http_proxy_read_response_header(ngx_event_t *ev) { - int n; + int n, rc; + ngx_hunk_t **ph; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_proxy_ctx_t *p; @@ -264,7 +272,14 @@ if (p->header_in == NULL) { ngx_test_null(p->header_in, - ngx_palloc(r->pool, sizeof(ngx_http_proxy_header_in_t)), + ngx_create_temp_hunk(r->pool, + /* STUB */ 1024 /**/, 0, 0), + NGX_ERROR); + + p->header_in->type = NGX_HUNK_MEMORY; + + ngx_test_null(p->headers_in, + ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)), NGX_ERROR); ngx_test_null(p->hunks, @@ -273,36 +288,87 @@ sizeof(ngx_hunk_t *)), NGX_ERROR); - p->last_hunk = 0; + ngx_test_null(ph, ngx_push_array(p->hunks), NGX_ERROR); + *ph = p->header_in; - ngx_test_null(p->hunk, - ngx_create_temp_hunk(r->pool, - /* STUB */ 1024 /**/, 0, 0), - NGX_ERROR); - - p->hunk->type = NGX_HUNK_MEMORY; + p->state_handler = ngx_http_proxy_process_status_line; } - n = ngx_event_recv(c, p->hunk->last.mem, p->hunk->end - p->hunk->last.mem); + n = ngx_event_recv(c, p->header_in->last.mem, + p->header_in->end - p->header_in->last.mem); ngx_log_debug(c->log, "READ:%d" _ n); - p->hunk->last.mem += n; + p->header_in->last.mem += n; + + /* STUB */ + *p->header_in->last.mem = '\0'; + ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->header_in->pos.mem); + /**/ + + if (n == 0) { + ngx_log_debug(c->log, "CLOSE proxy"); + ngx_del_event(ev, NGX_READ_EVENT); + ngx_event_close_connection(ev); - *p->hunk->last.mem = '\0'; - ngx_log_debug(c->log, "PROXY:\n'%s'" _ p->hunk->pos.mem); + p->hunk_n = 0; + c->write->event_handler = ngx_http_proxy_write_to_client; + return ngx_http_proxy_write_to_client(c->write); + } + + /* state_handlers are called in following order: + ngx_http_proxy_process_status_line(r, p) + ngx_http_proxy_process_reponse_header(r, p) */ + + 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); ev->event_handler = ngx_http_proxy_read_response_body; - if (p->hunk->end - p->hunk->last.mem == 0) + if (p->header_in->end - p->header_in->last.mem == 0) return ngx_http_proxy_read_response_body(ev); + return NGX_WAITING; +} + +static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, + ngx_http_proxy_ctx_t *p) +{ + int rc; + + ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); + + rc = ngx_read_http_proxy_status_line(p); + + ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); + + if (rc == NGX_OK) { + /* STUB */ + ngx_log_debug(r->connection->log, "STATUS: %d" _ p->status); + + p->state_handler = NULL; + } + + if (p->header_in->last.mem >= p->header_in->end) { + rc = NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE; + + } else if (rc == NGX_AGAIN) { + return NGX_AGAIN; + } + /* STUB */ return NGX_ERROR; } static int ngx_http_proxy_read_response_body(ngx_event_t *ev) { int n; - size_t size; + size_t left; ngx_hunk_t *h, **ph; ngx_connection_t *c; ngx_http_request_t *r; @@ -315,15 +381,24 @@ r = (ngx_http_request_t *) c->data; p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); - size = 0; + left = 0; if (p->hunks->nelts > 0) { h = ((ngx_hunk_t **) p->hunks->elts)[p->hunks->nelts - 1]; - size = h->end - h->last.mem; + left = h->end - h->last.mem; } do { - if (size == 0) { + +#if (HAVE_KQUEUE) +#if !(USE_KQUEUE) + if (ngx_event_type == NGX_KQUEUE_EVENT) +#endif + /* do not allocate new block if there is EOF */ + if (ev->eof && ev->available == 0) + left = 1; +#endif + if (left == 0) { ngx_test_null(ph, ngx_push_array(p->hunks), NGX_ERROR); ngx_test_null(h, ngx_create_temp_hunk(r->pool, @@ -338,29 +413,211 @@ ngx_log_debug(c->log, "READ:%d" _ n); + if (n == NGX_AGAIN) + return NGX_WAITING; + + if (n == NGX_ERROR) + return NGX_ERROR; + h->last.mem += n; + left = h->end - h->last.mem; + /* STUB */ *h->last.mem = '\0'; ngx_log_debug(c->log, "PROXY:\n'%s'" _ h->pos.mem); - size = h->end - h->last.mem; + /**/ - /* TODO: close if KEVENT and (ev->available == 0 && ev->eof) */ - - } while (size == 0); + } while (n > 0 && left == 0); if (n == 0) { - return ngx_event_close_connection(ev); + ngx_log_debug(c->log, "CLOSE proxy"); + ngx_del_event(ev, NGX_READ_EVENT); + 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); } /* STUB */ return NGX_WAITING; } -#if 0 static int ngx_http_proxy_write_to_client(ngx_event_t *ev) { - /* если бэкенд быстрее, то CLEAR, иначе - ONESHOT */ + int rc; + ngx_hunk_t *h; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_proxy_ctx_t *p; + + c = (ngx_connection_t *) ev->data; + r = (ngx_http_request_t *) c->data; + p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module); + + do { + h = ((ngx_hunk_t **) p->hunks->elts)[p->hunk_n]; - rc = ngx_http_output_filter(r, h); + rc = ngx_http_output_filter(r, h); + if (rc != NGX_OK) + return rc; + + if (p->hunk_n >= p->hunks->nelts) + break; + + p->hunk_n++; + + } while (rc == NGX_OK); + + return NGX_OK; } -#endif + +static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx) +{ + char ch; + char *p; + enum { + sw_start = 0, + sw_first_major_digit, + sw_major_digit, + sw_first_minor_digit, + sw_minor_digit, + sw_status, + sw_space_after_status, + sw_status_text, + sw_almost_done, + sw_done + } state; + + state = ctx->state; + p = ctx->header_in->pos.mem; + + while (p < ctx->header_in->last.mem && state < sw_done) { + ch = *p++; + +fprintf(stderr, "state: %d, pos: %x, end: %x, char: '%c', status: %d\n", + state, p, ctx->header_in->last.mem, ch, ctx->status); + + switch (state) { + + /* "HTTP/" */ + case sw_start: + if (p + 3 >= ctx->header_in->last.mem) + return NGX_AGAIN; + + if (ch != 'H' || *p != 'T' || *(p + 1) != 'T' || *(p + 2) != 'P' + || *(p + 3) != '/') + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + + p += 4; + state = sw_first_major_digit; + break; + + /* first digit of major HTTP version */ + case sw_first_major_digit: + if (ch < '1' || ch > '9') + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + + state = sw_major_digit; + break; + + /* major HTTP version or dot */ + case sw_major_digit: + if (ch == '.') { + state = sw_first_minor_digit; + break; + } + + if (ch < '0' || ch > '9') + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + + break; + + /* first digit of minor HTTP version */ + case sw_first_minor_digit: + if (ch < '0' || ch > '9') + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + + state = sw_minor_digit; + break; + + /* minor HTTP version or end of request line */ + case sw_minor_digit: + if (ch == ' ') { + state = sw_status; + break; + } + + if (ch < '0' || ch > '9') + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + + break; + + /* HTTP status code */ + case sw_status: + if (ch < '0' || ch > '9') + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + + ctx->status = ctx->status * 10 + ch - '0'; + + if (++ctx->status_count == 3) + state = sw_space_after_status; + + break; + + /* space or end of line */ + case sw_space_after_status: + switch (ch) { + case ' ': + ctx->status_text = p - 1; + state = sw_status_text; + break; + case CR: + state = sw_almost_done; + break; + case LF: + state = sw_done; + break; + default: + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + } + break; + + /* any text until end of line */ + case sw_status_text: + switch (ch) { + case CR: + state = sw_almost_done; + break; + case LF: + state = sw_done; + break; + } + break; + + /* end of request line */ + case sw_almost_done: + ctx->request_end = p - 2; + switch (ch) { + case LF: + state = sw_done; + break; + default: + return NGX_HTTP_PROXY_PARSE_NO_HEADER; + } + break; + } + } + + ctx->header_in->pos.mem = p; + + if (state == sw_done) { + if (ctx->request_end == NULL) + ctx->request_end = p - 1; + ctx->state = sw_start; + return NGX_OK; + } else { + ctx->state = state; + return NGX_AGAIN; + } +} diff -r aa3b53e74728 -r f540a63026c9 src/http/modules/ngx_http_event_proxy_handler.h --- a/src/http/modules/ngx_http_event_proxy_handler.h Thu Dec 05 16:21:24 2002 +0000 +++ b/src/http/modules/ngx_http_event_proxy_handler.h Fri Dec 06 16:32:33 2002 +0000 @@ -7,19 +7,33 @@ #include +#define NGX_HTTP_PROXY_PARSE_NO_HEADER 20 +#define NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE 21 + typedef struct { int dummy; -} ngx_http_proxy_header_in_t; +} ngx_http_proxy_headers_in_t; -typedef struct { +typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t; + +struct ngx_http_proxy_ctx_s { ngx_chain_t *out; - ngx_hunk_t *hunk; int last_hunk; ngx_array_t *hunks; - ngx_http_proxy_header_in_t *header_in; -} ngx_http_proxy_ctx_t; + int hunk_n; + + ngx_http_proxy_headers_in_t *headers_in; + + ngx_hunk_t *header_in; + int state; + int status; + int status_count; + char *status_text; + char *request_end; + int (*state_handler)(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p); +}; extern ngx_http_module_t ngx_http_proxy_module; diff -r aa3b53e74728 -r f540a63026c9 src/http/ngx_http_event.c --- a/src/http/ngx_http_event.c Thu Dec 05 16:21:24 2002 +0000 +++ b/src/http/ngx_http_event.c Fri Dec 06 16:32:33 2002 +0000 @@ -323,7 +323,7 @@ } if (r->header_in->last.mem >= r->header_in->end) { - rc == NGX_HTTP_PARSE_TOO_LONG_URI; + rc = NGX_HTTP_PARSE_TOO_LONG_URI; } else if (rc == NGX_AGAIN) { return NGX_AGAIN; @@ -495,10 +495,11 @@ rc = ngx_http_handler(r); + /* handler is still busy */ if (rc == NGX_WAITING) return rc; - /* transfer not completed */ + /* handler has done its work but transfer is not completed */ if (rc == NGX_AGAIN) { #if (HAVE_CLEAR_EVENT) if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT, @@ -567,7 +568,7 @@ r->connection->read->event_handler = ngx_http_block_read; /* STUB: should find handler */ -#if 1 +#if 0 r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; #endif rc = ngx_http_set_default_handler(r); diff -r aa3b53e74728 -r f540a63026c9 src/http/ngx_http_output_filter.c --- a/src/http/ngx_http_output_filter.c Thu Dec 05 16:21:24 2002 +0000 +++ b/src/http/ngx_http_output_filter.c Fri Dec 06 16:32:33 2002 +0000 @@ -126,7 +126,7 @@ ctx->in = ce->next; } - if (rc == NGX_OK) + if (rc == NGX_OK && ctx->hunk) ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; else return rc; @@ -218,7 +218,8 @@ return NGX_OK; if (rc == NGX_OK) { - ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; + if (ctx->hunk) + ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; #if level_event ngx_del_event(r->connection->write, NGX_WRITE_EVENT); #endif diff -r aa3b53e74728 -r f540a63026c9 src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c Thu Dec 05 16:21:24 2002 +0000 +++ b/src/http/ngx_http_parse.c Fri Dec 06 16:32:33 2002 +0000 @@ -312,86 +312,6 @@ } } -#if 0 -int ngx_read_http_response_line(ngx_http_request_t *r) -{ - char c, ch; - char *p; - enum { - sw_start = 0, - sw_done - } state; - - state = r->state; - p = r->header_in->pos.mem; - - while (p < r->header_in->last.mem && state < sw_done) { - ch = *p++; - -/* -printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s", - state, p, r->header_in->last, ch, p); -*/ - - switch (state) { - - /* "HTTP/" */ - case sw_start: - if (p + 3 >= r->header_in->last.mem) - return NGX_AGAIN; - - if (ch != 'H' || *p != 'T' || *(p + 1) != 'T' || *(p + 2) != 'P' - || *(p + 3) != '/') - return NGX_HTTP_PARSE_NO_HEADER; - - p += 4; - state = sw_first_major_digit; - break; - - /* first digit of major HTTP version */ - case sw_first_major_digit: - if (ch < '1' || ch > '9') - return NGX_HTTP_PARSE_NO_HEADER; - - state = sw_major_digit; - break; - - /* major HTTP version or dot */ - case sw_major_digit: - if (ch == '.') { - state = sw_first_minor_digit; - break; - } - - if (ch < '0' || ch > '9') - return NGX_HTTP_PARSE_NO_HEADER; - - break; - - /* first digit of minor HTTP version */ - case sw_first_minor_digit: - if (ch < '0' || ch > '9') - return NGX_HTTP_PARSE_NO_HEADER; - - state = sw_minor_digit; - break; - - /* minor HTTP version or end of request line */ - case sw_minor_digit: - if (ch == ' ') { - state = sw_code; - break; - } - - if (ch < '0' || ch > '9') - return NGX_HTTP_PARSE_NO_HEADER; - - break; - } - } -} -#endif - int ngx_read_http_header_line(ngx_http_request_t *r) { char c, ch;