From f7abd72716bf9499581a010d7c2bf21da7987ba9 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Thu, 23 Sep 2004 06:32:00 +0000 Subject: nginx-0.0.11-2004-09-23-10:32:00 import --- src/core/ngx_buf.c | 4 +- src/core/ngx_palloc.c | 15 +- src/core/ngx_palloc.h | 2 +- src/http/ngx_http_core_module.c | 41 ++- src/http/ngx_http_core_module.h | 9 +- src/http/ngx_http_request.c | 728 +++++++++++++++++++--------------------- src/http/ngx_http_request.h | 4 + src/os/unix/ngx_freebsd_init.c | 4 +- 8 files changed, 385 insertions(+), 422 deletions(-) diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c index 9c5266a73..16398a638 100644 --- a/src/core/ngx_buf.c +++ b/src/core/ngx_buf.c @@ -21,6 +21,7 @@ ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size) b->temporary = 1; /* + b->file_pos = 0; b->file_last = 0; @@ -28,7 +29,8 @@ ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size) b->shadow = NULL; b->tag = 0; - */ + + */ return b; } diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c index 37a0868c1..132eb70d7 100644 --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -44,8 +44,9 @@ void ngx_destroy_pool(ngx_pool_t *pool) */ for (p = pool, n = pool->next; /* void */; p = n, n = n->next) { - ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, - "free: " PTR_FMT, p); + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0, + "free: " PTR_FMT ", unused: " SIZE_T_FMT, + p, p->end - p->last); if (n == NULL) { break; @@ -71,7 +72,7 @@ void *ngx_palloc(ngx_pool_t *pool, size_t size) ngx_pool_large_t *large, *last; if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL - && size <= (size_t) (pool->end - (char *) pool)) + && size <= (size_t) (pool->end - (char *) pool) - sizeof(ngx_pool_t)) { for (p = pool, n = pool->next; /* void */; p = n, n = n->next) { m = ngx_align(p->last); @@ -106,7 +107,7 @@ void *ngx_palloc(ngx_pool_t *pool, size_t size) last = NULL; if (pool->large) { - for (last = pool->large; /* void */; last = last->next) { + for (last = pool->large; /* void */ ; last = last->next) { if (last->alloc == NULL) { large = last; last = NULL; @@ -150,7 +151,7 @@ void *ngx_palloc(ngx_pool_t *pool, size_t size) } -void ngx_pfree(ngx_pool_t *pool, void *p) +ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p) { ngx_pool_large_t *l; @@ -160,8 +161,12 @@ void ngx_pfree(ngx_pool_t *pool, void *p) "free: " PTR_FMT, l->alloc); free(l->alloc); l->alloc = NULL; + + return NGX_OK; } } + + return NGX_DECLINED; } diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h index 667bef514..1700efb45 100644 --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -43,7 +43,7 @@ void ngx_destroy_pool(ngx_pool_t *pool); void *ngx_palloc(ngx_pool_t *pool, size_t size); void *ngx_pcalloc(ngx_pool_t *pool, size_t size); -void ngx_pfree(ngx_pool_t *pool, void *p); +ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p); #endif /* _NGX_PALLOC_H_INCLUDED_ */ diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 325a8fe03..9f29c5706 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -96,18 +96,11 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size), NULL }, - { ngx_string("client_large_buffers"), + { ngx_string("large_client_header_buffers"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2, ngx_conf_set_bufs_slot, NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, client_large_buffers), - NULL }, - - { ngx_string("large_client_header"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, large_client_header), + offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers), NULL }, { ngx_string("restrict_host_names"), @@ -241,6 +234,13 @@ static ngx_command_t ngx_http_core_commands[] = { 0, NULL }, + { ngx_string("keepalive_buffers"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, keepalive_buffers), + NULL }, + { ngx_string("lingering_time"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -1275,7 +1275,6 @@ static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf) cscf->request_pool_size = NGX_CONF_UNSET_SIZE; cscf->client_header_timeout = NGX_CONF_UNSET_MSEC; cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE; - cscf->large_client_header = NGX_CONF_UNSET; cscf->restrict_host_names = NGX_CONF_UNSET_UINT; return cscf; @@ -1333,7 +1332,7 @@ static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf, } ngx_conf_merge_size_value(conf->connection_pool_size, - prev->connection_pool_size, 16384); + prev->connection_pool_size, 2048); ngx_conf_merge_msec_value(conf->post_accept_timeout, prev->post_accept_timeout, 30000); ngx_conf_merge_size_value(conf->request_pool_size, @@ -1342,10 +1341,17 @@ static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf, prev->client_header_timeout, 60000); ngx_conf_merge_size_value(conf->client_header_buffer_size, prev->client_header_buffer_size, 1024); - ngx_conf_merge_bufs_value(conf->client_large_buffers, - prev->client_large_buffers, 4, ngx_pagesize); - ngx_conf_merge_value(conf->large_client_header, - prev->large_client_header, 1); + ngx_conf_merge_bufs_value(conf->large_client_header_buffers, + prev->large_client_header_buffers, + 4, ngx_pagesize); + + if (conf->large_client_header_buffers.size < conf->connection_pool_size) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the \"large_client_header_buffers\" size must be " + "equal to or bigger than \"connection_pool_size\""); + return NGX_CONF_ERROR; + } + ngx_conf_merge_unsigned_value(conf->restrict_host_names, prev->restrict_host_names, 0); @@ -1387,9 +1393,9 @@ static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf) lcf->send_lowat = NGX_CONF_UNSET_SIZE; lcf->postpone_output = NGX_CONF_UNSET_SIZE; lcf->limit_rate = NGX_CONF_UNSET_SIZE; - lcf->discarded_buffer_size = NGX_CONF_UNSET_SIZE; lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; lcf->keepalive_header = NGX_CONF_UNSET; + lcf->keepalive_buffers = NGX_CONF_UNSET; lcf->lingering_time = NGX_CONF_UNSET_MSEC; lcf->lingering_timeout = NGX_CONF_UNSET_MSEC; lcf->reset_timedout_connection = NGX_CONF_UNSET; @@ -1474,12 +1480,11 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output, 1460); ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0); - ngx_conf_merge_size_value(conf->discarded_buffer_size, - prev->discarded_buffer_size, 1500); ngx_conf_merge_msec_value(conf->keepalive_timeout, prev->keepalive_timeout, 75000); ngx_conf_merge_sec_value(conf->keepalive_header, prev->keepalive_header, 0); + ngx_conf_merge_value(conf->keepalive_buffers, prev->keepalive_buffers, 1); ngx_conf_merge_msec_value(conf->lingering_time, prev->lingering_time, 30000); ngx_conf_merge_msec_value(conf->lingering_timeout, diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 0122b8b09..7de7d1bed 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -66,14 +66,12 @@ typedef struct { size_t request_pool_size; size_t client_header_buffer_size; - ngx_bufs_t client_large_buffers; + ngx_bufs_t large_client_header_buffers; ngx_msec_t post_accept_timeout; ngx_msec_t client_header_timeout; ngx_uint_t restrict_host_names; - - ngx_flag_t large_client_header; } ngx_http_core_srv_conf_t; @@ -153,7 +151,6 @@ struct ngx_http_core_loc_conf_s { ngx_str_t default_type; size_t client_max_body_size; /* client_max_body_size */ - size_t discarded_buffer_size; /* discarded_buffer_size */ size_t client_body_buffer_size; /* client_body_buffer_size */ size_t send_lowat; /* send_lowat */ size_t postpone_output; /* postpone_output */ @@ -162,10 +159,12 @@ struct ngx_http_core_loc_conf_s { ngx_msec_t client_body_timeout; /* client_body_timeout */ ngx_msec_t send_timeout; /* send_timeout */ ngx_msec_t keepalive_timeout; /* keepalive_timeout */ - time_t keepalive_header; /* keepalive_timeout */ ngx_msec_t lingering_time; /* lingering_time */ ngx_msec_t lingering_timeout; /* lingering_timeout */ + time_t keepalive_header; /* keepalive_timeout */ + + ngx_flag_t keepalive_buffers; /* keepalive_buffers */ ngx_flag_t sendfile; /* sendfile */ ngx_flag_t tcp_nopush; /* tcp_nopush */ ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 49ca93ac0..8144d0a47 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -12,8 +12,8 @@ static void ngx_http_ssl_handshake(ngx_event_t *rev); static void ngx_http_process_request_line(ngx_event_t *rev); static void ngx_http_process_request_headers(ngx_event_t *rev); static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); -static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, - ngx_uint_t request_line); +static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, + ngx_uint_t request_line); static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r); static void ngx_http_set_write_handler(ngx_http_request_t *r); @@ -195,19 +195,9 @@ static void ngx_http_init_request(ngx_event_t *rev) return; } - if (c->data) { - hc = c->data; - r = hc->request; + hc = c->data; - ngx_memzero(r, sizeof(ngx_http_request_t)); - - r->pipeline = hc->pipeline; - -#if (NGX_STAT_STUB) - (*ngx_stat_reading)++; -#endif - - } else { + if (hc == NULL) { if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)))) { #if (NGX_STAT_STUB) @@ -217,7 +207,24 @@ static void ngx_http_init_request(ngx_event_t *rev) ngx_http_close_connection(c); return; } + } + + r = hc->request; + + if (r) { + ngx_memzero(r, sizeof(ngx_http_request_t)); + + r->pipeline = hc->pipeline; + + if (hc->nbusy) { + r->header_in = hc->busy[0]; + } +#if (NGX_STAT_STUB) + (*ngx_stat_reading)++; +#endif + + } else { if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) { #if (NGX_STAT_STUB) @@ -355,6 +362,10 @@ static void ngx_http_init_request(ngx_event_t *rev) } } + if (r->header_in == NULL) { + r->header_in = c->buffer; + } + if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) { ngx_http_close_connection(c); return; @@ -387,7 +398,6 @@ static void ngx_http_init_request(ngx_event_t *rev) c->single_connection = 1; r->connection = c; - r->header_in = c->buffer; r->file.fd = NGX_INVALID_FILE; @@ -470,13 +480,12 @@ static void ngx_http_ssl_handshake(ngx_event_t *rev) static void ngx_http_process_request_line(ngx_event_t *rev) { - u_char *p; - ssize_t n; - ngx_int_t rc, offset; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_log_ctx_t *ctx; - ngx_http_core_srv_conf_t *cscf; + u_char *p; + ssize_t n; + ngx_int_t rc, rv, offset; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; c = rev->data; r = c->data; @@ -489,280 +498,218 @@ static void ngx_http_process_request_line(ngx_event_t *rev) return; } - n = ngx_http_read_request_header(r); - - if (n == NGX_AGAIN || n == NGX_ERROR) { - return; - } - - rc = ngx_http_parse_request_line(r, r->header_in); - - if (rc == NGX_OK) { - - /* the request line has been parsed successfully */ + rc = NGX_AGAIN; - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + for ( ;; ) { - if (r->http_version >= NGX_HTTP_VERSION_10 - && cscf->large_client_header == 0 - && r->header_in->pos == r->header_in->end) - { - /* no space for "\r\n" at the end of the header */ + if (rc == NGX_AGAIN) { + n = ngx_http_read_request_header(r); - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI, - NGX_HTTP_REQUEST_URI_TOO_LARGE); - return; + if (n == NGX_AGAIN || n == NGX_ERROR) { + return; + } } + rc = ngx_http_parse_request_line(r, r->header_in); - /* copy unparsed URI */ - - r->unparsed_uri.len = r->uri_end - r->uri_start; - r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1); - if (r->unparsed_uri.data == NULL) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } + if (rc == NGX_OK) { - ngx_cpystrn(r->unparsed_uri.data, r->uri_start, - r->unparsed_uri.len + 1); + /* the request line has been parsed successfully */ + /* copy unparsed URI */ - /* copy URI */ + r->unparsed_uri.len = r->uri_end - r->uri_start; + r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1); + if (r->unparsed_uri.data == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } - if (r->args_start) { - r->uri.len = r->args_start - 1 - r->uri_start; - } else { - r->uri.len = r->uri_end - r->uri_start; - } + ngx_cpystrn(r->unparsed_uri.data, r->uri_start, + r->unparsed_uri.len + 1); - if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } - if (r->complex_uri) { - rc = ngx_http_parse_complex_uri(r); + /* copy URI */ - if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { - ngx_http_close_request(r, rc); - ngx_http_close_connection(c); - return; + if (r->args_start) { + r->uri.len = r->args_start - 1 - r->uri_start; + } else { + r->uri.len = r->uri_end - r->uri_start; } - if (rc != NGX_OK) { - r->request_line.len = r->request_end - r->request_start; - r->request_line.data = r->request_start; - - ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); + if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); return; } - } else { - ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); - } - + if (r->complex_uri) { + rc = ngx_http_parse_complex_uri(r); - r->request_line.len = r->request_end - r->request_start; + if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { + ngx_http_close_request(r, rc); + ngx_http_close_connection(c); + return; + } - if (cscf->large_client_header) { + if (rc != NGX_OK) { + r->request_line.len = r->request_end - r->request_start; + r->request_line.data = r->request_start; - /* - * if the large client headers are enabled then - * we need to copy the request line - */ + ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); + return; + } - r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1); - if (r->request_line.data == NULL) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; + } else { + ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); } - ngx_cpystrn(r->request_line.data, r->request_start, - r->request_line.len + 1); - } else { + r->request_line.len = r->request_end - r->request_start; r->request_line.data = r->request_start; r->request_line.data[r->request_line.len] = '\0'; - } - if (r->method == 0) { - r->method_name.len = r->method_end - r->request_start + 1; - r->method_name.data = r->request_line.data; - } + if (r->method == 0) { + r->method_name.len = r->method_end - r->request_start + 1; + r->method_name.data = r->request_line.data; + } - if (r->uri_ext) { + if (r->uri_ext) { - /* copy URI extention */ + /* copy URI extention */ - if (r->args_start) { - r->exten.len = r->args_start - 1 - r->uri_ext; - } else { - r->exten.len = r->uri_end - r->uri_ext; - } + if (r->args_start) { + r->exten.len = r->args_start - 1 - r->uri_ext; + } else { + r->exten.len = r->uri_end - r->uri_ext; + } - if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; + if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } + + ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); } - ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); - } + if (r->args_start && r->uri_end > r->args_start) { - if (r->args_start && r->uri_end > r->args_start) { + /* copy URI arguments */ - /* copy URI arguments */ + r->args.len = r->uri_end - r->args_start; - r->args.len = r->uri_end - r->args_start; + if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } - if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; + ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1); } - ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1); - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http request line: \"%s\"", r->request_line.data); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http request line: \"%s\"", r->request_line.data); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http uri: \"%s\"", r->uri.data); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http uri: \"%s\"", r->uri.data); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http args: \"%s\"", - r->args.data ? r->args.data : (u_char *) ""); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http args: \"%s\"", + r->args.data ? r->args.data : (u_char *) ""); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http exten: \"%s\"", - r->exten.data ? r->exten.data : (u_char *) ""); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http exten: \"%s\"", + r->exten.data ? r->exten.data : (u_char *) ""); - if (r->http_version < NGX_HTTP_VERSION_10) { - rev->event_handler = ngx_http_block_read; - ngx_http_handler(r); - return; - } + if (r->http_version < NGX_HTTP_VERSION_10) { + rev->event_handler = ngx_http_block_read; + ngx_http_handler(r); + return; + } - if (ngx_list_init(&r->headers_in.headers, r->pool, 20, + if (ngx_list_init(&r->headers_in.headers, r->pool, 20, sizeof(ngx_table_elt_t)) == NGX_ERROR) - { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } - if (ngx_array_init(&r->headers_in.cookies, r->pool, 5, + if (ngx_array_init(&r->headers_in.cookies, r->pool, 5, sizeof(ngx_table_elt_t *)) == NGX_ERROR) - { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } - + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } - ctx = c->log->data; - ctx->action = "reading client request headers"; - ctx->url = r->unparsed_uri.data; - if (cscf->large_client_header - && r->header_in->pos == r->header_in->last) - { - r->header_in->pos = r->header_in->last = r->header_in->start; - } + ctx = c->log->data; + ctx->action = "reading client request headers"; + ctx->url = r->unparsed_uri.data; - rev->event_handler = ngx_http_process_request_headers; - ngx_http_process_request_headers(rev); + rev->event_handler = ngx_http_process_request_headers; + ngx_http_process_request_headers(rev); - return; + return; - } else if (rc != NGX_AGAIN) { + } else if (rc != NGX_AGAIN) { - /* there was error while a request line parsing */ + /* there was error while a request line parsing */ - for (p = r->request_start; p < r->header_in->last; p++) { - if (*p == CR || *p == LF) { - break; + for (p = r->request_start; p < r->header_in->last; p++) { + if (*p == CR || *p == LF) { + break; + } } - } - r->request_line.len = p - r->request_start; - r->request_line.data = r->request_start; - - if (rc == NGX_HTTP_PARSE_INVALID_METHOD) { - r->http_version = NGX_HTTP_VERSION_10; - } + r->request_line.len = p - r->request_start; + r->request_line.data = r->request_start; - ngx_http_client_error(r, rc, - (rc == NGX_HTTP_PARSE_INVALID_METHOD) ? - NGX_HTTP_NOT_IMPLEMENTED: - NGX_HTTP_BAD_REQUEST); - return; - } + if (rc == NGX_HTTP_PARSE_INVALID_METHOD) { + r->http_version = NGX_HTTP_VERSION_10; + } - /* NGX_AGAIN: a request line parsing is still not complete */ + ngx_http_client_error(r, rc, + (rc == NGX_HTTP_PARSE_INVALID_METHOD) ? + NGX_HTTP_NOT_IMPLEMENTED: + NGX_HTTP_BAD_REQUEST); + return; + } - if (r->header_in->last == r->header_in->end) { + /* NGX_AGAIN: a request line parsing is still incomplete */ - /* - * If it's a pipelined request and a request line is not complete - * then we have to copy it to the start of the r->header_in buf. - * We have to copy it here only if the large client headers - * are enabled otherwise a request line had been already copied - * to the start of the r->header_in buf in ngx_http_set_keepalive(). - */ + if (r->header_in->last == r->header_in->end) { - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + rv = ngx_http_alloc_large_header_buffer(r, 1); - if (cscf->large_client_header) { - offset = r->request_start - r->header_in->start; + if (rv == NGX_ERROR) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } - if (offset == 0) { + if (rv == NGX_DECLINED) { ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI, NGX_HTTP_REQUEST_URI_TOO_LARGE); return; } - - ngx_memcpy(r->header_in->start, r->request_start, - r->header_in->last - r->request_start); - - r->header_in->pos -= offset; - r->header_in->last -= offset; - r->request_start = r->header_in->start; - r->request_end -= offset; - r->uri_start -= offset; - r->uri_end -= offset; - if (r->uri_ext) { - r->uri_ext -= offset; - } - if (r->args_start) { - r->args_start -= offset; - } - - } else { - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI, - NGX_HTTP_REQUEST_URI_TOO_LARGE); } } - - return; } static void ngx_http_process_request_headers(ngx_event_t *rev) { - ssize_t n; - ngx_int_t rc, i, offset; - ngx_table_elt_t *h, **cookie; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_core_srv_conf_t *cscf; + ssize_t n; + ngx_int_t rc, rv, i, offset; + ngx_table_elt_t *h, **cookie; + ngx_connection_t *c; + ngx_http_request_t *r; c = rev->data; r = c->data; @@ -775,12 +722,29 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) return; } - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - rc = NGX_AGAIN; for ( ;; ) { + if (rc == NGX_AGAIN) { + + if (r->header_in->last == r->header_in->end) { + + rv = ngx_http_alloc_large_header_buffer(r, 0); + + if (rv == NGX_ERROR) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } + + if (rv == NGX_DECLINED) { + ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER, + NGX_HTTP_BAD_REQUEST); + return; + } + } + n = ngx_http_read_request_header(r); if (n == NGX_AGAIN || n == NGX_ERROR) { @@ -809,35 +773,17 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) } h->key.len = r->header_name_end - r->header_name_start; - h->value.len = r->header_end - r->header_start; - - /* if the large client headers are enabled then - we need to copy the header name and value */ + h->key.data = r->header_name_start; + h->key.data[h->key.len] = '\0'; - if (cscf->large_client_header) { - h->key.data = ngx_palloc(r->pool, - h->key.len + 1 + h->value.len + 1); - if (h->key.data == NULL) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } - - h->value.data = h->key.data + h->key.len + 1; - ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); - - } else { - h->key.data = r->header_name_start; - h->key.data[h->key.len] = '\0'; - h->value.data = r->header_start; - h->value.data[h->value.len] = '\0'; - } + h->value.len = r->header_end - r->header_start; + h->value.data = r->header_start; + h->value.data[h->value.len] = '\0'; if (h->key.len == sizeof("Cookie") - 1 && ngx_strcasecmp(h->key.data, "Cookie") == 0) { - if (!(cookie = ngx_push_array(&r->headers_in.cookies))) { + if (!(cookie = ngx_array_push(&r->headers_in.cookies))) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ngx_http_close_connection(c); return; @@ -866,12 +812,6 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) "http header: \"%s: %s\"", h->key.data, h->value.data); - if (cscf->large_client_header - && r->header_in->pos == r->header_in->last) - { - r->header_in->pos = r->header_in->last = r->header_in->start; - } - continue; } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { @@ -935,58 +875,6 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) /* NGX_AGAIN: a header line parsing is still not complete */ - if (r->header_in->last == r->header_in->end) { - -#if 1 - /* ngx_http_alloc_large_header_buffer() */ - - rc = ngx_http_alloc_header_buf(r, 0); - - if (rc == NGX_ERROR) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } - - if (rc == NGX_DECLINED) { - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER, - NGX_HTTP_BAD_REQUEST); - return; - } -#endif - -#if 0 - /* - * if the large client headers are enabled then - * we need to compact r->header_in buf - */ - - if (cscf->large_client_header) { - offset = r->header_name_start - r->header_in->start; - - if (offset == 0) { - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER, - NGX_HTTP_BAD_REQUEST); - return; - } - - ngx_memcpy(r->header_in->start, r->header_name_start, - r->header_in->last - r->header_name_start); - - r->header_in->last -= offset; - r->header_in->pos -= offset; - r->header_name_start = r->header_in->start; - r->header_name_end -= offset; - r->header_start -= offset; - r->header_end -= offset; - - } else { - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER, - NGX_HTTP_BAD_REQUEST); - return; - } -#endif - } } } @@ -1045,10 +933,8 @@ static ssize_t ngx_http_read_request_header(ngx_http_request_t *r) } -#if 1 - -static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, - ngx_uint_t request_line) +static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, + ngx_uint_t request_line) { u_char *old, *new; ngx_int_t offset; @@ -1059,11 +945,24 @@ static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http alloc large header buffer"); + if (request_line && r->state == 0) { + + /* the client fills up the buffer with "\r\n" */ + + r->header_in->pos = r->header_in->start; + r->header_in->last = r->header_in->start; + + return NGX_OK; + } + old = request_line ? r->request_start : r->header_name_start; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - if ((size_t) (r->header_in->pos - old) >= cscf->client_large_buffers.size) { + if (r->state != 0 + && (size_t) (r->header_in->pos - old) + >= cscf->large_client_header_buffers.size) + { return NGX_DECLINED; } @@ -1072,18 +971,18 @@ static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, if (hc->nfree) { b = hc->free[--hc->nfree]; - } else if (hc->nbusy < cscf->client_large_buffers.num) { + } else if (hc->nbusy < cscf->large_client_header_buffers.num) { if (hc->busy == NULL) { hc->busy = ngx_palloc(r->connection->pool, - cscf->client_large_buffers.num * sizeof(ngx_buf_t *)); + cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); if (hc->busy == NULL) { return NGX_ERROR; } } b = ngx_create_temp_buf(r->connection->pool, - cscf->client_large_buffers.size); + cscf->large_client_header_buffers.size); if (b == NULL) { return NGX_ERROR; } @@ -1094,6 +993,18 @@ static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, hc->busy[hc->nbusy++] = b; + if (r->state == 0) { + /* + * r->state == 0 means that a header line was parsed successfully + * and we do not need to copy incomplete header line and + * to relocate the parser header pointers + */ + + r->header_in = b; + + return NGX_OK; + } + new = b->start; ngx_memcpy(new, old, r->header_in->last - old); @@ -1103,11 +1014,31 @@ static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, if (request_line) { r->request_start = new; - r->request_end = new + (r->request_end - old); + + if (r->request_end) { + r->request_end = new + (r->request_end - old); + } + + r->method_end = new + (r->method_end - old); r->uri_start = new + (r->uri_start - old); r->uri_end = new + (r->uri_end - old); + if (r->schema_start) { + r->schema_start = new + (r->schema_start - old); + r->schema_end = new + (r->schema_end - old); + } + + if (r->host_start) { + r->host_start = new + (r->host_start - old); + r->host_end = new + (r->host_end - old); + } + + if (r->port_start) { + r->port_start = new + (r->port_start - old); + r->port_end = new + (r->port_end - old); + } + if (r->uri_ext) { r->uri_ext = new + (r->uri_ext - old); } @@ -1128,8 +1059,6 @@ static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, return NGX_OK; } -#endif - static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) { @@ -1559,8 +1488,8 @@ static void ngx_http_read_discarded_body_event(ngx_event_t *rev) static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r) { - ssize_t size, n; - ngx_http_core_loc_conf_t *clcf; + ssize_t size, n; + u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE]; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http read discarded body"); @@ -1569,29 +1498,21 @@ static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r) return NGX_OK; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r->discarded_buffer == NULL) { - r->discarded_buffer = ngx_palloc(r->pool, clcf->discarded_buffer_size); - if (r->discarded_buffer == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - } size = r->headers_in.content_length_n; - if (size > (ssize_t) clcf->discarded_buffer_size) { - size = (ssize_t) clcf->discarded_buffer_size; + if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) { + size = NGX_HTTP_DISCARD_BUFFER_SIZE; } - n = r->connection->recv(r->connection, r->discarded_buffer, size); + n = r->connection->recv(r->connection, buffer, size); if (n == NGX_ERROR) { r->closed = 1; /* - * when a client request body is discarded then we already set + * if a client request body is discarded then we already set * some HTTP response code for client and we can ignore the error */ @@ -1610,8 +1531,9 @@ static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r) static void ngx_http_set_keepalive(ngx_http_request_t *r) { + ngx_int_t i; size_t len; - ngx_buf_t *b; + ngx_buf_t *b, *f; ngx_event_t *rev, *wev; ngx_connection_t *c; ngx_http_connection_t *hc; @@ -1628,10 +1550,47 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) ctx->action = "closing request"; hc = r->http_connection; + b = r->header_in; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (b->pos < b->last || clcf->keepalive_buffers) { + + /* + * the pipelined request or we like to keep the allocated + * ngx_http_request_t and the client header buffers while keepalive + */ + + if (b != c->buffer) { + + /* move the large header buffers to the free list */ + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + if (hc->free == NULL) { + hc->free = ngx_palloc(c->pool, + cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); + if (hc->free == NULL) { + ngx_http_close_connection(c); + return; + } + } + + for (i = 0; i < hc->nbusy - 1; i++) { + f = hc->busy[i]; + hc->free[hc->nfree++] = f; + f->pos = f->start; + f->last = f->start; + } + + hc->busy[0] = b; + hc->nbusy = 1; + } + } + ngx_http_close_request(r, 0); c->data = hc; - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_add_timer(rev, clcf->keepalive_timeout); if (ngx_handle_level_read_event(rev) == NGX_ERROR) { @@ -1639,31 +1598,12 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) return; } - b = c->buffer; wev = c->write; wev->event_handler = ngx_http_empty_handler; - if (b->pos < b->last) { - /* - * The pipelined request. - * - * We do not know here whether the pipelined request is complete - * so if the large client headers are not enabled - * we need to copy the data to the start of c->buffer. - * This copy should be rare because clients that support - * pipelined requests (Mozilla 1.x, Opera 6.x+) are still rare. - */ - - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (!cscf->large_client_header) { - len = b->last - b->pos; - ngx_memcpy(b->start, b->pos, len); - b->pos = b->start; - b->last = b->start + len; - } + /* the pipelined request */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); @@ -1676,6 +1616,36 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) hc->pipeline = 0; b->pos = b->last = b->start; + + if (!clcf->keepalive_buffers) { + + if (ngx_pfree(c->pool, r) == NGX_OK) { + hc->request = NULL; + } + + if (ngx_pfree(c->pool, c->buffer->start) == NGX_OK) { + c->buffer = NULL; + } + + if (hc->free) { + for (i = 0; i < hc->nfree; i++) { + ngx_pfree(c->pool, hc->free[i]); + hc->free[i] = NULL; + } + + hc->nfree = 0; + } + + if (hc->busy) { + for (i = 0; i < hc->nbusy; i++) { + ngx_pfree(c->pool, hc->busy[i]); + hc->busy[i] = NULL; + } + + hc->nbusy = 0; + } + } + rev->event_handler = ngx_http_keepalive_handler; if (wev->active) { @@ -1706,7 +1676,10 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; } +#if 0 + /* if "keepalive_buffers off" then we need some other place */ r->http_state = NGX_HTTP_KEEPALIVE_STATE; +#endif if (rev->ready) { ngx_http_keepalive_handler(rev); @@ -1716,9 +1689,11 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) static void ngx_http_keepalive_handler(ngx_event_t *rev) { - ssize_t n; - ngx_connection_t *c; - ngx_http_log_ctx_t *ctx; + ssize_t n; + ngx_buf_t *b; + ngx_connection_t *c; + ngx_http_log_ctx_t *ctx; + ngx_http_connection_t *hc; c = rev->data; @@ -1729,6 +1704,9 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev) return; } + hc = c->data; + b = hc->nbusy ? hc->busy[0] : c->buffer; + /* * MSIE closes a keepalive connection with RST flag * so we ignore ECONNRESET here. @@ -1737,7 +1715,7 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev) c->log_error = NGX_ERROR_IGNORE_ECONNRESET; ngx_set_socket_errno(0); - n = c->recv(c, c->buffer->last, c->buffer->end - c->buffer->last); + n = c->recv(c, b->last, b->end - b->last); c->log_error = NGX_ERROR_INFO; if (n == NGX_AGAIN) { @@ -1759,20 +1737,10 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev) return; } - c->buffer->last += n; + b->last += n; rev->log->handler = ngx_http_log_error; ctx->action = "reading client request line"; -#if 0 - if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)) { - ngx_http_close_connection(c); - return; - } - - hc->request = r; - c->data = r; -#endif - ngx_http_init_request(rev); } @@ -1840,6 +1808,7 @@ static void ngx_http_lingering_close_handler(ngx_event_t *rev) ngx_connection_t *c; ngx_http_request_t *r; ngx_http_core_loc_conf_t *clcf; + u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE]; c = rev->data; r = c->data; @@ -1860,32 +1829,8 @@ static void ngx_http_lingering_close_handler(ngx_event_t *rev) return; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r->discarded_buffer == NULL) { - - /* TODO: r->header_in->start (if large headers are enabled) - or the end of parsed header (otherwise) - instead of r->header_in->last */ - - if (r->header_in->end - r->header_in->last - >= (ssize_t) clcf->discarded_buffer_size) - { - r->discarded_buffer = r->header_in->last; - - } else { - r->discarded_buffer = ngx_palloc(c->pool, - clcf->discarded_buffer_size); - if (r->discarded_buffer) { - ngx_http_close_request(r, 0); - ngx_http_close_connection(c); - return; - } - } - } - do { - n = c->recv(c, r->discarded_buffer, clcf->discarded_buffer_size); + n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n); @@ -1897,7 +1842,10 @@ static void ngx_http_lingering_close_handler(ngx_event_t *rev) } while (rev->ready); + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + timer *= 1000; + if (timer > clcf->lingering_timeout) { timer = clcf->lingering_timeout; } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index c719be897..79b25b032 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -2,6 +2,10 @@ #define _NGX_HTTP_REQUEST_H_INCLUDED_ +#define NGX_HTTP_DISCARD_BUFFER_SIZE 4096 +#define NGX_HTTP_LINGERING_BUFFER_SIZE 4096 + + #define NGX_HTTP_VERSION_9 9 #define NGX_HTTP_VERSION_10 1000 #define NGX_HTTP_VERSION_11 1001 diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c index 3084831cd..55758311f 100644 --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -66,9 +66,9 @@ void ngx_debug_init() #if (NGX_DEBUG && !NGX_NO_DEBUG_MALLOC) #if __FreeBSD_version >= 500014 - _malloc_options = "J"; + _malloc_options = "JAV"; #else - malloc_options = "J"; + malloc_options = "JAV"; #endif #endif -- cgit v1.2.3