# HG changeset patch # User Igor Sysoev # Date 1030640394 0 # Node ID b5481d6fbbd475ac2fe94250ff59eede4a477ba7 # Parent 669801705ab12826bd58ce04d273ba80aae50c04 nginx-0.0.1-2002-08-29-20:59:54 import diff --git a/src/core/ngx_alloc.c b/src/core/ngx_alloc.c --- a/src/core/ngx_alloc.c +++ b/src/core/ngx_alloc.c @@ -14,6 +14,9 @@ void *ngx_alloc(size_t size, ngx_log_t * if (p == NULL) ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "malloc() %d bytes failed", size); + + ngx_log_debug(log, "malloc: %x" _ p); + return p; } diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -34,7 +34,7 @@ struct ngx_connection_s { char *addr_text; size_t addr_textlen; - time_t post_accept_timeout; + unsigned int post_accept_timeout; }; diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h --- a/src/core/ngx_hunk.h +++ b/src/core/ngx_hunk.h @@ -57,6 +57,9 @@ struct ngx_chain_s { ngx_chain_t *next; }; +#define ngx_create_temp_hunk(pool, size, before, after) \ + ngx_get_hunk(pool, size, before, after) + #define ngx_add_hunk_to_chain(chain, h, pool, error) \ do { \ ngx_test_null(chain, ngx_create_chain_entry(pool), error); \ @@ -66,6 +69,7 @@ struct ngx_chain_s { + ngx_hunk_t *ngx_get_hunk(ngx_pool_t *pool, int size, int before, int after); 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 @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -19,7 +20,6 @@ #endif static void ngx_add_timer_core(ngx_event_t *ev, u_int timer); -static void ngx_inline ngx_del_timer(ngx_event_t *ev); static int kq; @@ -145,7 +145,7 @@ int ngx_kqueue_process_events(ngx_log_t } ngx_log_debug(log, "ngx_kqueue_process_events: " - "timer: %d, delta: %d" _ timer _ delta); + "timer: %d, delta: %d" _ timer _ delta); if (timer) { if (delta >= timer) { @@ -158,7 +158,7 @@ int ngx_kqueue_process_events(ngx_log_t ngx_del_timer(ev); #if 1 ev->timedout = 1; - if (ev->event_handler(ev) == -1) + if (ev->event_handler(ev) == NGX_ERROR) ev->close_handler(ev); #else if (ev->timer_handler(ev) == -1) @@ -200,7 +200,7 @@ int ngx_kqueue_process_events(ngx_log_t ev->error = event_list[i].fflags; } - if (ev->event_handler(ev) == -1) + if (ev->event_handler(ev) == NGX_ERROR) ev->close_handler(ev); break; @@ -233,6 +233,7 @@ static void ngx_add_timer_core(ngx_event e->timer_prev = ev; } +#if 0 static void ngx_inline ngx_del_timer(ngx_event_t *ev) { if (ev->timer_prev) @@ -240,9 +241,10 @@ static void ngx_inline ngx_del_timer(ngx if (ev->timer_next) { ev->timer_next->timer_prev = ev->timer_prev; - ev->timer_prev = NULL; + ev->timer_next = NULL; } if (ev->timer_prev) - ev->timer_next = NULL; + ev->timer_prev = NULL; } +#endif diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -24,7 +24,6 @@ static ngx_event_t timer_queue; static void ngx_add_timer_core(ngx_event_t *ev, u_int timer); -static void ngx_inline ngx_del_timer(ngx_event_t *ev); static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event, ngx_log_t *log); @@ -338,6 +337,7 @@ static void ngx_add_timer_core(ngx_event e->timer_prev = ev; } +#if 0 static void ngx_inline ngx_del_timer(ngx_event_t *ev) { if (ev->timer_prev) @@ -345,9 +345,10 @@ static void ngx_inline ngx_del_timer(ngx if (ev->timer_next) { ev->timer_next->timer_prev = ev->timer_prev; - ev->timer_prev = NULL; + ev->timer_next = NULL; } if (ev->timer_prev) - ev->timer_next = NULL; + ev->timer_prev = NULL; } +#endif diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -19,7 +19,7 @@ ngx_event_t *ngx_read_events, *n #if !(USE_KQUEUE) -#if 1 +#if 0 ngx_event_type_e ngx_event_type = NGX_SELECT_EVENT; #else ngx_event_type_e ngx_event_type = NGX_KQUEUE_EVENT; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -133,6 +133,23 @@ NGX_AIO_EVENT overlapped, a #define ngx_add_timer(ev, time) ngx_add_event(ev, NGX_TIMER_EVENT, time) +static void ngx_inline ngx_del_timer(ngx_event_t *ev) +{ + if (ev->timer_prev) + ev->timer_prev->timer_next = ev->timer_next; + + if (ev->timer_next) { + ev->timer_next->timer_prev = ev->timer_prev; + ev->timer_next = NULL; + } + + if (ev->timer_prev) + ev->timer_prev = NULL; +} + + + + extern ngx_event_t *ngx_read_events; extern ngx_event_t *ngx_write_events; extern ngx_connection_t *ngx_connections; diff --git a/src/event/ngx_event_close.c b/src/event/ngx_event_close.c --- a/src/event/ngx_event_close.c +++ b/src/event/ngx_event_close.c @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -8,22 +9,24 @@ int ngx_event_close_connection(ngx_event_t *ev) { int rc; - ngx_connection_t *cn = (ngx_connection_t *) ev->data; + ngx_connection_t *c = (ngx_connection_t *) ev->data; - ngx_assert((cn->fd != -1), return -1, ev->log, + ngx_assert((c->fd != -1), return NGX_ERROR, c->log, "ngx_event_close: already closed"); - if ((rc = ngx_close_socket(cn->fd)) == -1) - ngx_log_error(NGX_LOG_ERR, ev->log, ngx_socket_errno, + ngx_destroy_pool(c->pool); + + if ((rc = ngx_close_socket(c->fd)) == -1) + ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno, "ngx_event_close: close failed"); - if (cn->read->next) - ngx_del_event(cn->read, NGX_READ_EVENT); + if (c->read->next) + ngx_del_event(c->read, NGX_READ_EVENT); - if (cn->write->next) - ngx_del_event(cn->write, NGX_WRITE_EVENT); + if (c->write->next) + ngx_del_event(c->write, NGX_WRITE_EVENT); - cn->fd = -1; + c->fd = -1; return rc; } diff --git a/src/event/ngx_event_recv.c b/src/event/ngx_event_recv.c --- a/src/event/ngx_event_recv.c +++ b/src/event/ngx_event_recv.c @@ -6,29 +6,27 @@ #include #include -int ngx_event_recv_core(ngx_event_t *ev, char *buf, size_t size) +int ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size) { int n; ngx_err_t err; - ngx_connection_t *c; - c = (ngx_connection_t *) ev->data; - - if (ev->timedout) { + if (c->read->timedout) { ngx_set_socket_errno(NGX_ETIMEDOUT); - ngx_log_error(NGX_LOG_ERR, ev->log, NGX_ETIMEDOUT, "recv() failed"); + ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "recv() failed"); return NGX_ERROR; } #if (HAVE_KQUEUE) - ngx_log_debug(ev->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _ - ev->eof _ ev->available _ ev->error); + ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _ + c->read->eof _ c->read->available _ c->read->error); #if !(USE_KQUEUE) if (ngx_event_type == NGX_KQUEUE_EVENT) #endif - if (ev->eof && ev->available == 0) { - if (ev->error) { - ngx_log_error(NGX_LOG_ERR, ev->log, ev->error, "recv() failed"); + if (c->read->eof && c->read->available == 0) { + if (c->read->error) { + ngx_log_error(NGX_LOG_ERR, c->log, c->read->error, + "recv() failed"); return NGX_ERROR; } @@ -42,11 +40,11 @@ int ngx_event_recv_core(ngx_event_t *ev, err = ngx_socket_errno; if (err == NGX_EAGAIN) { - ngx_log_error(NGX_LOG_INFO, ev->log, err, "recv() returns EAGAIN"); + ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returns EAGAIN"); return NGX_AGAIN; } - ngx_log_error(NGX_LOG_ERR, ev->log, err, "recv() failed"); + ngx_log_error(NGX_LOG_ERR, c->log, err, "recv() failed"); return NGX_ERROR; } @@ -54,7 +52,7 @@ int ngx_event_recv_core(ngx_event_t *ev, #if !(USE_KQUEUE) if (ngx_event_type == NGX_KQUEUE_EVENT) #endif - ev->available -= n; + c->read->available -= n; #endif return n; 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 @@ -17,6 +17,7 @@ int ngx_http_init(ngx_pool_t *pool, ngx_ { ngx_listen_t *ls; + ngx_http_server.header_timeout = 20000; ngx_http_server.buff_size = 1024; #if (WIN32) ngx_http_server.doc_root = "html"; 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 @@ -4,15 +4,11 @@ #include #include +#include #include #include -#define NGX_SYS_ERROR -1 -#define NGX_HTTP_INVALID_METHOD -2 -#define NGX_HTTP_INVALID_REQUEST -3 -#define NGX_HTTP_INVALID_HEADER -4 - #define NGX_HTTP_GET 1 #define NGX_HTTP_HEAD 2 #define NGX_HTTP_POST 3 @@ -20,10 +16,17 @@ #define NGX_HTTP_CONN_CLOSE 0 #define NGX_HTTP_CONN_KEEP_ALIVE 1 -#define NGX_OK 0 + +#define NGX_HTTP_HEADER_DONE 1 +#define NGX_HTTP_INVALID_METHOD 10 +#define NGX_HTTP_INVALID_REQUEST 11 +#define NGX_HTTP_INVALID_HEAD 12 +#define NGX_HTTP_INVALID_HEADER 13 + #define NGX_HTTP_OK 200 #define NGX_HTTP_MOVED_PERMANENTLY 302 +#define NGX_HTTP_BAD_REQUEST 400 #define NGX_HTTP_NOT_FOUND 404 #define NGX_HTTP_INTERNAL_SERVER_ERROR 503 @@ -40,9 +43,11 @@ typedef struct { #define ngx_get_module_ctx(r, module) (module)->ctx typedef struct { - char *doc_root; - size_t doc_root_len; - size_t buff_size; + char *doc_root; + size_t doc_root_len; + size_t buff_size; + + unsigned int header_timeout; } ngx_http_server_t; typedef struct { @@ -72,6 +77,12 @@ struct ngx_http_request_s { char *location; ngx_fd_t fd; + ngx_pool_t *pool; + ngx_hunk_t *header_in; + +/* + ngx_http_headers_in_t *headers_in; +*/ ngx_http_headers_out_t *headers_out; int filename_len; @@ -90,11 +101,11 @@ struct ngx_http_request_s { ngx_connection_t *connection; ngx_http_server_t *server; - ngx_buff_t *buff; - ngx_pool_t *pool; int filter; + unsigned header_timeout:1; + unsigned header_only:1; unsigned unusual_uri:1; unsigned complex_uri:1; 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 @@ -15,12 +15,12 @@ int ngx_http_init_connection(ngx_connect static int ngx_http_init_request(ngx_event_t *ev); static int ngx_http_process_request(ngx_event_t *ev); -static int ngx_process_http_request_line(ngx_http_request_t *r); -static int ngx_process_http_request_header(ngx_http_request_t *r); +static int ngx_http_process_request_line(ngx_http_request_t *r); +static int ngx_http_process_request_header(ngx_http_request_t *r); -static int ngx_process_http_request(ngx_http_request_t *r); +static int ngx_http_process_http_request(ngx_http_request_t *r); -static int ngx_http_close_request(ngx_event_t *ev); +static int ngx_http_close_request(ngx_http_request_t *r); static size_t ngx_http_log_error(void *data, char *buf, size_t len); @@ -28,6 +28,13 @@ static size_t ngx_http_log_error(void *d static int ngx_http_writer(ngx_event_t *ev); +static char *header_errors[] = { + "client %s sent invalid method", + "client %s sent invalid request", + "client %s sent HEAD method in HTTP/0.9 request" +}; + + int ngx_http_init_connection(ngx_connection_t *c) { @@ -57,13 +64,12 @@ int ngx_http_init_connection(ngx_connect c->log->data = ctx; c->log->handler = ngx_http_log_error; - ngx_add_timer(ev, c->post_accept_timeout); - #if (HAVE_DEFERRED_ACCEPT) - if (ev->ready) + if (ev->ready) { return ngx_http_init_request(ev); - else + } else { #endif + ngx_add_timer(ev, c->post_accept_timeout); #if (USE_KQUEUE) return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT); #else @@ -76,9 +82,11 @@ int ngx_http_init_connection(ngx_connect if (ngx_event_type == NGX_KQUEUE_EVENT) return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT); else -#else +#endif return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT); -#endif +#endif /* USE_KQUEUE */ +#if (HAVE_DEFERRED_ACCEPT) + } #endif } @@ -99,21 +107,16 @@ int ngx_http_init_request(ngx_event_t *e r->connection = c; r->server = srv; - ngx_test_null(r->pool, ngx_create_pool(16384, ev->log), NGX_ERROR); + /* TODO: request's pool size */ + ngx_test_null(r->pool, ngx_create_pool(16384, ev->log), + ngx_http_close_request(r)); - /* TODO: buff -> hunk */ - ngx_test_null(r->buff, ngx_palloc(r->pool, sizeof(ngx_buff_t)), NGX_ERROR); - ngx_test_null(r->buff->buff, ngx_palloc(r->pool, srv->buff_size), - NGX_ERROR); - - r->buff->pos = r->buff->last = r->buff->buff; - r->buff->end = r->buff->buff + srv->buff_size; - - r->state_handler = ngx_process_http_request_line; + ngx_test_null(r->header_in, + ngx_create_temp_hunk(r->pool, srv->buff_size, 0, 0), + ngx_http_close_request(r)); ev->event_handler = ngx_http_process_request; - ev->close_handler = ngx_http_close_request; - c->write->close_handler = ngx_http_close_request; + r->state_handler = ngx_http_process_request_line; return ngx_http_process_request(ev); } @@ -121,7 +124,7 @@ int ngx_http_init_request(ngx_event_t *e int ngx_http_process_request(ngx_event_t *ev) { - int n; + int n, rc; ngx_connection_t *c ; ngx_http_request_t *r; @@ -130,79 +133,128 @@ int ngx_http_process_request(ngx_event_t ngx_log_debug(ev->log, "http process request"); - n = ngx_event_recv(ev, r->buff->last, r->buff->end - r->buff->last); - - if (n == NGX_AGAIN) - return NGX_AGAIN; + n = ngx_event_recv(c, r->header_in->last.mem, + r->header_in->end - r->header_in->last.mem); - if (n == NGX_ERROR) { - /* close request */ - return NGX_ERROR; + if (n == NGX_AGAIN) { + if (!r->header_timeout) { + r->header_timeout = 1; + ngx_del_timer(ev); + ngx_add_timer(ev, r->server->header_timeout); + } + return NGX_AGAIN; } + if (n == NGX_ERROR) + return ngx_http_close_request(r); + ngx_log_debug(ev->log, "http read %d" _ n); if (n == 0) { - if (ev->unexpected_eof) { - ngx_log_error(NGX_LOG_INFO, ev->log, 0, "connection is closed"); - /* close request */ - return NGX_ERROR; - } + /* STUB: c-> */ + if (ev->unexpected_eof) + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client prematurely closed connection"); - return ngx_http_close_request(ev); + return ngx_http_close_request(r); } - if (!ev->read_discarded) { - r->buff->last += n; + r->header_in->last.mem += n; + + /* state_handlers are called in following order: + ngx_http_process_request_line(r) + ngx_http_process_request_header(r) */ + + do { + rc = (r->state_handler)(r); - /* state_handlers are called in following order: - ngx_process_http_request_line() - ngx_process_http_request_header() */ + if (rc == NGX_ERROR) + return rc; + + /* rc == NGX_OK || rc == NGX_AGAIN */ - do { - if ((r->state_handler)(r) < 0) - return -1; - } while (r->buff->pos < r->buff->last); + } while (r->header_in->pos.mem < r->header_in->last.mem); + + if (!r->header_timeout) { + r->header_timeout = 1; + ngx_del_timer(ev); + ngx_add_timer(ev, r->server->header_timeout); } - if (ngx_del_event(ev, NGX_TIMER_EVENT) == -1) - return -1; - - if (ngx_add_event(ev, NGX_TIMER_EVENT, ev->timer) == -1) - return -1; - - return 0; + return rc; } -static int ngx_process_http_request_line(ngx_http_request_t *r) +static int ngx_http_process_request_line(ngx_http_request_t *r) { - int n; + int rc; + ngx_http_log_ctx_t *ctx; + + rc = ngx_read_http_request_line(r); + + if (rc == NGX_OK) { + ngx_test_null(r->uri, + ngx_palloc(r->pool, r->uri_end - r->uri_start + 1), + ngx_http_close_request(r)); + ngx_cpystrn(r->uri, r->uri_start, r->uri_end - r->uri_start + 1); - if ((n = ngx_read_http_request_line(r)) == 1) { - *r->uri_end = '\0'; ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s" _ - r->method _ r->http_version _ r->uri_start); - r->state_handler = ngx_process_http_request_header; + r->method _ r->http_version _ r->uri); + + if (r->http_version == 9) { + /* set lock event */ + return ngx_http_process_http_request(r); + } + + r->state_handler = ngx_http_process_request_header; r->connection->read->action = "reading client request headers"; + + return NGX_OK; } - return n; + r->connection->log->handler = NULL; + ctx = r->connection->log->data; + + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + header_errors[rc - NGX_HTTP_INVALID_METHOD], ctx->client); + + r->connection->log->handler = ngx_http_log_error; + + /* STUB return ngx_http_error(r, NGX_HTTP_BAD_REQUEST) */ + return ngx_http_close_request(r); } -static int ngx_process_http_request_header(ngx_http_request_t *r) +static int ngx_http_process_request_header(ngx_http_request_t *r) { - int n; + int rc; + ngx_http_log_ctx_t *ctx; + + for ( ;; ) { + rc = ngx_read_http_header_line(r); + + if (rc == NGX_OK) { + *r->header_name_end = '\0'; + *r->header_end = '\0'; + ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _ + r->header_name_start _ r->header_start); - while ((n = ngx_read_http_header_line(r)) == 1) { - *r->header_name_end = '\0'; - *r->header_end = '\0'; - ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _ - r->header_name_start _ r->header_start); + } else if (rc == NGX_AGAIN) { + return NGX_AGAIN; + + } else if (rc == NGX_HTTP_HEADER_DONE) { + break; + + } else if (rc == NGX_HTTP_INVALID_HEADER) { + r->connection->log->handler = NULL; + ctx = r->connection->log->data; + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client %s sent invalid header", ctx->client); + r->connection->log->handler = ngx_http_log_error; + + /* STUB return ngx_http_error(r, NGX_HTTP_BAD_REQUEST) */ + return ngx_http_close_request(r); + } } - if (n != 2) - return n; - r->state_handler = NULL; r->connection->read->action = "reading client request body"; @@ -210,7 +262,9 @@ static int ngx_process_http_request_head r->connection->read->unexpected_eof = 0; ngx_log_debug(r->connection->log, "HTTP header done"); - return ngx_process_http_request(r); + ngx_del_timer(r->connection->read); + + return ngx_http_process_http_request(r); } #if 0 @@ -221,7 +275,7 @@ static int ngx_http_lock_read(ngx_event_ } #endif -static int ngx_process_http_request(ngx_http_request_t *r) +static int ngx_http_process_http_request(ngx_http_request_t *r) { int err, rc; char *name, *loc, *file; @@ -489,16 +543,16 @@ static int ngx_process_http_request(ngx_ #endif -static int ngx_http_close_request(ngx_event_t *ev) +static int ngx_http_close_request(ngx_http_request_t *r) { - ngx_connection_t *c = (ngx_connection_t *) ev->data; + ngx_destroy_pool(r->pool); - ngx_log_debug(ev->log, "http close"); + ngx_log_debug(r->connection->log, "http close"); - ngx_del_event(c->read, NGX_TIMER_EVENT); - ngx_del_event(c->write, NGX_TIMER_EVENT); + ngx_del_event(r->connection->read, NGX_TIMER_EVENT); + ngx_del_event(r->connection->write, NGX_TIMER_EVENT); - return ngx_event_close_connection(ev); + return NGX_ERROR; } diff --git a/src/http/ngx_http_filter.c b/src/http/ngx_http_filter.c --- a/src/http/ngx_http_filter.c +++ b/src/http/ngx_http_filter.c @@ -141,7 +141,7 @@ int ngx_http_filter(ngx_http_request_t * ngx_test_null(ctx->hunk, ngx_create_temp_hunk(r->pool, size, - 50, 50), + 50, 50), NGX_ERROR); rc = ngx_http_filter_copy_hunk(ctx->hunk, 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 @@ -1,47 +1,47 @@ #include +#include #include int ngx_read_http_request_line(ngx_http_request_t *r) { char ch; - char *buff = r->buff->buff; - char *p = r->buff->pos; + char *p = r->header_in->pos.mem; enum { - rl_start = 0, - rl_space_after_method, - rl_spaces_before_uri, - rl_after_slash_in_uri, - rl_check_uri, - rl_uri, - rl_http_09, - rl_http_version, - rl_first_major_digit, - rl_major_digit, - rl_first_minor_digit, - rl_minor_digit, - rl_almost_done, - rl_done + sw_start = 0, + sw_space_after_method, + sw_spaces_before_uri, + sw_after_slash_in_uri, + sw_check_uri, + sw_uri, + sw_http_09, + sw_http_version, + sw_first_major_digit, + sw_major_digit, + sw_first_minor_digit, + sw_minor_digit, + sw_almost_done, + sw_done } state = r->state; - while (p < r->buff->last && state < rl_done) { + 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->buff->last, ch, p); + state, p, r->header_in->last, ch, p); */ - /* GCC complie it as jump table */ + /* GCC compiles switch as jump table */ switch (state) { /* HTTP methods: GET, HEAD, POST */ - case rl_start: + case sw_start: switch (ch) { case 'G': - if (p + 1 >= r->buff->last) - return 0; + if (p + 1 >= r->header_in->last.mem) + return NGX_AGAIN; if (*p != 'E' || *(p + 1) != 'T') return NGX_HTTP_INVALID_METHOD; @@ -51,8 +51,8 @@ printf("\nstate: %d, pos: %x, end: %x, c break; case 'H': - if (p + 2 >= r->buff->last) - return 0; + if (p + 2 >= r->header_in->last.mem) + return NGX_AGAIN; if (*p != 'E' || *(p + 1) != 'A' || *(p + 2) != 'D') return NGX_HTTP_INVALID_METHOD; @@ -62,8 +62,8 @@ printf("\nstate: %d, pos: %x, end: %x, c break; case 'P': - if (p + 2 >= r->buff->last) - return 0; + if (p + 2 >= r->header_in->last.mem) + return NGX_AGAIN; if (*p != 'O' || *(p + 1) != 'S' || *(p + 2) != 'T') return NGX_HTTP_INVALID_METHOD; @@ -76,14 +76,14 @@ printf("\nstate: %d, pos: %x, end: %x, c return NGX_HTTP_INVALID_METHOD; } - state = rl_space_after_method; + state = sw_space_after_method; break; /* single space after method */ - case rl_space_after_method: + case sw_space_after_method: switch (ch) { case ' ': - state = rl_spaces_before_uri; + state = sw_spaces_before_uri; break; default: return NGX_HTTP_INVALID_METHOD; @@ -91,123 +91,123 @@ printf("\nstate: %d, pos: %x, end: %x, c break; /* space* before URI */ - case rl_spaces_before_uri: + case sw_spaces_before_uri: switch (ch) { case '/': r->uri_start = p - 1; - state = rl_after_slash_in_uri; + state = sw_after_slash_in_uri; break; case ' ': break; default: r->unusual_uri = 1; r->uri_start = p - 1; - state = rl_uri; + state = sw_uri; break; } break; /* check dot after slash */ - case rl_after_slash_in_uri: + case sw_after_slash_in_uri: switch (ch) { case CR: r->uri_end = p - 1; r->http_minor = 9; - state = rl_almost_done; + state = sw_almost_done; break; case LF: r->uri_end = p - 1; r->http_minor = 9; - state = rl_done; + state = sw_done; break; case ' ': r->uri_end = p - 1; - state = rl_http_09; + state = sw_http_09; break; case '.': r->complex_uri = 1; - state = rl_uri; + state = sw_uri; break; case '/': r->complex_uri = 1; - state = rl_uri; + state = sw_uri; break; case '?': r->args_start = p; - state = rl_uri; + state = sw_uri; break; default: - state = rl_check_uri; + state = sw_check_uri; break; } break; /* check slash in URI */ - case rl_check_uri: + case sw_check_uri: switch (ch) { case CR: r->uri_end = p - 1; r->http_minor = 9; - state = rl_almost_done; + state = sw_almost_done; break; case LF: r->uri_end = p - 1; r->http_minor = 9; - state = rl_done; + state = sw_done; break; case ' ': r->uri_end = p - 1; - state = rl_http_09; + state = sw_http_09; break; case '.': r->uri_ext = p; break; case '/': r->uri_ext = NULL; - state = rl_after_slash_in_uri; + state = sw_after_slash_in_uri; break; case '?': r->args_start = p; - state = rl_uri; + state = sw_uri; break; } break; /* URI */ - case rl_uri: + case sw_uri: switch (ch) { case CR: r->uri_end = p - 1; r->http_minor = 9; - state = rl_almost_done; + state = sw_almost_done; break; case LF: r->uri_end = p - 1; r->http_minor = 9; - state = rl_done; + state = sw_done; break; case ' ': r->uri_end = p - 1; - state = rl_http_09; + state = sw_http_09; break; } break; /* space+ after URI */ - case rl_http_09: + case sw_http_09: switch (ch) { case ' ': break; case CR: r->http_minor = 9; - state = rl_almost_done; + state = sw_almost_done; break; case LF: r->http_minor = 9; - state = rl_done; + state = sw_done; break; case 'H': - state = rl_http_version; + state = sw_http_version; break; default: return NGX_HTTP_INVALID_REQUEST; @@ -215,33 +215,33 @@ printf("\nstate: %d, pos: %x, end: %x, c break; /* TTP/ */ - case rl_http_version: - if (p + 2 >= r->buff->last) { - r->state = rl_http_version; - r->buff->pos = p - 1; - return 0; + case sw_http_version: + if (p + 2 >= r->header_in->last.mem) { + r->state = sw_http_version; + r->header_in->pos.mem = p - 1; + return NGX_AGAIN; } if (ch != 'T' || *p != 'T' || *(p + 1) != 'P' || *(p + 2) != '/') return NGX_HTTP_INVALID_REQUEST; p += 3; - state = rl_first_major_digit; + state = sw_first_major_digit; break; /* first digit of major HTTP version */ - case rl_first_major_digit: + case sw_first_major_digit: if (ch < '1' || ch > '9') return NGX_HTTP_INVALID_REQUEST; r->http_major = ch - '0'; - state = rl_major_digit; + state = sw_major_digit; break; /* major HTTP version or dot */ - case rl_major_digit: + case sw_major_digit: if (ch == '.') { - state = rl_first_minor_digit; + state = sw_first_minor_digit; break; } @@ -252,24 +252,24 @@ printf("\nstate: %d, pos: %x, end: %x, c break; /* first digit of minor HTTP version */ - case rl_first_minor_digit: + case sw_first_minor_digit: if (ch < '0' || ch > '9') return NGX_HTTP_INVALID_REQUEST; r->http_minor = ch - '0'; - state = rl_minor_digit; + state = sw_minor_digit; break; /* minor HTTP version or end of request line */ - case rl_minor_digit: + case sw_minor_digit: if (ch == CR) { - state = rl_almost_done; + state = sw_almost_done; break; } if (ch == LF) { - state = rl_done; + state = sw_done; break; } @@ -280,70 +280,72 @@ printf("\nstate: %d, pos: %x, end: %x, c break; /* end of request line */ - case rl_almost_done: + case sw_almost_done: switch (ch) { case LF: - state = rl_done; + state = sw_done; break; default: - return NGX_HTTP_INVALID_METHOD; + return NGX_HTTP_INVALID_REQUEST; } break; } } - r->buff->pos = p; + r->header_in->pos.mem = p; - if (state == rl_done) { + if (state == sw_done) { r->http_version = r->http_major * 1000 + r->http_minor; - r->state = rl_start; - return 1; + r->state = sw_start; + if (r->http_version == 9 && r->method == NGX_HTTP_HEAD) + return NGX_HTTP_INVALID_HEAD; + else + return NGX_OK; } else { r->state = state; - return 0; + return NGX_AGAIN; } } int ngx_read_http_header_line(ngx_http_request_t *r) { char c, ch; - char *buff = r->buff->buff; - char *p = r->buff->pos; + char *p = r->header_in->pos.mem; enum { - hl_start = 0, - hl_name, - hl_space_before_value, - hl_value, - hl_space_after_value, - hl_almost_done, - header_almost_done, - hl_done, - header_done + sw_start = 0, + sw_name, + sw_space_before_value, + sw_value, + sw_space_after_value, + sw_almost_done, + sw_header_almost_done, + sw_done, + sw_header_done } state = r->state; - while (p < r->buff->last && state < hl_done) { + 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->buff->last, ch, p); + state, p, r->header_in->last.mem, ch, p); */ switch (state) { /* first char */ - case hl_start: + case sw_start: switch (ch) { case CR: r->header_end = p - 1; - state = header_almost_done; + state = sw_header_almost_done; break; case LF: r->header_end = p - 1; - state = header_done; + state = sw_header_done; break; default: - state = hl_name; + state = sw_name; r->header_name_start = p - 1; c = ch | 0x20; @@ -362,14 +364,14 @@ printf("\nstate: %d, pos: %x, end: %x, c break; /* header name */ - case hl_name: + case sw_name: c = ch | 0x20; if (c >= 'a' && c <= 'z') break; if (ch == ':') { r->header_name_end = p - 1; - state = hl_space_before_value; + state = sw_space_before_value; break; } @@ -382,65 +384,65 @@ printf("\nstate: %d, pos: %x, end: %x, c return NGX_HTTP_INVALID_HEADER; /* space* before header value */ - case hl_space_before_value: + case sw_space_before_value: switch (ch) { case ' ': break; case CR: r->header_start = r->header_end = p - 1; - state = hl_almost_done; + state = sw_almost_done; break; case LF: r->header_start = r->header_end = p - 1; - state = hl_done; + state = sw_done; break; default: r->header_start = p - 1; - state = hl_value; + state = sw_value; break; } break; /* header value */ - case hl_value: + case sw_value: switch (ch) { case ' ': r->header_end = p - 1; - state = hl_space_after_value; + state = sw_space_after_value; break; case CR: r->header_end = p - 1; - state = hl_almost_done; + state = sw_almost_done; break; case LF: r->header_end = p - 1; - state = hl_done; + state = sw_done; break; } break; /* space* before end of header line */ - case hl_space_after_value: + case sw_space_after_value: switch (ch) { case ' ': break; case CR: - state = hl_almost_done; + state = sw_almost_done; break; case LF: - state = hl_done; + state = sw_done; break; default: - state = hl_value; + state = sw_value; break; } break; /* end of header line */ - case hl_almost_done: + case sw_almost_done: switch (ch) { case LF: - state = hl_done; + state = sw_done; break; default: return NGX_HTTP_INVALID_HEADER; @@ -448,10 +450,10 @@ printf("\nstate: %d, pos: %x, end: %x, c break; /* end of header */ - case header_almost_done: + case sw_header_almost_done: switch (ch) { case LF: - state = header_done; + state = sw_header_done; break; default: return NGX_HTTP_INVALID_HEADER; @@ -460,16 +462,16 @@ printf("\nstate: %d, pos: %x, end: %x, c } } - r->buff->pos = p; + r->header_in->pos.mem = p; - if (state == hl_done) { - r->state = hl_start; - return 1; - } else if (state == header_done) { - r->state = hl_start; - return 2; + if (state == sw_done) { + r->state = sw_start; + return NGX_OK; + } else if (state == sw_header_done) { + r->state = sw_start; + return NGX_HTTP_HEADER_DONE; } else { r->state = state; - return 0; + return NGX_AGAIN; } }