diff options
| author | 2013-06-01 16:12:54 +0000 | |
|---|---|---|
| committer | 2013-06-01 16:12:54 +0000 | |
| commit | d8dc9a5250771aed5ee92cbc434097082ef103f1 (patch) | |
| tree | 1d1294b5132ddb61207c9fcb594f00810c3fdb69 /usr.sbin/nginx/src/http/ngx_http_request.c | |
| parent | As found by kurt, there's a twisty race between exit1 and fork1 (diff) | |
| download | wireguard-openbsd-d8dc9a5250771aed5ee92cbc434097082ef103f1.tar.xz wireguard-openbsd-d8dc9a5250771aed5ee92cbc434097082ef103f1.zip | |
update to nginx-1.4.1 and enable the SPDY module by default
Diffstat (limited to 'usr.sbin/nginx/src/http/ngx_http_request.c')
| -rw-r--r-- | usr.sbin/nginx/src/http/ngx_http_request.c | 1324 |
1 files changed, 825 insertions, 499 deletions
diff --git a/usr.sbin/nginx/src/http/ngx_http_request.c b/usr.sbin/nginx/src/http/ngx_http_request.c index 268cc37f354..6afca1140e6 100644 --- a/usr.sbin/nginx/src/http/ngx_http_request.c +++ b/usr.sbin/nginx/src/http/ngx_http_request.c @@ -10,7 +10,7 @@ #include <ngx_http.h> -static void ngx_http_init_request(ngx_event_t *ev); +static void ngx_http_wait_request_handler(ngx_event_t *ev); 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); @@ -21,21 +21,22 @@ static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r); -static void ngx_http_process_request(ngx_http_request_t *r); -static ssize_t ngx_http_validate_host(ngx_http_request_t *r, u_char **host, - size_t len, ngx_uint_t alloc); -static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r, - u_char *host, size_t len); +static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, + ngx_uint_t alloc); +static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r, + ngx_str_t *host); +static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c, + ngx_http_virtual_names_t *virtual_names, ngx_str_t *host, + ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp); static void ngx_http_request_handler(ngx_event_t *ev); static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc); @@ -51,9 +52,7 @@ static void ngx_http_set_lingering_close(ngx_http_request_t *r); static void ngx_http_lingering_close_handler(ngx_event_t *ev); static ngx_int_t ngx_http_post_action(ngx_http_request_t *r); static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error); -static void ngx_http_free_request(ngx_http_request_t *r, ngx_int_t error); static void ngx_http_log_request(ngx_http_request_t *r); -static void ngx_http_close_connection(ngx_connection_t *c); static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len); static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, @@ -93,6 +92,14 @@ ngx_http_header_t ngx_http_headers_in[] = { offsetof(ngx_http_headers_in_t, if_unmodified_since), ngx_http_process_unique_header_line }, + { ngx_string("If-Match"), + offsetof(ngx_http_headers_in_t, if_match), + ngx_http_process_unique_header_line }, + + { ngx_string("If-None-Match"), + offsetof(ngx_http_headers_in_t, if_none_match), + ngx_http_process_unique_header_line }, + { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent), ngx_http_process_user_agent }, @@ -122,6 +129,10 @@ ngx_http_header_t ngx_http_headers_in[] = { offsetof(ngx_http_headers_in_t, expect), ngx_http_process_unique_header_line }, + { ngx_string("Upgrade"), + offsetof(ngx_http_headers_in_t, upgrade), + ngx_http_process_header_line }, + #if (NGX_HTTP_GZIP) { ngx_string("Accept-Encoding"), offsetof(ngx_http_headers_in_t, accept_encoding), @@ -141,7 +152,7 @@ ngx_http_header_t ngx_http_headers_in[] = { #if (NGX_HTTP_X_FORWARDED_FOR) { ngx_string("X-Forwarded-For"), offsetof(ngx_http_headers_in_t, x_forwarded_for), - ngx_http_process_header_line }, + ngx_http_process_multi_header_lines }, #endif #if (NGX_HTTP_REALIP) @@ -173,7 +184,8 @@ ngx_http_header_t ngx_http_headers_in[] = { ngx_http_process_header_line }, #endif - { ngx_string("Cookie"), 0, ngx_http_process_cookie }, + { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies), + ngx_http_process_multi_header_lines }, { ngx_null_string, 0, NULL } }; @@ -182,137 +194,30 @@ ngx_http_header_t ngx_http_headers_in[] = { void ngx_http_init_connection(ngx_connection_t *c) { - ngx_event_t *rev; - ngx_http_log_ctx_t *ctx; - - ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); - if (ctx == NULL) { - ngx_http_close_connection(c); - return; - } - - ctx->connection = c; - ctx->request = NULL; - ctx->current_request = NULL; - - c->log->connection = c->number; - c->log->handler = ngx_http_log_error; - c->log->data = ctx; - c->log->action = "reading client request line"; - - c->log_error = NGX_ERROR_INFO; - - rev = c->read; - rev->handler = ngx_http_init_request; - c->write->handler = ngx_http_empty_handler; - -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); -#endif - - if (rev->ready) { - /* the deferred accept(), rtsig, aio, iocp */ - - if (ngx_use_accept_mutex) { - ngx_post_event(rev, &ngx_posted_events); - return; - } - - ngx_http_init_request(rev); - return; - } - - ngx_add_timer(rev, c->listening->post_accept_timeout); - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); -#endif - ngx_http_close_connection(c); - return; - } -} - - -static void -ngx_http_init_request(ngx_event_t *rev) -{ - ngx_time_t *tp; - ngx_uint_t i; - ngx_connection_t *c; - ngx_http_request_t *r; - struct sockaddr_in *sin; - ngx_http_port_t *port; - ngx_http_in_addr_t *addr; - ngx_http_log_ctx_t *ctx; - ngx_http_addr_conf_t *addr_conf; - ngx_http_connection_t *hc; - ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; - ngx_http_core_main_conf_t *cmcf; + ngx_uint_t i; + ngx_event_t *rev; + struct sockaddr_in *sin; + ngx_http_port_t *port; + ngx_http_in_addr_t *addr; + ngx_http_log_ctx_t *ctx; + ngx_http_connection_t *hc; #if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; - ngx_http_in6_addr_t *addr6; -#endif - -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); + struct sockaddr_in6 *sin6; + ngx_http_in6_addr_t *addr6; #endif - c = rev->data; - - if (rev->timedout) { - ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); - + hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)); + if (hc == NULL) { ngx_http_close_connection(c); return; } - c->requests++; - - hc = c->data; - - if (hc == NULL) { - hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)); - if (hc == NULL) { - 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]; - } - - } else { - r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)); - if (r == NULL) { - ngx_http_close_connection(c); - return; - } - - hc->request = r; - } - - c->data = r; - r->http_connection = hc; - - c->sent = 0; - r->signature = NGX_HTTP_MODULE; + c->data = hc; /* find the server configuration for the address:port */ port = c->listening->servers; - r->connection = c; - if (port->naddrs > 1) { /* @@ -342,7 +247,7 @@ ngx_http_init_request(ngx_event_t *rev) } } - addr_conf = &addr6[i].conf; + hc->addr_conf = &addr6[i].conf; break; #endif @@ -360,7 +265,7 @@ ngx_http_init_request(ngx_event_t *rev) } } - addr_conf = &addr[i].conf; + hc->addr_conf = &addr[i].conf; break; } @@ -372,108 +277,278 @@ ngx_http_init_request(ngx_event_t *rev) #if (NGX_HAVE_INET6) case AF_INET6: addr6 = port->addrs; - addr_conf = &addr6[0].conf; + hc->addr_conf = &addr6[0].conf; break; #endif default: /* AF_INET */ addr = port->addrs; - addr_conf = &addr[0].conf; + hc->addr_conf = &addr[0].conf; break; } } - r->virtual_names = addr_conf->virtual_names; - /* the default server configuration for the address:port */ - cscf = addr_conf->default_server; + hc->conf_ctx = hc->addr_conf->default_server->ctx; - r->main_conf = cscf->ctx->main_conf; - r->srv_conf = cscf->ctx->srv_conf; - r->loc_conf = cscf->ctx->loc_conf; + ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); + if (ctx == NULL) { + ngx_http_close_connection(c); + return; + } - rev->handler = ngx_http_process_request_line; - r->read_event_handler = ngx_http_block_reading; + ctx->connection = c; + ctx->request = NULL; + ctx->current_request = NULL; -#if (NGX_HTTP_SSL) + c->log->connection = c->number; + c->log->handler = ngx_http_log_error; + c->log->data = ctx; + c->log->action = "waiting for request"; + + c->log_error = NGX_ERROR_INFO; + + rev = c->read; + rev->handler = ngx_http_wait_request_handler; + c->write->handler = ngx_http_empty_handler; + +#if (NGX_HTTP_SPDY) + if (hc->addr_conf->spdy) { + rev->handler = ngx_http_spdy_init; + } +#endif +#if (NGX_HTTP_SSL) { ngx_http_ssl_srv_conf_t *sscf; - sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); - if (sscf->enable || addr_conf->ssl) { + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); - if (c->ssl == NULL) { + if (sscf->enable || hc->addr_conf->ssl) { - c->log->action = "SSL handshaking"; + c->log->action = "SSL handshaking"; - if (addr_conf->ssl && sscf->ssl.ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, c->log, 0, - "no \"ssl_certificate\" is defined " - "in server listening on SSL port"); - ngx_http_close_connection(c); - return; - } + if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "no \"ssl_certificate\" is defined " + "in server listening on SSL port"); + ngx_http_close_connection(c); + return; + } - if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) - != NGX_OK) - { - ngx_http_close_connection(c); - return; - } + hc->ssl = 1; + + rev->handler = ngx_http_ssl_handshake; + } + } +#endif + + if (rev->ready) { + /* the deferred accept(), rtsig, aio, iocp */ - rev->handler = ngx_http_ssl_handshake; + if (ngx_use_accept_mutex) { + ngx_post_event(rev, &ngx_posted_events); + return; } - r->main_filter_need_in_memory = 1; + rev->handler(rev); + return; } + + ngx_add_timer(rev, c->listening->post_accept_timeout); + ngx_reusable_connection(c, 1); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_close_connection(c); + return; } +} -#endif - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - c->log->file = clcf->error_log->file; -#if (NGX_ENABLE_SYSLOG) - c->log->priority = clcf->error_log->priority; -#endif - if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { - c->log->log_level = clcf->error_log->log_level; +static void +ngx_http_wait_request_handler(ngx_event_t *rev) +{ + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_connection_t *c; + ngx_http_connection_t *hc; + ngx_http_core_srv_conf_t *cscf; + + c = rev->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler"); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + ngx_http_close_connection(c); + return; + } + + if (c->close) { + ngx_http_close_connection(c); + return; } - if (c->buffer == NULL) { - c->buffer = ngx_create_temp_buf(c->pool, - cscf->client_header_buffer_size); - if (c->buffer == NULL) { + hc = c->data; + cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); + + size = cscf->client_header_buffer_size; + + b = c->buffer; + + if (b == NULL) { + b = ngx_create_temp_buf(c->pool, size); + if (b == NULL) { + ngx_http_close_connection(c); + return; + } + + c->buffer = b; + + } else if (b->start == NULL) { + + b->start = ngx_palloc(c->pool, size); + if (b->start == NULL) { ngx_http_close_connection(c); return; } + + b->pos = b->start; + b->last = b->start; + b->end = b->last + size; } - if (r->header_in == NULL) { - r->header_in = c->buffer; + n = c->recv(c, b->last, size); + + if (n == NGX_AGAIN) { + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + if (c->listening->deferred_accept +#if (NGX_HTTP_SSL) + && c->ssl == NULL +#endif + ) + { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "client timed out in deferred accept"); + ngx_http_close_connection(c); + return; + } +#endif + + if (!rev->timer_set) { + ngx_add_timer(rev, c->listening->post_accept_timeout); + ngx_reusable_connection(c, 1); + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_close_connection(c); + return; + } + + /* + * We are trying to not hold c->buffer's memory for an idle connection. + */ + + if (ngx_pfree(c->pool, b->start) == NGX_OK) { + b->start = NULL; + } + + return; } - r->pool = ngx_create_pool(cscf->request_pool_size, c->log); - if (r->pool == NULL) { + if (n == NGX_ERROR) { + ngx_http_close_connection(c); + return; + } + + if (n == 0) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client closed connection"); + ngx_http_close_connection(c); + return; + } + + b->last += n; + + c->log->action = "reading client request line"; + + ngx_reusable_connection(c, 0); + + c->data = ngx_http_create_request(c); + if (c->data == NULL) { ngx_http_close_connection(c); return; } + rev->handler = ngx_http_process_request_line; + ngx_http_process_request_line(rev); +} + + +ngx_http_request_t * +ngx_http_create_request(ngx_connection_t *c) +{ + ngx_pool_t *pool; + ngx_time_t *tp; + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_connection_t *hc; + ngx_http_core_srv_conf_t *cscf; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_main_conf_t *cmcf; + + c->requests++; + + hc = c->data; + + cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); + + pool = ngx_create_pool(cscf->request_pool_size, c->log); + if (pool == NULL) { + return NULL; + } + + r = ngx_pcalloc(pool, sizeof(ngx_http_request_t)); + if (r == NULL) { + ngx_destroy_pool(pool); + return NULL; + } + + r->pool = pool; + + r->http_connection = hc; + r->signature = NGX_HTTP_MODULE; + r->connection = c; + + r->main_conf = hc->conf_ctx->main_conf; + r->srv_conf = hc->conf_ctx->srv_conf; + r->loc_conf = hc->conf_ctx->loc_conf; + + r->read_event_handler = ngx_http_block_reading; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_http_set_connection_log(r->connection, clcf->error_log); +#if (NGX_ENABLE_SYSLOG) + c->log->priority = clcf->error_log->priority; +#endif + + r->header_in = hc->nbusy ? hc->busy[0] : c->buffer; if (ngx_list_init(&r->headers_out.headers, r->pool, 20, sizeof(ngx_table_elt_t)) != NGX_OK) { ngx_destroy_pool(r->pool); - ngx_http_close_connection(c); - return; + return NULL; } r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (r->ctx == NULL) { ngx_destroy_pool(r->pool); - ngx_http_close_connection(c); - return; + return NULL; } cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); @@ -482,12 +557,14 @@ ngx_http_init_request(ngx_event_t *rev) * sizeof(ngx_http_variable_value_t)); if (r->variables == NULL) { ngx_destroy_pool(r->pool); - ngx_http_close_connection(c); - return; + return NULL; } - c->single_connection = 1; - c->destroyed = 0; +#if (NGX_HTTP_SSL) + if (c->ssl) { + r->main_filter_need_in_memory = 1; + } +#endif r->main = r; r->count = 1; @@ -519,7 +596,7 @@ ngx_http_init_request(ngx_event_t *rev) (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); #endif - rev->handler(rev); + return r; } @@ -528,37 +605,63 @@ ngx_http_init_request(ngx_event_t *rev) static void ngx_http_ssl_handshake(ngx_event_t *rev) { - u_char buf[1]; - ssize_t n; - ngx_int_t rc; - ngx_connection_t *c; - ngx_http_request_t *r; + u_char buf[1]; + ssize_t n; + ngx_err_t err; + ngx_int_t rc; + ngx_connection_t *c; + ngx_http_connection_t *hc; + ngx_http_ssl_srv_conf_t *sscf; c = rev->data; - r = c->data; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http check ssl handshake"); if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); - c->timedout = 1; - ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_close_connection(c); + return; + } + + if (c->close) { + ngx_http_close_connection(c); return; } n = recv(c->fd, (char *) buf, 1, MSG_PEEK); - if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { + err = ngx_socket_errno; - if (!rev->timer_set) { - ngx_add_timer(rev, c->listening->post_accept_timeout); - } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n); - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + if (n == -1) { + if (err == NGX_EAGAIN) { + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + if (c->listening->deferred_accept) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "client timed out in deferred accept"); + ngx_http_close_connection(c); + return; + } +#endif + + if (!rev->timer_set) { + ngx_add_timer(rev, c->listening->post_accept_timeout); + ngx_reusable_connection(c, 1); + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_close_connection(c); + } + + return; } + ngx_connection_error(c, err, "recv() failed"); + ngx_http_close_connection(c); + return; } @@ -567,6 +670,17 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "https ssl handshake: 0x%02Xd", buf[0]); + hc = c->data; + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, + ngx_http_ssl_module); + + if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) + != NGX_OK) + { + ngx_http_close_connection(c); + return; + } + rc = ngx_ssl_handshake(c); if (rc == NGX_AGAIN) { @@ -575,6 +689,8 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_add_timer(rev, c->listening->post_accept_timeout); } + ngx_reusable_connection(c, 0); + c->ssl->handler = ngx_http_ssl_handshake_handler; return; } @@ -582,27 +698,26 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_http_ssl_handshake_handler(c); return; + } - } else { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, - "plain http"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http"); - r->plain_http = 1; - } - } + c->log->action = "waiting for request"; - c->log->action = "reading client request line"; + rev->handler = ngx_http_wait_request_handler; + ngx_http_wait_request_handler(rev); - rev->handler = ngx_http_process_request_line; - ngx_http_process_request_line(rev); + return; + } + + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection"); + ngx_http_close_connection(c); } static void ngx_http_ssl_handshake_handler(ngx_connection_t *c) { - ngx_http_request_t *r; - if (c->ssl->handshaked) { /* @@ -615,21 +730,38 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) c->ssl->no_wait_shutdown = 1; - c->log->action = "reading client request line"; +#if (NGX_HTTP_SPDY && defined TLSEXT_TYPE_next_proto_neg) + { + unsigned int len; + const unsigned char *data; + static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED); + + SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); - c->read->handler = ngx_http_process_request_line; + if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) { + ngx_http_spdy_init(c->read); + return; + } + } +#endif + + c->log->action = "waiting for request"; + + c->read->handler = ngx_http_wait_request_handler; /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler; - ngx_http_process_request_line(c->read); + ngx_reusable_connection(c, 1); + + ngx_http_wait_request_handler(c->read); return; } - r = c->data; - - ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + if (c->read->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + } - return; + ngx_http_close_connection(c); } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -637,12 +769,13 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { - size_t len; - u_char *host; - const char *servername; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_ssl_srv_conf_t *sscf; + ngx_str_t host; + const char *servername; + ngx_connection_t *c; + ngx_http_connection_t *hc; + ngx_http_ssl_srv_conf_t *sscf; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); @@ -655,27 +788,44 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL server name: \"%s\"", servername); - len = ngx_strlen(servername); + host.len = ngx_strlen(servername); - if (len == 0) { + if (host.len == 0) { return SSL_TLSEXT_ERR_NOACK; } - r = c->data; + host.data = (u_char *) servername; - host = (u_char *) servername; + if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) { + return SSL_TLSEXT_ERR_NOACK; + } - len = ngx_http_validate_host(r, &host, len, 1); + hc = c->data; - if (len <= 0) { + if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, + NULL, &cscf) + != NGX_OK) + { return SSL_TLSEXT_ERR_NOACK; } - if (ngx_http_find_virtual_server(r, host, len) != NGX_OK) { + hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); + if (hc->ssl_servername == NULL) { return SSL_TLSEXT_ERR_NOACK; } - sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); + *hc->ssl_servername = host; + + hc->conf_ctx = cscf->ctx; + + clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); + + ngx_http_set_connection_log(c, clcf->error_log); +#if (NGX_ENABLE_SYSLOG) + c->log->priority = clcf->error_log->priority; +#endif + + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); if (sscf->ssl.ctx) { SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx); @@ -710,12 +860,11 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) static void ngx_http_process_request_line(ngx_event_t *rev) { - u_char *host; - ssize_t n; - ngx_int_t rc, rv; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_core_srv_conf_t *cscf; + ssize_t n; + ngx_int_t rc, rv; + ngx_str_t host; + ngx_connection_t *c; + ngx_http_request_t *r; c = rev->data; r = c->data; @@ -752,159 +901,52 @@ ngx_http_process_request_line(ngx_event_t *rev) r->request_line.data = r->request_start; r->request_length = r->header_in->pos - r->request_start; - - 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 (r->complex_uri || r->quoted_uri) { - - r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1); - if (r->uri.data == NULL) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes); - - if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid request"); - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return; - } - - } else { - r->uri.data = r->uri_start; - } - - - r->unparsed_uri.len = r->uri_end - r->uri_start; - r->unparsed_uri.data = r->uri_start; - - r->valid_unparsed_uri = r->space_in_uri ? 0 : 1; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http request line: \"%V\"", &r->request_line); r->method_name.len = r->method_end - r->request_start + 1; r->method_name.data = r->request_line.data; - if (r->http_protocol.data) { r->http_protocol.len = r->request_end - r->http_protocol.data; } - - if (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; - } - - r->exten.data = r->uri_ext; - } - - - if (r->args_start && r->uri_end > r->args_start) { - r->args.len = r->uri_end - r->args_start; - r->args.data = r->args_start; - } - -#if (NGX_WIN32) - { - u_char *p, *last; - - p = r->uri.data; - last = r->uri.data + r->uri.len; - - while (p < last) { - - if (*p++ == ':') { - - /* - * this check covers "::$data", "::$index_allocation" and - * ":$i30:$index_allocation" - */ - - if (p < last && *p == '$') { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent unsafe win32 URI"); - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return; - } - } - } - - p = r->uri.data + r->uri.len - 1; - - while (p > r->uri.data) { - - if (*p == ' ') { - p--; - continue; - } - - if (*p == '.') { - p--; - continue; - } - - break; - } - - if (p != r->uri.data + r->uri.len - 1) { - r->uri.len = p + 1 - r->uri.data; - ngx_http_set_exten(r); - } - + if (ngx_http_process_request_uri(r) != NGX_OK) { + return; } -#endif - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http request line: \"%V\"", &r->request_line); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http uri: \"%V\"", &r->uri); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http args: \"%V\"", &r->args); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http exten: \"%V\"", &r->exten); if (r->host_start && r->host_end) { - host = r->host_start; - n = ngx_http_validate_host(r, &host, - r->host_end - r->host_start, 0); + host.len = r->host_end - r->host_start; + host.data = r->host_start; + + rc = ngx_http_validate_host(&host, r->pool, 0); - if (n == 0) { + if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent invalid host in request line"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } - if (n < 0) { + if (rc == NGX_ERROR) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } - r->headers_in.server.len = n; - r->headers_in.server.data = host; + if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) { + return; + } + + r->headers_in.server = host; } if (r->http_version < NGX_HTTP_VERSION_10) { - if (ngx_http_find_virtual_server(r, r->headers_in.server.data, - r->headers_in.server.len) - == NGX_ERROR) + if (r->headers_in.server.len == 0 + && ngx_http_set_virtual_server(r, &r->headers_in.server) + == NGX_ERROR) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -921,15 +963,6 @@ ngx_http_process_request_line(ngx_event_t *rev) return; } - - if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, - sizeof(ngx_table_elt_t *)) - != NGX_OK) - { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - c->log->action = "reading client request headers"; rev->handler = ngx_http_process_request_headers; @@ -973,6 +1006,121 @@ ngx_http_process_request_line(ngx_event_t *rev) } +ngx_int_t +ngx_http_process_request_uri(ngx_http_request_t *r) +{ + ngx_http_core_srv_conf_t *cscf; + + 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 (r->complex_uri || r->quoted_uri) { + + r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1); + if (r->uri.data == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid request"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + + } else { + r->uri.data = r->uri_start; + } + + r->unparsed_uri.len = r->uri_end - r->uri_start; + r->unparsed_uri.data = r->uri_start; + + r->valid_unparsed_uri = r->space_in_uri ? 0 : 1; + + if (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; + } + + r->exten.data = r->uri_ext; + } + + if (r->args_start && r->uri_end > r->args_start) { + r->args.len = r->uri_end - r->args_start; + r->args.data = r->args_start; + } + +#if (NGX_WIN32) + { + u_char *p, *last; + + p = r->uri.data; + last = r->uri.data + r->uri.len; + + while (p < last) { + + if (*p++ == ':') { + + /* + * this check covers "::$data", "::$index_allocation" and + * ":$i30:$index_allocation" + */ + + if (p < last && *p == '$') { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent unsafe win32 URI"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + } + } + + p = r->uri.data + r->uri.len - 1; + + while (p > r->uri.data) { + + if (*p == ' ') { + p--; + continue; + } + + if (*p == '.') { + p--; + continue; + } + + break; + } + + if (p != r->uri.data + r->uri.len - 1) { + r->uri.len = p + 1 - r->uri.data; + ngx_http_set_exten(r); + } + + } +#endif + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http uri: \"%V\"", &r->uri); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http args: \"%V\"", &r->args); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http exten: \"%V\"", &r->exten); + + return NGX_OK; +} + + static void ngx_http_process_request_headers(ngx_event_t *rev) { @@ -1001,7 +1149,6 @@ ngx_http_process_request_headers(ngx_event_t *rev) } cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); rc = NGX_AGAIN; @@ -1055,6 +1202,9 @@ ngx_http_process_request_headers(ngx_event_t *rev) } } + /* the host header could change the server configuration context */ + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers); @@ -1404,24 +1554,25 @@ static ngx_int_t ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - u_char *host; - ssize_t len; + ngx_int_t rc; + ngx_str_t host; if (r->headers_in.host == NULL) { r->headers_in.host = h; } - host = h->value.data; - len = ngx_http_validate_host(r, &host, h->value.len, 0); + host = h->value; + + rc = ngx_http_validate_host(&host, r->pool, 0); - if (len == 0) { + if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent invalid host header"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } - if (len < 0) { + if (rc == NGX_ERROR) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -1430,8 +1581,11 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, return NGX_OK; } - r->headers_in.server.len = len; - r->headers_in.server.data = host; + if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) { + return NGX_ERROR; + } + + r->headers_in.server = host; return NGX_OK; } @@ -1526,31 +1680,41 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h, static ngx_int_t -ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, +ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ngx_table_elt_t **cookie; + ngx_array_t *headers; + ngx_table_elt_t **ph; - cookie = ngx_array_push(&r->headers_in.cookies); - if (cookie) { - *cookie = h; - return NGX_OK; + headers = (ngx_array_t *) ((char *) &r->headers_in + offset); + + if (headers->elts == NULL) { + if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *)) + != NGX_OK) + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } } - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ph = ngx_array_push(headers); + if (ph == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } - return NGX_ERROR; + *ph = h; + return NGX_OK; } -static ngx_int_t +ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) { - if (ngx_http_find_virtual_server(r, r->headers_in.server.data, - r->headers_in.server.len) - == NGX_ERROR) + if (r->headers_in.server.len == 0 + && ngx_http_set_virtual_server(r, &r->headers_in.server) + == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -1569,19 +1733,11 @@ ngx_http_process_request_header(ngx_http_request_t *r) if (r->headers_in.content_length_n == NGX_ERROR) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent invalid \"Content-Length\" header"); - ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } } - if (r->method & NGX_HTTP_PUT && r->headers_in.content_length_n == -1) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent %V method without \"Content-Length\" header", - &r->method_name); - ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED); - return NGX_ERROR; - } - if (r->method & NGX_HTTP_TRACE) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent TRACE method"); @@ -1589,14 +1745,25 @@ ngx_http_process_request_header(ngx_http_request_t *r) return NGX_ERROR; } - if (r->headers_in.transfer_encoding - && ngx_strcasestrn(r->headers_in.transfer_encoding->value.data, - "chunked", 7 - 1)) - { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent \"Transfer-Encoding: chunked\" header"); - ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED); - return NGX_ERROR; + if (r->headers_in.transfer_encoding) { + if (r->headers_in.transfer_encoding->value.len == 7 + && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data, + (u_char *) "chunked", 7) == 0) + { + r->headers_in.content_length = NULL; + r->headers_in.content_length_n = -1; + r->headers_in.chunked = 1; + + } else if (r->headers_in.transfer_encoding->value.len != 8 + || ngx_strncasecmp(r->headers_in.transfer_encoding->value.data, + (u_char *) "identity", 8) != 0) + { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent unknown \"Transfer-Encoding\": \"%V\"", + &r->headers_in.transfer_encoding->value); + ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED); + return NGX_ERROR; + } } if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) { @@ -1611,27 +1778,27 @@ ngx_http_process_request_header(ngx_http_request_t *r) } -static void +void ngx_http_process_request(ngx_http_request_t *r) { ngx_connection_t *c; c = r->connection; - if (r->plain_http) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent plain HTTP request to HTTPS port"); - ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS); - return; - } - #if (NGX_HTTP_SSL) - if (c->ssl) { + if (r->http_connection->ssl) { long rc; X509 *cert; ngx_http_ssl_srv_conf_t *sscf; + if (c->ssl == NULL) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent plain HTTP request to HTTPS port"); + ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS); + return; + } + sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (sscf->verify) { @@ -1693,9 +1860,8 @@ ngx_http_process_request(ngx_http_request_t *r) } -static ssize_t -ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, - ngx_uint_t alloc) +static ngx_int_t +ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc) { u_char *h, ch; size_t i, dot_pos, host_len; @@ -1706,21 +1872,21 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, sw_rest } state; - dot_pos = len; - host_len = len; + dot_pos = host->len; + host_len = host->len; - h = *host; + h = host->data; state = sw_usual; - for (i = 0; i < len; i++) { + for (i = 0; i < host->len; i++) { ch = h[i]; switch (ch) { case '.': if (dot_pos == i - 1) { - return 0; + return NGX_DECLINED; } dot_pos = i; break; @@ -1746,12 +1912,12 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, break; case '\0': - return 0; + return NGX_DECLINED; default: if (ngx_path_separator(ch)) { - return 0; + return NGX_DECLINED; } if (ch >= 'A' && ch <= 'Z') { @@ -1766,86 +1932,190 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, host_len--; } + if (host_len == 0) { + return NGX_DECLINED; + } + if (alloc) { - *host = ngx_pnalloc(r->pool, host_len); - if (*host == NULL) { - return -1; + host->data = ngx_pnalloc(pool, host_len); + if (host->data == NULL) { + return NGX_ERROR; } - ngx_strlow(*host, h, host_len); + ngx_strlow(host->data, h, host_len); } - return host_len; + host->len = host_len; + + return NGX_OK; } static ngx_int_t -ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len) +ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host) { + ngx_int_t rc; + ngx_http_connection_t *hc; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - if (r->virtual_names == NULL) { + hc = r->http_connection; + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + if (hc->ssl_servername) { + if (hc->ssl_servername->len == host->len + && ngx_strncmp(hc->ssl_servername->data, + host->data, host->len) == 0) + { +#if (NGX_PCRE) + if (hc->ssl_servername_regex + && ngx_http_regex_exec(r, hc->ssl_servername_regex, + hc->ssl_servername) != NGX_OK) + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } +#endif + return NGX_OK; + } + } + +#endif + + rc = ngx_http_find_virtual_server(r->connection, + hc->addr_conf->virtual_names, + host, r, &cscf); + + if (rc == NGX_ERROR) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + if (hc->ssl_servername) { + ngx_http_ssl_srv_conf_t *sscf; + + if (rc == NGX_DECLINED) { + cscf = hc->addr_conf->default_server; + rc = NGX_OK; + } + + sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module); + + if (sscf->verify) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client attempted to request the server name " + "different from that one was negotiated"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + } + +#endif + + if (rc == NGX_DECLINED) { + return NGX_OK; + } + + r->srv_conf = cscf->ctx->srv_conf; + r->loc_conf = cscf->ctx->loc_conf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_http_set_connection_log(r->connection, clcf->error_log); +#if (NGX_ENABLE_SYSLOG) + r->connection->log->priority = clcf->error_log->priority; +#endif + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_find_virtual_server(ngx_connection_t *c, + ngx_http_virtual_names_t *virtual_names, ngx_str_t *host, + ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp) +{ + ngx_http_core_srv_conf_t *cscf; + + if (virtual_names == NULL) { return NGX_DECLINED; } - cscf = ngx_hash_find_combined(&r->virtual_names->names, - ngx_hash_key(host, len), host, len); + cscf = ngx_hash_find_combined(&virtual_names->names, + ngx_hash_key(host->data, host->len), + host->data, host->len); if (cscf) { - goto found; + *cscfp = cscf; + return NGX_OK; } #if (NGX_PCRE) - if (len && r->virtual_names->nregex) { + if (host->len && virtual_names->nregex) { ngx_int_t n; ngx_uint_t i; - ngx_str_t name; ngx_http_server_name_t *sn; - name.len = len; - name.data = host; + sn = virtual_names->regex; - sn = r->virtual_names->regex; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - for (i = 0; i < r->virtual_names->nregex; i++) { + if (r == NULL) { + ngx_http_connection_t *hc; - n = ngx_http_regex_exec(r, sn[i].regex, &name); + for (i = 0; i < virtual_names->nregex; i++) { - if (n == NGX_OK) { - cscf = sn[i].server; - goto found; - } + n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0); - if (n == NGX_DECLINED) { - continue; + if (n == NGX_REGEX_NO_MATCHED) { + continue; + } + + if (n >= 0) { + hc = c->data; + hc->ssl_servername_regex = sn[i].regex; + + *cscfp = sn[i].server; + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + ngx_regex_exec_n " failed: %i " + "on \"%V\" using \"%V\"", + n, host, &sn[i].regex->name); + + return NGX_ERROR; } - return NGX_ERROR; + return NGX_DECLINED; } - } -#endif +#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */ - return NGX_DECLINED; + for (i = 0; i < virtual_names->nregex; i++) { -found: + n = ngx_http_regex_exec(r, sn[i].regex, host); - r->srv_conf = cscf->ctx->srv_conf; - r->loc_conf = cscf->ctx->loc_conf; + if (n == NGX_DECLINED) { + continue; + } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - r->connection->log->file = clcf->error_log->file; -#if (NGX_ENABLE_SYSLOG) - r->connection->log->priority = clcf->error_log->priority; -#endif + if (n == NGX_OK) { + *cscfp = sn[i].server; + return NGX_OK; + } - if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { - r->connection->log->log_level = clcf->error_log->log_level; + return NGX_ERROR; + } } - return NGX_OK; +#endif /* NGX_PCRE */ + + return NGX_DECLINED; } @@ -2188,6 +2458,13 @@ ngx_http_finalize_connection(ngx_http_request_t *r) { ngx_http_core_loc_conf_t *clcf; +#if (NGX_HTTP_SPDY) + if (r->spdy_stream) { + ngx_http_close_request(r, 0); + return; + } +#endif + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->main->count != 1) { @@ -2242,6 +2519,12 @@ ngx_http_set_write_handler(ngx_http_request_t *r) ngx_http_test_reading; r->write_event_handler = ngx_http_writer; +#if (NGX_HTTP_SPDY) + if (r->spdy_stream) { + return NGX_OK; + } +#endif + wev = r->connection->write; if (wev->ready && wev->delayed) { @@ -2389,6 +2672,19 @@ ngx_http_test_reading(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading"); +#if (NGX_HTTP_SPDY) + + if (r->spdy_stream) { + if (c->error) { + err = 0; + goto closed; + } + + return; + } + +#endif + #if (NGX_HAVE_KQUEUE) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -2490,7 +2786,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r) /* * If the large header buffers were allocated while the previous * request processing then we do not use c->buffer for - * the pipelined request (see ngx_http_init_request()). + * the pipelined request (see ngx_http_create_request()). * * Now we would move the large header buffers to the free list. */ @@ -2519,14 +2815,13 @@ ngx_http_set_keepalive(ngx_http_request_t *r) } } + /* guard against recursive call from ngx_http_finalize_connection() */ r->keepalive = 0; ngx_http_free_request(r, 0); c->data = hc; - ngx_add_timer(rev, clcf->keepalive_timeout); - if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_connection(c); return; @@ -2539,32 +2834,37 @@ ngx_http_set_keepalive(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); -#endif - - hc->pipeline = 1; c->log->action = "reading client pipelined request line"; - rev->handler = ngx_http_init_request; + r = ngx_http_create_request(c); + if (r == NULL) { + ngx_http_close_connection(c); + return; + } + + r->pipeline = 1; + + c->data = r; + + c->sent = 0; + c->destroyed = 0; + + if (rev->timer_set) { + ngx_del_timer(rev); + } + + rev->handler = ngx_http_process_request_line; ngx_post_event(rev, &ngx_posted_events); return; } - hc->pipeline = 0; - /* - * To keep a memory footprint as small as possible for an idle - * keepalive connection we try to free the ngx_http_request_t and - * c->buffer's memory if they were allocated outside the c->pool. - * The large header buffers are always allocated outside the c->pool and - * are freed too. + * To keep a memory footprint as small as possible for an idle keepalive + * connection we try to free c->buffer's memory if it was allocated outside + * the c->pool. The large header buffers are always allocated outside the + * c->pool and are freed too. */ - if (ngx_pfree(c->pool, r) == NGX_OK) { - hc->request = NULL; - } - b = c->buffer; if (ngx_pfree(c->pool, b->start) == NGX_OK) { @@ -2670,6 +2970,8 @@ ngx_http_set_keepalive(ngx_http_request_t *r) c->idle = 1; ngx_reusable_connection(c, 1); + ngx_add_timer(rev, clcf->keepalive_timeout); + if (rev->ready) { ngx_post_event(rev, &ngx_posted_events); } @@ -2785,17 +3087,25 @@ ngx_http_keepalive_handler(ngx_event_t *rev) b->last += n; -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); -#endif - c->log->handler = ngx_http_log_error; c->log->action = "reading client request line"; c->idle = 0; ngx_reusable_connection(c, 0); - ngx_http_init_request(rev); + c->data = ngx_http_create_request(c); + if (c->data == NULL) { + ngx_http_close_connection(c); + return; + } + + c->sent = 0; + c->destroyed = 0; + + ngx_del_timer(rev); + + rev->handler = ngx_http_process_request_line; + ngx_http_process_request_line(rev); } @@ -3010,15 +3320,23 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc) return; } +#if (NGX_HTTP_SPDY) + if (r->spdy_stream) { + ngx_http_spdy_close_stream(r->spdy_stream, rc); + return; + } +#endif + ngx_http_free_request(r, rc); ngx_http_close_connection(c); } -static void +void ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) { ngx_log_t *log; + ngx_pool_t *pool; struct linger linger; ngx_http_cleanup_t *cln; ngx_http_log_ctx_t *ctx; @@ -3085,7 +3403,15 @@ ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) r->connection->destroyed = 1; - ngx_destroy_pool(r->pool); + /* + * Setting r->pool to NULL will increase probability to catch double close + * of request since the request object is allocated from its own pool. + */ + + pool = r->pool; + r->pool = NULL; + + ngx_destroy_pool(pool); } @@ -3107,7 +3433,7 @@ ngx_http_log_request(ngx_http_request_t *r) } -static void +void ngx_http_close_connection(ngx_connection_t *c) { ngx_pool_t *pool; |
