# HG changeset patch # User Igor Sysoev # Date 1256504400 -10800 # Node ID 1dcf6adad48485e10aec666e0774634c318a9d76 # Parent 3ca2e495d9de60059e5bf5e8fb0ba11b9a4b8f23 nginx 0.8.21 *) Feature: now the "-V" switch shows TLS SNI support. *) Feature: the "listen" directive of the HTTP module supports unix domain sockets. Thanks to Hongli Lai. *) Feature: the "default_server" parameter of the "listen" directive. *) Feature: now a "default" parameter is not required to set listen socket options. *) Bugfix: nginx did not support dates in 2038 year on 32-bit platforms; *) Bugfix: socket leak; the bug had appeared in 0.8.11. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,22 @@ +Changes with nginx 0.8.21 26 Oct 2009 + + *) Feature: now the "-V" switch shows TLS SNI support. + + *) Feature: the "listen" directive of the HTTP module supports unix + domain sockets. + Thanks to Hongli Lai. + + *) Feature: the "default_server" parameter of the "listen" directive. + + *) Feature: now a "default" parameter is not required to set listen + socket options. + + *) Bugfix: nginx did not support dates in 2038 year on 32-bit platforms; + + *) Bugfix: socket leak; the bug had appeared in 0.8.11. + + Changes with nginx 0.8.20 14 Oct 2009 *) Change: now default SSL ciphers are "HIGH:!ADH:!MD5". @@ -13,7 +31,7 @@ Changes with nginx 0.8.20 "Cache-Control" backend response header line. *) Bugfix: nginx/Windows might not create temporary file, a cache file, - or "proxy/fastcgi_store"d file if a worker has no enough access + or "proxy/fastcgi_store"d file if a worker had no enough access rights for top level directories. *) Bugfix: the "Set-Cookie" and "P3P" FastCGI response header lines diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,23 @@ +Изменения в nginx 0.8.21 26.10.2009 + + *) Добавление: теперь ключ -V показывает статус поддержки TLS SNI. + + *) Добавление: директива listen модуля HTTP поддерживает unix domain + сокеты. + Спасибо Hongli Lai. + + *) Добавление: параметр "default_server" в директиве listen. + + *) Добавление: теперь параметр "default" не обязателен для установки + параметров listen-сокета. + + *) Исправление: nginx не поддерживал даты в 2038 году на 32-битных + платформах; + + *) Исправление: утечки сокетов; ошибка появилась в 0.8.11. + + Изменения в nginx 0.8.20 14.10.2009 *) Изменение: теперь по умолчанию используются следующие шифры SSL: diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -239,6 +239,13 @@ main(int argc, char *const *argv) #ifdef NGX_COMPILER ngx_log_stderr(0, "built by " NGX_COMPILER); #endif +#if (NGX_SSL) +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + ngx_log_stderr(0, "TLS SNI support enabled"); +#else + ngx_log_stderr(0, "TLS SNI support disabled"); +#endif +#endif ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE); } diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 8020 -#define NGINX_VERSION "0.8.20" +#define nginx_version 8021 +#define NGINX_VERSION "0.8.21" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -15,6 +15,7 @@ ngx_os_io_t ngx_io; ngx_listening_t * ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) { + size_t len; ngx_listening_t *ls; struct sockaddr *sa; u_char text[NGX_SOCKADDR_STRLEN]; @@ -36,17 +37,8 @@ ngx_create_listening(ngx_conf_t *cf, voi ls->sockaddr = sa; ls->socklen = socklen; - ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); - - ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len); - if (ls->addr_text.data == NULL) { - return NULL; - } - - ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len); - - ls->fd = (ngx_socket_t) -1; - ls->type = SOCK_STREAM; + len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); + ls->addr_text.len = len; switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) @@ -54,6 +46,12 @@ ngx_create_listening(ngx_conf_t *cf, voi ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; + len++; + break; +#endif case AF_INET: ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; break; @@ -62,6 +60,16 @@ ngx_create_listening(ngx_conf_t *cf, voi break; } + ls->addr_text.data = ngx_pnalloc(cf->pool, len); + if (ls->addr_text.data == NULL) { + return NULL; + } + + ngx_memcpy(ls->addr_text.data, text, len); + + ls->fd = (ngx_socket_t) -1; + ls->type = SOCK_STREAM; + ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; @@ -604,6 +612,21 @@ ngx_close_listening_sockets(ngx_cycle_t ngx_close_socket_n " %V failed", &ls[i].addr_text); } +#if (NGX_HAVE_UNIX_DOMAIN) + + if (ls[i].sockaddr->sa_family == AF_UNIX + && ngx_process != NGX_PROCESS_WORKER) + { + u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; + + if (ngx_delete_file(name) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, + ngx_delete_file_n " %s failed", name); + } + } + +#endif + ls[i].fd = (ngx_socket_t) -1; } } diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -204,7 +204,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) return NULL; } - ngx_memcpy(cycle->hostname.data, hostname, cycle->hostname.len); + ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); for (i = 0; ngx_modules[i]; i++) { diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -68,6 +68,9 @@ ngx_sock_ntop(struct sockaddr *sa, u_cha size_t n; struct sockaddr_in6 *sin6; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un *saun; +#endif switch (sa->sa_family) { @@ -108,6 +111,17 @@ ngx_sock_ntop(struct sockaddr *sa, u_cha return n; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + + case AF_UNIX: + saun = (struct sockaddr_un *) sa; + + /* we do not include trailing zero in address length */ + + return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1; + +#endif + default: return 0; } diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -12,21 +12,26 @@ #include -#define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1) -#define NGX_INET6_ADDRSTRLEN \ - (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) - -#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1) - - /* - * TODO: autoconfigure NGX_SOCKADDRLEN as + * TODO: autoconfigure NGX_SOCKADDRLEN and NGX_SOCKADDR_STRLEN as * sizeof(struct sockaddr_storage) * sizeof(struct sockaddr_un) * sizeof(struct sockaddr_in6) * sizeof(struct sockaddr_in) */ +#define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1) +#define NGX_INET6_ADDRSTRLEN \ + (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) +#define NGX_UNIX_ADDRSTRLEN \ + (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path)) + +#if (NGX_HAVE_UNIX_DOMAIN) +#define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN) +#else +#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1) +#endif + #if (NGX_HAVE_UNIX_DOMAIN) #define NGX_SOCKADDRLEN sizeof(struct sockaddr_un) #else diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -156,6 +156,17 @@ ngx_event_accept(ngx_event_t *ev) c->unexpected_eof = 1; +#if (NGX_HAVE_UNIX_DOMAIN) + if (c->sockaddr->sa_family == AF_UNIX) { + c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; + c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; +#if (NGX_SOLARIS) + /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */ + c->sendfile = 0; +#endif + } +#endif + rev = c->read; wev = c->write; diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -409,7 +409,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * == 0) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "nginx was build with SNI support, however, now it is linked " + "nginx was built with SNI support, however, now it is linked " "dynamically to an OpenSSL library which has no tlsext support, " "therefore SNI is not available"); } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.20'; +our $VERSION = '0.8.21'; require XSLoader; XSLoader::load('nginx', $VERSION); 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,18 +17,13 @@ static ngx_int_t ngx_http_init_headers_i static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf); -static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf, - ngx_array_t *servers, ngx_array_t *ports); -static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf, - ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports, - ngx_http_listen_t *listen); static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, - ngx_http_listen_t *listen); + ngx_http_listen_opt_t *lsopt); static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, - ngx_http_listen_t *listen); -static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, + ngx_http_listen_opt_t *lsopt); +static ngx_int_t ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr); static char *ngx_http_merge_locations(ngx_conf_t *cf, @@ -122,7 +117,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma char *rv; ngx_uint_t mi, m, s; ngx_conf_t pcf; - ngx_array_t ports; ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; @@ -362,19 +356,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma } - /* - * create the lists of ports, addresses and server names - * to find quickly the server core module configuration at run-time - */ - - if (ngx_http_init_server_lists(cf, &cmcf->servers, &ports) != NGX_OK) { - return NGX_CONF_ERROR; - } - - /* optimize the lists of ports, addresses and server names */ - if (ngx_http_optimize_servers(cf, cmcf, &ports) != NGX_OK) { + if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) { return NGX_CONF_ERROR; } @@ -1109,54 +1093,31 @@ inclusive: } -static ngx_int_t -ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers, - ngx_array_t *ports) +ngx_int_t +ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + ngx_http_listen_opt_t *lsopt) { - ngx_uint_t s, i; - ngx_http_listen_t *listen; - ngx_http_core_srv_conf_t **cscfp; - - if (ngx_array_init(ports, cf->temp_pool, 2, sizeof(ngx_http_conf_port_t)) - != NGX_OK) - { - return NGX_ERROR; - } + in_port_t p; + ngx_uint_t i; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_http_conf_port_t *port; + ngx_http_core_main_conf_t *cmcf; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif - /* "server" directives */ - - cscfp = servers->elts; - for (s = 0; s < servers->nelts; s++) { - - /* "listen" directives */ + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - listen = cscfp[s]->listen.elts; - for (i = 0; i < cscfp[s]->listen.nelts; i++) { - - if (ngx_http_add_ports(cf, cscfp[s], ports, &listen[i]) != NGX_OK) { - return NGX_ERROR; - } + if (cmcf->ports == NULL) { + cmcf->ports = ngx_array_create(cf->temp_pool, 2, + sizeof(ngx_http_conf_port_t)); + if (cmcf->ports == NULL) { + return NGX_ERROR; } } - return NGX_OK; -} - - -static ngx_int_t -ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, - ngx_array_t *ports, ngx_http_listen_t *listen) -{ - in_port_t p; - ngx_uint_t i; - struct sockaddr *sa; - struct sockaddr_in *sin; - ngx_http_conf_port_t *port; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif - - sa = (struct sockaddr *) &listen->sockaddr; + sa = (struct sockaddr *) &lsopt->sockaddr; switch (sa->sa_family) { @@ -1167,14 +1128,20 @@ ngx_http_add_ports(ngx_conf_t *cf, ngx_h break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + p = 0; + break; +#endif + default: /* AF_INET */ sin = (struct sockaddr_in *) sa; p = sin->sin_port; break; } - port = ports->elts; - for (i = 0; i < ports->nelts; i++) { + port = cmcf->ports->elts; + for (i = 0; i < cmcf->ports->nelts; i++) { if (p != port[i].port || sa->sa_family != port[i].family) { continue; @@ -1182,12 +1149,12 @@ ngx_http_add_ports(ngx_conf_t *cf, ngx_h /* a port is already in the port list */ - return ngx_http_add_addresses(cf, cscf, &port[i], listen); + return ngx_http_add_addresses(cf, cscf, &port[i], lsopt); } /* add a port to the port list */ - port = ngx_array_push(ports); + port = ngx_array_push(cmcf->ports); if (port == NULL) { return NGX_ERROR; } @@ -1196,26 +1163,29 @@ ngx_http_add_ports(ngx_conf_t *cf, ngx_h port->port = p; port->addrs.elts = NULL; - return ngx_http_add_address(cf, cscf, port, listen); + return ngx_http_add_address(cf, cscf, port, lsopt); } static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, - ngx_http_conf_port_t *port, ngx_http_listen_t *listen) + ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) { u_char *p; size_t len, off; - ngx_uint_t i; + ngx_uint_t i, default_server; struct sockaddr *sa; ngx_http_conf_addr_t *addr; +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un *saun; +#endif /* * we can not compare whole sockaddr struct's as kernel * may fill some fields in inherited sockaddr struct's */ - sa = (struct sockaddr *) &listen->sockaddr; + sa = (struct sockaddr *) &lsopt->sockaddr; switch (sa->sa_family) { @@ -1226,54 +1196,71 @@ ngx_http_add_addresses(ngx_conf_t *cf, n break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + off = offsetof(struct sockaddr_un, sun_path); + len = sizeof(saun->sun_path); + break; +#endif + default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; break; } - p = listen->sockaddr + off; + p = lsopt->sockaddr + off; addr = port->addrs.elts; for (i = 0; i < port->addrs.nelts; i++) { - if (ngx_memcmp(p, (u_char *) addr[i].sockaddr + off, len) != 0) { + if (ngx_memcmp(p, (u_char *) addr[i].opt.sockaddr + off, len) != 0) { continue; } /* the address is already in the address list */ - if (ngx_http_add_names(cf, cscf, &addr[i]) != NGX_OK) { + if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) { return NGX_ERROR; } + /* preserve default_server bit during listen options overwriting */ + default_server = addr[i].opt.default_server; + + if (lsopt->set) { + + if (addr[i].opt.set) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "a duplicate listen options for %s", addr[i].opt.addr); + return NGX_ERROR; + } + + addr[i].opt = *lsopt; + } + /* check the duplicate "default" server for this address:port */ - if (listen->conf.default_server) { + if (lsopt->default_server) { - if (addr[i].default_server) { - ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "the duplicate default server in %s:%ui", - listen->file_name, listen->line); - + if (default_server) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "a duplicate default server for %s", addr[i].opt.addr); return NGX_ERROR; } - addr[i].core_srv_conf = cscf; - addr[i].default_server = 1; -#if (NGX_HTTP_SSL) - addr[i].ssl = listen->conf.ssl; -#endif - addr[i].listen_conf = &listen->conf; + default_server = 1; + addr[i].default_server = cscf; } + addr[i].opt.default_server = default_server; + return NGX_OK; } /* add the address to the addresses list that bound to this port */ - return ngx_http_add_address(cf, cscf, port, listen); + return ngx_http_add_address(cf, cscf, port, lsopt); } @@ -1284,7 +1271,7 @@ ngx_http_add_addresses(ngx_conf_t *cf, n static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, - ngx_http_conf_port_t *port, ngx_http_listen_t *listen) + ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) { ngx_http_conf_addr_t *addr; @@ -1302,68 +1289,56 @@ ngx_http_add_address(ngx_conf_t *cf, ngx return NGX_ERROR; } - addr->sockaddr = (struct sockaddr *) &listen->sockaddr; - addr->socklen = listen->socklen; + addr->opt = *lsopt; addr->hash.buckets = NULL; addr->hash.size = 0; addr->wc_head = NULL; addr->wc_tail = NULL; - addr->names.elts = NULL; #if (NGX_PCRE) addr->nregex = 0; addr->regex = NULL; #endif - addr->core_srv_conf = cscf; - addr->default_server = listen->conf.default_server; - addr->bind = listen->conf.bind; - addr->wildcard = listen->conf.wildcard; -#if (NGX_HTTP_SSL) - addr->ssl = listen->conf.ssl; -#endif - addr->listen_conf = &listen->conf; + addr->default_server = cscf; + addr->servers.elts = NULL; - return ngx_http_add_names(cf, cscf, addr); + return ngx_http_add_server(cf, cscf, addr); } -/* - * add the server names and the server core module - * configurations to the address:port - */ +/* add the server core module configuration to the address:port */ static ngx_int_t -ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, +ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr) { - ngx_uint_t i; - ngx_http_server_name_t *server_names, *name; + ngx_uint_t i; + ngx_http_core_srv_conf_t **server; - if (addr->names.elts == NULL) { - if (ngx_array_init(&addr->names, cf->temp_pool, 4, - sizeof(ngx_http_server_name_t)) + if (addr->servers.elts == NULL) { + if (ngx_array_init(&addr->servers, cf->temp_pool, 4, + sizeof(ngx_http_core_srv_conf_t *)) != NGX_OK) { return NGX_ERROR; } + + } else { + server = addr->servers.elts; + for (i = 0; i < addr->servers.nelts; i++) { + if (server[i] == cscf) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "a duplicate listen %s", addr->opt.addr); + return NGX_ERROR; + } + } } - server_names = cscf->server_names.elts; - - for (i = 0; i < cscf->server_names.nelts; i++) { - - ngx_strlow(server_names[i].name.data, server_names[i].name.data, - server_names[i].name.len); + server = ngx_array_push(&addr->servers); + if (server == NULL) { + return NGX_ERROR; + } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, - "name: %V", &server_names[i].name); - - name = ngx_array_push(&addr->names); - if (name == NULL) { - return NGX_ERROR; - } - - *name = server_names[i]; - } + *server = cscf; return NGX_OK; } @@ -1373,10 +1348,9 @@ static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports) { - ngx_uint_t s, p, a; - ngx_http_conf_port_t *port; - ngx_http_conf_addr_t *addr; - ngx_http_server_name_t *name; + ngx_uint_t p, a; + ngx_http_conf_port_t *port; + ngx_http_conf_addr_t *addr; port = ports->elts; for (p = 0; p < ports->nelts; p++) { @@ -1392,23 +1366,15 @@ ngx_http_optimize_servers(ngx_conf_t *cf addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { - name = addr[a].names.elts; - for (s = 0; s < addr[a].names.nelts; s++) { - - if (addr[a].core_srv_conf == name[s].core_srv_conf + if (addr[a].servers.nelts > 1 #if (NGX_PCRE) - && name[s].captures == 0 + || addr[a].default_server->captures #endif - ) - { - continue; - } - + ) + { if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) { return NGX_ERROR; } - - break; } } @@ -1425,13 +1391,14 @@ static ngx_int_t ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr) { - ngx_int_t rc; - ngx_uint_t s; - ngx_hash_init_t hash; - ngx_hash_keys_arrays_t ha; - ngx_http_server_name_t *name; + ngx_int_t rc; + ngx_uint_t n, s; + ngx_hash_init_t hash; + ngx_hash_keys_arrays_t ha; + ngx_http_server_name_t *name; + ngx_http_core_srv_conf_t **cscfp; #if (NGX_PCRE) - ngx_uint_t regex, i; + ngx_uint_t regex, i; regex = 0; #endif @@ -1449,35 +1416,40 @@ ngx_http_server_names(ngx_conf_t *cf, ng goto failed; } - name = addr->names.elts; + cscfp = addr->servers.elts; + + for (s = 0; s < addr->servers.nelts; s++) { - for (s = 0; s < addr->names.nelts; s++) { + name = cscfp[s]->server_names.elts; + + for (n = 0; n < cscfp[s]->server_names.nelts; n++) { #if (NGX_PCRE) - if (name[s].regex) { - regex++; - continue; - } + if (name[n].regex) { + regex++; + continue; + } #endif - rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf, - NGX_HASH_WILDCARD_KEY); + rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, + NGX_HASH_WILDCARD_KEY); - if (rc == NGX_ERROR) { - return NGX_ERROR; - } + if (rc == NGX_ERROR) { + return NGX_ERROR; + } - if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid server name or wildcard \"%V\" on %s", - &name[s].name, addr->listen_conf->addr); - return NGX_ERROR; - } + if (rc == NGX_DECLINED) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "invalid server name or wildcard \"%V\" on %s", + &name[n].name, addr->opt.addr); + return NGX_ERROR; + } - if (rc == NGX_BUSY) { + if (rc == NGX_BUSY) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "conflicting server name \"%V\" on %s, ignored", - &name[s].name, addr->listen_conf->addr); + "conflicting server name \"%V\" on %s, ignored", + &name[n].name, addr->opt.addr); + } } } @@ -1546,9 +1518,16 @@ ngx_http_server_names(ngx_conf_t *cf, ng return NGX_ERROR; } - for (i = 0, s = 0; s < addr->names.nelts; s++) { - if (name[s].regex) { - addr->regex[i++] = name[s]; + i = 0; + + for (s = 0; s < addr->servers.nelts; s++) { + + name = cscfp[s]->server_names.elts; + + for (n = 0; n < cscfp[s]->server_names.nelts; n++) { + if (name[n].regex) { + addr->regex[i++] = name[n]; + } } } @@ -1572,17 +1551,17 @@ ngx_http_cmp_conf_addrs(const void *one, first = (ngx_http_conf_addr_t *) one; second = (ngx_http_conf_addr_t *) two; - if (first->wildcard) { + if (first->opt.wildcard) { /* a wildcard address must be the last resort, shift it to the end */ return 1; } - if (first->bind && !second->bind) { + if (first->opt.bind && !second->opt.bind) { /* shift explicit bind()ed addresses to the start */ return -1; } - if (!first->bind && second->bind) { + if (!first->opt.bind && second->opt.bind) { /* shift explicit bind()ed addresses to the start */ return 1; } @@ -1623,8 +1602,8 @@ ngx_http_init_listening(ngx_conf_t *cf, * implicit bindings go, and wildcard binding is in the end. */ - if (addr[last - 1].wildcard) { - addr[last - 1].bind = 1; + if (addr[last - 1].opt.wildcard) { + addr[last - 1].opt.bind = 1; bind_wildcard = 1; } else { @@ -1635,7 +1614,7 @@ ngx_http_init_listening(ngx_conf_t *cf, while (i < last) { - if (bind_wildcard && !addr[i].bind) { + if (bind_wildcard && !addr[i].opt.bind) { i++; continue; } @@ -1691,7 +1670,7 @@ ngx_http_add_listening(ngx_conf_t *cf, n ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - ls = ngx_create_listening(cf, addr->sockaddr, addr->socklen); + ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen); if (ls == NULL) { return NULL; } @@ -1700,7 +1679,7 @@ ngx_http_add_listening(ngx_conf_t *cf, n ls->handler = ngx_http_init_connection; - cscf = addr->core_srv_conf; + cscf = addr->default_server; ls->pool_size = cscf->connection_pool_size; ls->post_accept_timeout = cscf->client_header_timeout; @@ -1721,20 +1700,20 @@ ngx_http_add_listening(ngx_conf_t *cf, n } #endif - ls->backlog = addr->listen_conf->backlog; - ls->rcvbuf = addr->listen_conf->rcvbuf; - ls->sndbuf = addr->listen_conf->sndbuf; + ls->backlog = addr->opt.backlog; + ls->rcvbuf = addr->opt.rcvbuf; + ls->sndbuf = addr->opt.sndbuf; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - ls->accept_filter = addr->listen_conf->accept_filter; + ls->accept_filter = addr->opt.accept_filter; #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - ls->deferred_accept = addr->listen_conf->deferred_accept; + ls->deferred_accept = addr->opt.deferred_accept; #endif #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - ls->ipv6only = addr->listen_conf->ipv6only; + ls->ipv6only = addr->opt.ipv6only; #endif return ls; @@ -1760,11 +1739,11 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h for (i = 0; i < hport->naddrs; i++) { - sin = (struct sockaddr_in *) addr[i].sockaddr; + sin = (struct sockaddr_in *) addr[i].opt.sockaddr; addrs[i].addr = sin->sin_addr.s_addr; - addrs[i].conf.core_srv_conf = addr[i].core_srv_conf; + addrs[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) - addrs[i].conf.ssl = addr[i].ssl; + addrs[i].conf.ssl = addr[i].opt.ssl; #endif if (addr[i].hash.buckets == NULL @@ -1821,11 +1800,11 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < hport->naddrs; i++) { - sin6 = (struct sockaddr_in6 *) addr[i].sockaddr; + sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; addrs6[i].addr6 = sin6->sin6_addr; - addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf; + addrs6[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) - addrs6[i].conf.ssl = addr[i].ssl; + addrs6[i].conf.ssl = addr[i].opt.ssl; #endif if (addr[i].hash.buckets == NULL 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 @@ -57,6 +57,8 @@ struct ngx_http_log_ctx_s { ngx_int_t ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations, ngx_http_core_loc_conf_t *clcf); +ngx_int_t ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + ngx_http_listen_opt_t *lsopt); void ngx_http_init_connection(ngx_connection_t *c); @@ -118,6 +120,7 @@ size_t ngx_http_get_time(char *buf, time ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r); +void ngx_http_discarded_request_body_handler(ngx_http_request_t *r); void ngx_http_block_reading(ngx_http_request_t *r); void ngx_http_test_reading(ngx_http_request_t *r); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2807,13 +2807,6 @@ ngx_http_core_create_srv_conf(ngx_conf_t * conf->client_large_buffers.num = 0; */ - if (ngx_array_init(&cscf->listen, cf->temp_pool, 4, - sizeof(ngx_http_listen_t)) - != NGX_OK) - { - return NULL; - } - if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4, sizeof(ngx_http_server_name_t)) != NGX_OK) @@ -2839,21 +2832,16 @@ ngx_http_core_merge_srv_conf(ngx_conf_t ngx_http_core_srv_conf_t *prev = parent; ngx_http_core_srv_conf_t *conf = child; - ngx_http_listen_t *ls; struct sockaddr_in *sin; + ngx_http_listen_opt_t lsopt; ngx_http_server_name_t *sn; /* TODO: it does not merge, it inits only */ - if (conf->listen.nelts == 0) { - ls = ngx_array_push(&conf->listen); - if (ls == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(ls, sizeof(ngx_http_listen_t)); - - sin = (struct sockaddr_in *) &ls->sockaddr; + if (!conf->listen) { + ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); + + sin = (struct sockaddr_in *) &lsopt.sockaddr; sin->sin_family = AF_INET; #if (NGX_WIN32) @@ -2863,15 +2851,19 @@ ngx_http_core_merge_srv_conf(ngx_conf_t #endif sin->sin_addr.s_addr = INADDR_ANY; - ls->socklen = sizeof(struct sockaddr_in); - - ls->conf.backlog = NGX_LISTEN_BACKLOG; - ls->conf.rcvbuf = -1; - ls->conf.sndbuf = -1; - ls->conf.wildcard = 1; - - (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr, + lsopt.socklen = sizeof(struct sockaddr_in); + + lsopt.backlog = NGX_LISTEN_BACKLOG; + lsopt.rcvbuf = -1; + lsopt.sndbuf = -1; + lsopt.wildcard = 1; + + (void) ngx_sock_ntop((struct sockaddr *) &lsopt.sockaddr, lsopt.addr, NGX_SOCKADDR_STRLEN, 1); + + if (ngx_http_add_listen(cf, conf, &lsopt) == NGX_OK) { + return NGX_CONF_OK; + } } if (conf->server_name.data == NULL) { @@ -2884,9 +2876,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t #if (NGX_PCRE) sn->regex = NULL; - sn->captures = 0; #endif - sn->core_srv_conf = conf; + sn->server = conf; sn->name.len = conf->server_name.len; sn->name.data = conf->server_name.data; } @@ -3273,17 +3264,14 @@ ngx_http_core_merge_loc_conf(ngx_conf_t static char * ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_srv_conf_t *scf = conf; - - ngx_str_t *value, size; - ngx_url_t u; - ngx_uint_t n; - ngx_http_listen_t *ls; - - /* - * TODO: check duplicate 'listen' directives, - * add resolved name to server names ??? - */ + ngx_http_core_srv_conf_t *cscf = conf; + + ngx_str_t *value, size; + ngx_url_t u; + ngx_uint_t n; + ngx_http_listen_opt_t lsopt; + + cscf->listen = 1; value = cf->args->elts; @@ -3303,58 +3291,40 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - ls = ngx_array_push(&scf->listen); - if (ls == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(ls, sizeof(ngx_http_listen_t)); - - ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); - - ls->socklen = u.socklen; - ls->file_name = cf->conf_file->file.name.data; - ls->line = cf->conf_file->line; - ls->conf.backlog = NGX_LISTEN_BACKLOG; - ls->conf.rcvbuf = -1; - ls->conf.sndbuf = -1; - ls->conf.wildcard = u.wildcard; - - (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr, + ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); + + ngx_memcpy(lsopt.sockaddr, u.sockaddr, u.socklen); + + lsopt.socklen = u.socklen; + lsopt.backlog = NGX_LISTEN_BACKLOG; + lsopt.rcvbuf = -1; + lsopt.sndbuf = -1; + lsopt.wildcard = u.wildcard; + + (void) ngx_sock_ntop((struct sockaddr *) &lsopt.sockaddr, lsopt.addr, NGX_SOCKADDR_STRLEN, 1); - if (cf->args->nelts == 2) { - return NGX_CONF_OK; - } - - if (ngx_strcmp(value[2].data, "default") == 0) { - ls->conf.default_server = 1; - n = 3; - - } else { - n = 2; - } - - for ( /* void */ ; n < cf->args->nelts; n++) { - - if (ls->conf.default_server == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" parameter can be specified for " - "the default \"listen\" directive only", - &value[n]); - return NGX_CONF_ERROR; + for (n = 2; n < cf->args->nelts; n++) { + + if (ngx_strcmp(value[n].data, "default_server") == 0 + || ngx_strcmp(value[n].data, "default") == 0) + { + lsopt.default_server = 1; + continue; } if (ngx_strcmp(value[n].data, "bind") == 0) { - ls->conf.bind = 1; + lsopt.set = 1; + lsopt.bind = 1; continue; } if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) { - ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8); - ls->conf.bind = 1; - - if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) { + lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8); + lsopt.set = 1; + lsopt.bind = 1; + + if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid backlog \"%V\"", &value[n]); return NGX_CONF_ERROR; @@ -3367,10 +3337,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx size.len = value[n].len - 7; size.data = value[n].data + 7; - ls->conf.rcvbuf = ngx_parse_size(&size); - ls->conf.bind = 1; - - if (ls->conf.rcvbuf == NGX_ERROR) { + lsopt.rcvbuf = ngx_parse_size(&size); + lsopt.set = 1; + lsopt.bind = 1; + + if (lsopt.rcvbuf == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid rcvbuf \"%V\"", &value[n]); return NGX_CONF_ERROR; @@ -3383,10 +3354,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx size.len = value[n].len - 7; size.data = value[n].data + 7; - ls->conf.sndbuf = ngx_parse_size(&size); - ls->conf.bind = 1; - - if (ls->conf.sndbuf == NGX_ERROR) { + lsopt.sndbuf = ngx_parse_size(&size); + lsopt.set = 1; + lsopt.bind = 1; + + if (lsopt.sndbuf == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid sndbuf \"%V\"", &value[n]); return NGX_CONF_ERROR; @@ -3397,8 +3369,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) { #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - ls->conf.accept_filter = (char *) &value[n].data[14]; - ls->conf.bind = 1; + lsopt.accept_filter = (char *) &value[n].data[14]; + lsopt.set = 1; + lsopt.bind = 1; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "accept filters \"%V\" are not supported " @@ -3410,8 +3383,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strcmp(value[n].data, "deferred") == 0) { #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - ls->conf.deferred_accept = 1; - ls->conf.bind = 1; + lsopt.deferred_accept = 1; + lsopt.set = 1; + lsopt.bind = 1; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the deferred accept is not supported " @@ -3424,15 +3398,15 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; - sa = (struct sockaddr *) ls->sockaddr; + sa = (struct sockaddr *) lsopt.sockaddr; if (sa->sa_family == AF_INET6) { if (ngx_strcmp(&value[n].data[10], "n") == 0) { - ls->conf.ipv6only = 1; + lsopt.ipv6only = 1; } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { - ls->conf.ipv6only = 2; + lsopt.ipv6only = 2; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -3441,13 +3415,13 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - ls->conf.bind = 1; + lsopt.set = 1; + lsopt.bind = 1; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ipv6only is not supported " - "on addr \"%s\", ignored", - ls->conf.addr); + "on addr \"%s\", ignored", lsopt.addr); } continue; @@ -3461,7 +3435,8 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strcmp(value[n].data, "ssl") == 0) { #if (NGX_HTTP_SSL) - ls->conf.ssl = 1; + lsopt.set = 1; + lsopt.ssl = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -3476,7 +3451,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - return NGX_CONF_OK; + if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) { + return NGX_CONF_OK; + } + + return NGX_CONF_ERROR; } @@ -3548,11 +3527,12 @@ ngx_http_core_server_name(ngx_conf_t *cf #if (NGX_PCRE) sn->regex = NULL; - sn->captures = 0; #endif - sn->core_srv_conf = cscf; + sn->server = cscf; sn->name = value[i]; + ngx_strlow(sn->name.data, sn->name.data, sn->name.len); + if (value[i].data[0] != '~') { continue; } @@ -3581,8 +3561,8 @@ ngx_http_core_server_name(ngx_conf_t *cf return NGX_CONF_ERROR; } - sn->captures = (ngx_regex_capture_count(sn->regex) > 0); sn->name = value[i]; + cscf->captures = (ngx_regex_capture_count(sn->regex) > 0); } #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -43,6 +43,10 @@ typedef struct ngx_http_core_loc_conf_s typedef struct { + u_char sockaddr[NGX_SOCKADDRLEN]; + socklen_t socklen; + + unsigned set:1; unsigned default_server:1; unsigned bind:1; unsigned wildcard:1; @@ -65,18 +69,7 @@ typedef struct { #endif u_char addr[NGX_SOCKADDR_STRLEN + 1]; -} ngx_http_listen_conf_t; - - -typedef struct { - u_char sockaddr[NGX_SOCKADDRLEN]; - socklen_t socklen; - - u_char *file_name; - ngx_uint_t line; - - ngx_http_listen_conf_t conf; -} ngx_http_listen_t; +} ngx_http_listen_opt_t; typedef enum { @@ -142,6 +135,8 @@ typedef struct { ngx_hash_keys_arrays_t *variables_keys; + ngx_array_t *ports; + ngx_uint_t try_files; /* unsigned try_files:1 */ ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1]; @@ -149,9 +144,6 @@ typedef struct { typedef struct { - /* array of the ngx_http_listen_t, "listen" directive */ - ngx_array_t listen; - /* array of the ngx_http_server_name_t, "server_name" directive */ ngx_array_t server_names; @@ -172,6 +164,11 @@ typedef struct { ngx_flag_t merge_slashes; ngx_flag_t underscores_in_headers; + unsigned listen:1; +#if (NGX_PCRE) + unsigned captures:1; +#endif + ngx_http_core_loc_conf_t **named_locations; } ngx_http_core_srv_conf_t; @@ -181,7 +178,7 @@ typedef struct { typedef struct { /* the default server configuration for this address:port */ - ngx_http_core_srv_conf_t *core_srv_conf; + ngx_http_core_srv_conf_t *default_server; ngx_http_virtual_names_t *virtual_names; @@ -222,40 +219,28 @@ typedef struct { typedef struct { - struct sockaddr *sockaddr; - socklen_t socklen; + ngx_http_listen_opt_t opt; ngx_hash_t hash; ngx_hash_wildcard_t *wc_head; ngx_hash_wildcard_t *wc_tail; - ngx_array_t names; /* array of ngx_http_server_name_t */ - #if (NGX_PCRE) ngx_uint_t nregex; ngx_http_server_name_t *regex; #endif /* the default server configuration for this address:port */ - ngx_http_core_srv_conf_t *core_srv_conf; - - unsigned default_server:1; - unsigned bind:1; - unsigned wildcard:1; -#if (NGX_HTTP_SSL) - unsigned ssl:1; -#endif - - ngx_http_listen_conf_t *listen_conf; + ngx_http_core_srv_conf_t *default_server; + ngx_array_t servers; /* array of ngx_http_core_srv_conf_t */ } ngx_http_conf_addr_t; struct ngx_http_server_name_s { #if (NGX_PCRE) ngx_regex_t *regex; - ngx_uint_t captures; /* unsigned captures:1; */ #endif - ngx_http_core_srv_conf_t *core_srv_conf; /* virtual name server conf */ + ngx_http_core_srv_conf_t *server; /* virtual name server conf */ ngx_str_t name; }; diff --git a/src/http/ngx_http_parse_time.c b/src/http/ngx_http_parse_time.c --- a/src/http/ngx_http_parse_time.c +++ b/src/http/ngx_http_parse_time.c @@ -8,13 +8,15 @@ #include -static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t ngx_http_parse_time(u_char *value, size_t len) { - u_char *p, *end; - int day, month, year, hour, min, sec; + u_char *p, *end; + ngx_int_t month; + ngx_uint_t day, year, hour, min, sec; + uint64_t time; enum { no = 0, rfc822, /* Tue, 10 Nov 2002 23:50:13 */ @@ -229,14 +231,6 @@ ngx_http_parse_time(u_char *value, size_ return NGX_ERROR; } -#if (NGX_TIME_T_SIZE <= 4) - - if (year >= 2038) { - return NGX_ERROR; - } - -#endif - /* * shift new year to March 1 and start months from 1 (not 0), * it is needed for Gauss' formula @@ -249,7 +243,7 @@ ngx_http_parse_time(u_char *value, size_ /* Gauss' formula for Grigorian days since March 1, 1 BC */ - return ( + time = (uint64_t) ( /* days in years including leap years since March 1, 1 BC */ 365 * year + year / 4 - year / 100 + year / 400 @@ -268,4 +262,14 @@ ngx_http_parse_time(u_char *value, size_ */ - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; + +#if (NGX_TIME_T_SIZE <= 4) + + if (time > 0x7fffffff) { + return NGX_ERROR; + } + +#endif + + return (time_t) time; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -381,7 +381,7 @@ ngx_http_init_request(ngx_event_t *rev) r->virtual_names = addr_conf->virtual_names; /* the default server configuration for the address:port */ - cscf = addr_conf->core_srv_conf; + cscf = addr_conf->default_server; r->main_conf = cscf->ctx->main_conf; r->srv_conf = cscf->ctx->srv_conf; @@ -1688,7 +1688,7 @@ ngx_http_find_virtual_server(ngx_http_re #if (NGX_PCRE) - if (r->virtual_names->nregex) { + if (len && r->virtual_names->nregex) { size_t ncaptures; ngx_int_t n; ngx_uint_t i; @@ -1704,7 +1704,7 @@ ngx_http_find_virtual_server(ngx_http_re for (i = 0; i < r->virtual_names->nregex; i++) { - if (sn[i].captures && r->captures == NULL) { + if (sn[i].server->captures && r->captures == NULL) { ncaptures = (NGX_HTTP_MAX_CAPTURES + 1) * 3; @@ -1730,7 +1730,7 @@ ngx_http_find_virtual_server(ngx_http_re /* match */ - cscf = sn[i].core_srv_conf; + cscf = sn[i].server; r->ncaptures = ncaptures; r->captures_data = host; @@ -2101,13 +2101,24 @@ ngx_http_finalize_connection(ngx_http_re { ngx_http_core_loc_conf_t *clcf; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (r->main->count != 1) { + + if (r->discard_body) { + r->read_event_handler = ngx_http_discarded_request_body_handler; + + if (r->lingering_time == 0) { + r->lingering_time = ngx_time() + + (time_t) (clcf->lingering_time / 1000); + ngx_add_timer(r->connection->read, clcf->lingering_timeout); + } + } + ngx_http_close_request(r, 0); return; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (!ngx_terminate && !ngx_exiting && r->keepalive @@ -2133,7 +2144,9 @@ ngx_http_set_write_handler(ngx_http_requ r->http_state = NGX_HTTP_WRITING_REQUEST_STATE; - r->read_event_handler = ngx_http_test_reading; + r->read_event_handler = r->discard_body ? + ngx_http_discarded_request_body_handler: + ngx_http_test_reading; r->write_event_handler = ngx_http_writer; wev = r->connection->write; @@ -2235,6 +2248,8 @@ ngx_http_writer(ngx_http_request_t *r) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer done: \"%V?%V\"", &r->uri, &r->args); + r->write_event_handler = ngx_http_request_empty_handler; + ngx_http_finalize_request(r, rc); } diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -13,7 +13,6 @@ static void ngx_http_read_client_request static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body); -static void ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r); @@ -460,6 +459,7 @@ ngx_http_discard_request_body(ngx_http_r if (size) { if (r->headers_in.content_length_n > size) { + r->header_in->pos += size; r->headers_in.content_length_n -= size; } else { @@ -469,7 +469,7 @@ ngx_http_discard_request_body(ngx_http_r } } - r->read_event_handler = ngx_http_read_discarded_request_body_handler; + r->read_event_handler = ngx_http_discarded_request_body_handler; if (ngx_handle_read_event(rev, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -487,8 +487,8 @@ ngx_http_discard_request_body(ngx_http_r } -static void -ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r) +void +ngx_http_discarded_request_body_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_msec_t timer; @@ -502,7 +502,7 @@ ngx_http_read_discarded_request_body_han if (rev->timedout) { c->timedout = 1; c->error = 1; - ngx_http_finalize_request(r, 0); + ngx_http_finalize_request(r, NGX_ERROR); return; } @@ -512,7 +512,7 @@ ngx_http_read_discarded_request_body_han if (timer <= 0) { r->discard_body = 0; r->lingering_close = 0; - ngx_http_finalize_request(r, 0); + ngx_http_finalize_request(r, NGX_ERROR); return; } @@ -523,14 +523,9 @@ ngx_http_read_discarded_request_body_han rc = ngx_http_read_discarded_request_body(r); if (rc == NGX_OK) { - r->discard_body = 0; r->lingering_close = 0; - - if (r->done) { - ngx_http_finalize_request(r, 0); - } - + ngx_http_finalize_request(r, NGX_DONE); return; } @@ -538,7 +533,7 @@ ngx_http_read_discarded_request_body_han if (ngx_handle_read_event(rev, 0) != NGX_OK) { c->error = 1; - ngx_http_finalize_request(r, rc); + ngx_http_finalize_request(r, NGX_ERROR); return; } diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -675,6 +675,8 @@ ngx_master_process_exit(ngx_cycle_t *cyc } } + ngx_close_listening_sockets(cycle); + /* * Copy ngx_cycle->log related data to the special static exit cycle, * log, and log file structures enough to allow a signal handler to log.