# HG changeset patch # User Igor Sysoev # Date 1332878400 -14400 # Node ID 9fbf3ad94cbf09e031296d66440c7ec89bd8114a # Parent e0eabdb2bad18a69d1f1a04c7cf5e4394d9b30ad nginx 1.1.18 *) Change: keepalive connections are no longer disabled for Safari by default. *) Feature: the $connection_requests variable. *) Feature: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd and $tcpinfo_rcv_space variables. *) Feature: the "worker_cpu_affinity" directive now works on FreeBSD. *) Feature: the "xslt_param" and "xslt_string_param" directives. Thanks to Samuel Behan. *) Bugfix: in configure tests. Thanks to Piotr Sikora. *) Bugfix: in the ngx_http_xslt_filter_module. *) Bugfix: nginx could not be built on Debian GNU/Hurd. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,27 @@ +Changes with nginx 1.1.18 28 Mar 2012 + + *) Change: keepalive connections are no longer disabled for Safari by + default. + + *) Feature: the $connection_requests variable. + + *) Feature: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd and + $tcpinfo_rcv_space variables. + + *) Feature: the "worker_cpu_affinity" directive now works on FreeBSD. + + *) Feature: the "xslt_param" and "xslt_string_param" directives. + Thanks to Samuel Behan. + + *) Bugfix: in configure tests. + Thanks to Piotr Sikora. + + *) Bugfix: in the ngx_http_xslt_filter_module. + + *) Bugfix: nginx could not be built on Debian GNU/Hurd. + + Changes with nginx 1.1.17 15 Mar 2012 *) Security: content of previously freed memory might be sent to a diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,27 @@ +Изменения в nginx 1.1.18 28.03.2012 + + *) Изменение: теперь keepalive соединения не запрещены для Safari по + умолчанию. + + *) Добавление: переменная $connection_requests. + + *) Добавление: переменные $tcpinfo_rtt, $tcpinfo_rttvar, + $tcpinfo_snd_cwnd и $tcpinfo_rcv_space. + + *) Добавление: директива worker_cpu_affinity теперь работает на FreeBSD. + + *) Добавление: директивы xslt_param и xslt_string_param. + Спасибо Samuel Behan. + + *) Исправление: в configure. + Спасибо Piotr Sikora. + + *) Исправление: в модуле ngx_http_xslt_filter_module. + + *) Исправление: nginx не собирался на Debian GNU/Hurd. + + Изменения в nginx 1.1.17 15.03.2012 *) Безопасность: содержимое ранее освобождённой памяти могло быть diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -98,7 +98,9 @@ else ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs="-lpcre" - ngx_feature_test="pcre *re; re = pcre_compile(NULL, 0, NULL, 0, NULL)" + ngx_feature_test="pcre *re; + re = pcre_compile(NULL, 0, NULL, 0, NULL); + if (re == NULL) return 1" . auto/feature if [ $ngx_found = no ]; then diff --git a/auto/os/freebsd b/auto/os/freebsd --- a/auto/os/freebsd +++ b/auto/os/freebsd @@ -134,3 +134,11 @@ END exit 1 fi fi + + +# cpuset_setaffinity() + +if [ $version -ge 701000 ]; then + echo " + cpuset_setaffinity() found" + have=NGX_HAVE_CPUSET_SETAFFINITY . auto/have +fi diff --git a/auto/os/linux b/auto/os/linux --- a/auto/os/linux +++ b/auto/os/linux @@ -52,7 +52,7 @@ ngx_feature_run=yes ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="int efd = 0, fd = 1, n; +ngx_feature_test="int efd = 0; struct epoll_event ee; ee.events = EPOLLIN|EPOLLOUT|EPOLLET; ee.data.ptr = NULL; @@ -128,8 +128,9 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="long mask = 0; - sched_setaffinity(0, 32, (cpu_set_t *) &mask)" +ngx_feature_test="cpu_set_t mask; + CPU_ZERO(&mask); + sched_setaffinity(0, sizeof(cpu_set_t), &mask)" . auto/feature @@ -142,7 +143,7 @@ ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs=-lcrypt ngx_feature_test="struct crypt_data cd; - crypt_r(NULL, NULL, &cd);" + crypt_r(\"key\", \"salt\", &cd);" . auto/feature diff --git a/auto/os/solaris b/auto/os/solaris --- a/auto/os/solaris +++ b/auto/os/solaris @@ -35,7 +35,8 @@ ngx_feature_path= ngx_feature_libs="-lsendfile" ngx_feature_test="int fd = 1; sendfilevec_t vec[1]; size_t sent; ssize_t n; - n = sendfilev(fd, vec, 1, &sent)" + n = sendfilev(fd, vec, 1, &sent); + if (n == -1) return 1" . auto/feature diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -145,6 +145,7 @@ UNIX_DEPS="$CORE_DEPS $EVENT_DEPS \ src/os/unix/ngx_channel.h \ src/os/unix/ngx_shmem.h \ src/os/unix/ngx_process.h \ + src/os/unix/ngx_setaffinity.h \ src/os/unix/ngx_setproctitle.h \ src/os/unix/ngx_atomic.h \ src/os/unix/ngx_gcc_atomic_x86.h \ @@ -179,6 +180,7 @@ UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \ src/os/unix/ngx_shmem.c \ src/os/unix/ngx_process.c \ src/os/unix/ngx_daemon.c \ + src/os/unix/ngx_setaffinity.c \ src/os/unix/ngx_setproctitle.c \ src/os/unix/ngx_posix_init.c \ src/os/unix/ngx_user.c \ diff --git a/auto/types/sizeof b/auto/types/sizeof --- a/auto/types/sizeof +++ b/auto/types/sizeof @@ -20,12 +20,13 @@ cat << END > $NGX_AUTOTEST.c #include $NGX_INCLUDE_UNISTD_H #include +#include #include $NGX_INCLUDE_INTTYPES_H $NGX_INCLUDE_AUTO_CONFIG_H int main() { - printf("%d", sizeof($ngx_type)); + printf("%d", (int) sizeof($ngx_type)); return 0; } diff --git a/auto/types/typedef b/auto/types/typedef --- a/auto/types/typedef +++ b/auto/types/typedef @@ -29,7 +29,7 @@ do int main() { $ngx_try i = 0; - return 0; + return (int) i; } END diff --git a/auto/types/uintptr_t b/auto/types/uintptr_t --- a/auto/types/uintptr_t +++ b/auto/types/uintptr_t @@ -4,8 +4,8 @@ echo $ngx_n "checking for uintptr_t ...$ngx_c" -echo >> $NGX_ERR -echo "checking for uintptr_t" >> $NGX_ERR +echo >> $NGX_AUTOCONF_ERR +echo "checking for uintptr_t" >> $NGX_AUTOCONF_ERR found=no @@ -16,12 +16,15 @@ cat << END > $NGX_AUTOTEST.c int main() { uintptr_t i = 0; - return 0; + return (int) i; } END -eval "$CC -o $NGX_AUTOTEST $NGX_AUTOTEST.c >> $NGX_ERR 2>&1" +ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \ + -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT" + +eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1" if [ -x $NGX_AUTOTEST ]; then echo " uintptr_t found" diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -33,12 +33,12 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="int n, dp; struct pollfd pl; - dp = 0; +ngx_feature_test="int n; struct pollfd pl; pl.fd = 0; pl.events = 0; pl.revents = 0; - n = poll(&pl, 1, 0)" + n = poll(&pl, 1, 0); + if (n == -1) return 1" . auto/feature if [ $ngx_found = no ]; then @@ -57,7 +57,8 @@ ngx_feature_test="int n, dp; struct dvp dvp.dp_fds = NULL; dvp.dp_nfds = 0; dvp.dp_timeout = 0; - n = ioctl(dp, DP_POLL, &dvp)" + n = ioctl(dp, DP_POLL, &dvp); + if (n == -1) return 1" . auto/feature if [ $ngx_found = yes ]; then @@ -237,7 +238,7 @@ ngx_feature_incs="$NGX_INCLUDE_SYS_PARAM ngx_feature_path= ngx_feature_libs= ngx_feature_test="struct statfs fs; - statfs(NULL, &fs);" + statfs(\".\", &fs);" . auto/feature @@ -249,7 +250,7 @@ ngx_feature_incs="#include ngx_feature_path= ngx_feature_libs= ngx_feature_test="struct statvfs fs; - statvfs(NULL, &fs);" + statvfs(\".\", &fs);" . auto/feature @@ -343,6 +344,24 @@ ngx_feature_test="setsockopt(0, IPPROTO_ . auto/feature +ngx_feature="TCP_INFO" +ngx_feature_name="NGX_HAVE_TCP_INFO" +ngx_feature_run=no +ngx_feature_incs="#include + #include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="socklen_t optlen = sizeof(struct tcp_info); + struct tcp_info ti; + ti.tcpi_rtt = 0; + ti.tcpi_rttvar = 0; + ti.tcpi_snd_cwnd = 0; + ti.tcpi_rcv_space = 0; + getsockopt(0, IPPROTO_TCP, TCP_INFO, &ti, &optlen)" +. auto/feature + + ngx_feature="accept4()" ngx_feature_name="NGX_HAVE_ACCEPT4" ngx_feature_run=no @@ -481,7 +500,7 @@ fi ngx_feature="setproctitle()" ngx_feature_name="NGX_HAVE_SETPROCTITLE" ngx_feature_run=no -ngx_feature_incs= +ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs=$NGX_SETPROCTITLE_LIB ngx_feature_test="setproctitle(\"test\");" @@ -494,7 +513,8 @@ ngx_feature_run=no ngx_feature_incs= ngx_feature_path= ngx_feature_libs= -ngx_feature_test="char buf[1]; ssize_t n; n = pread(0, buf, 1, 0)" +ngx_feature_test="char buf[1]; ssize_t n; n = pread(0, buf, 1, 0); + if (n == -1) return 1" . auto/feature @@ -504,7 +524,8 @@ ngx_feature_run=no ngx_feature_incs= ngx_feature_path= ngx_feature_libs= -ngx_feature_test="char buf[1]; ssize_t n; n = pwrite(1, buf, 1, 0)" +ngx_feature_test="char buf[1]; ssize_t n; n = pwrite(1, buf, 1, 0); + if (n == -1) return 1" . auto/feature @@ -578,17 +599,20 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="void *p; int n; n = posix_memalign(&p, 4096, 4096)" +ngx_feature_test="void *p; int n; n = posix_memalign(&p, 4096, 4096); + if (n != 0) return 1" . auto/feature ngx_feature="memalign()" ngx_feature_name="NGX_HAVE_MEMALIGN" ngx_feature_run=no -ngx_feature_incs="#include " +ngx_feature_incs="#include + #include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="void *p; p = memalign(4096, 4096)" +ngx_feature_test="void *p; p = memalign(4096, 4096); + if (p == NULL) return 1" . auto/feature @@ -675,10 +699,12 @@ fi ngx_feature="struct msghdr.msg_control" ngx_feature_name="NGX_HAVE_MSGHDR_MSG_CONTROL" ngx_feature_run=no -ngx_feature_incs="#include " +ngx_feature_incs="#include + #include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="struct msghdr msg; msg.msg_control = NULL" +ngx_feature_test="struct msghdr msg; + printf(\"%d\", (int) sizeof(msg.msg_control))" . auto/feature @@ -686,40 +712,47 @@ ngx_feature="ioctl(FIONBIO)" ngx_feature_name="NGX_HAVE_FIONBIO" ngx_feature_run=no ngx_feature_incs="#include + #include $NGX_INCLUDE_SYS_FILIO_H" ngx_feature_path= ngx_feature_libs= -ngx_feature_test="int i; i = FIONBIO" +ngx_feature_test="int i = FIONBIO; printf(\"%d\", i)" . auto/feature ngx_feature="struct tm.tm_gmtoff" ngx_feature_name="NGX_HAVE_GMTOFF" ngx_feature_run=no -ngx_feature_incs="#include " +ngx_feature_incs="#include + #include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="struct tm tm; tm.tm_gmtoff = 0" +ngx_feature_test="struct tm tm; tm.tm_gmtoff = 0; + printf(\"%d\", (int) tm.tm_gmtoff)" . auto/feature ngx_feature="struct dirent.d_namlen" ngx_feature_name="NGX_HAVE_D_NAMLEN" ngx_feature_run=no -ngx_feature_incs="#include " +ngx_feature_incs="#include + #include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="struct dirent dir; dir.d_namlen = 0" +ngx_feature_test="struct dirent dir; dir.d_namlen = 0; + printf(\"%d\", (int) dir.d_namlen)" . auto/feature ngx_feature="struct dirent.d_type" ngx_feature_name="NGX_HAVE_D_TYPE" ngx_feature_run=no -ngx_feature_incs="#include " +ngx_feature_incs="#include + #include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="struct dirent dir; dir.d_type = DT_REG" +ngx_feature_test="struct dirent dir; dir.d_type = DT_REG; + printf(\"%d\", (int) dir.d_type)" . auto/feature diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -983,15 +983,15 @@ ngx_core_module_init_conf(ngx_cycle_t *c ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); -#if (NGX_HAVE_SCHED_SETAFFINITY) +#if (NGX_HAVE_CPU_AFFINITY) if (ccf->cpu_affinity_n && ccf->cpu_affinity_n != 1 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes) { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, - "number of the \"worker_processes\" is not equal to " - "the number of the \"worker_cpu_affinity\" mask, " + "the number of \"worker_processes\" is not equal to " + "the number of \"worker_cpu_affinity\" masks, " "using last mask for remaining worker processes"); } @@ -1242,11 +1242,11 @@ ngx_set_priority(ngx_conf_t *cf, ngx_com static char * ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { -#if (NGX_HAVE_SCHED_SETAFFINITY) +#if (NGX_HAVE_CPU_AFFINITY) ngx_core_conf_t *ccf = conf; u_char ch; - u_long *mask; + uint64_t *mask; ngx_str_t *value; ngx_uint_t i, n; @@ -1254,7 +1254,7 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx return "is duplicate"; } - mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(long)); + mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t)); if (mask == NULL) { return NGX_CONF_ERROR; } @@ -1266,9 +1266,9 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx for (n = 1; n < cf->args->nelts; n++) { - if (value[n].len > 32) { + if (value[n].len > 64) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"worker_cpu_affinity\" supports up to 32 CPU only"); + "\"worker_cpu_affinity\" supports up to 64 CPUs only"); return NGX_CONF_ERROR; } @@ -1311,7 +1311,7 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx } -u_long +uint64_t ngx_get_cpu_affinity(ngx_uint_t n) { ngx_core_conf_t *ccf; diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1001017 -#define NGINX_VERSION "1.1.17" +#define nginx_version 1001018 +#define NGINX_VERSION "1.1.18" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -86,7 +86,7 @@ typedef struct { int priority; ngx_uint_t cpu_affinity_n; - u_long *cpu_affinity; + uint64_t *cpu_affinity; char *username; ngx_uid_t user; @@ -124,7 +124,7 @@ ngx_int_t ngx_signal_process(ngx_cycle_t void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user); char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last); ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); -u_long ngx_get_cpu_affinity(ngx_uint_t n); +uint64_t ngx_get_cpu_affinity(ngx_uint_t n); ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag); diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -1840,7 +1840,7 @@ ngx_resolver_create_name_query(ngx_resol len++; } else { - if (len == 0) { + if (len == 0 || len > 255) { return NGX_DECLINED; } @@ -1851,6 +1851,10 @@ ngx_resolver_create_name_query(ngx_resol p--; } + if (len == 0 || len > 255) { + return NGX_DECLINED; + } + *p = (u_char) len; return NGX_OK; diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -25,23 +25,25 @@ typedef struct { struct ngx_http_header_val_s { ngx_http_complex_value_t value; - ngx_uint_t hash; ngx_str_t key; ngx_http_set_header_pt handler; ngx_uint_t offset; }; -#define NGX_HTTP_EXPIRES_OFF 0 -#define NGX_HTTP_EXPIRES_EPOCH 1 -#define NGX_HTTP_EXPIRES_MAX 2 -#define NGX_HTTP_EXPIRES_ACCESS 3 -#define NGX_HTTP_EXPIRES_MODIFIED 4 -#define NGX_HTTP_EXPIRES_DAILY 5 +typedef enum { + NGX_HTTP_EXPIRES_OFF, + NGX_HTTP_EXPIRES_EPOCH, + NGX_HTTP_EXPIRES_MAX, + NGX_HTTP_EXPIRES_ACCESS, + NGX_HTTP_EXPIRES_MODIFIED, + NGX_HTTP_EXPIRES_DAILY, + NGX_HTTP_EXPIRES_UNSET +} ngx_http_expires_t; typedef struct { - ngx_uint_t expires; + ngx_http_expires_t expires; time_t expires_time; ngx_array_t *headers; } ngx_http_headers_conf_t; @@ -51,6 +53,8 @@ static ngx_int_t ngx_http_set_expires(ng ngx_http_headers_conf_t *conf); static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv, ngx_str_t *value); +static ngx_int_t ngx_http_add_header(ngx_http_request_t *r, + ngx_http_header_val_t *hv, ngx_str_t *value); static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r, ngx_http_header_val_t *hv, ngx_str_t *value); @@ -313,7 +317,7 @@ ngx_http_add_header(ngx_http_request_t * return NGX_ERROR; } - h->hash = hv->hash; + h->hash = 1; h->key = hv->key; h->value = *value; } @@ -366,16 +370,11 @@ ngx_http_set_last_modified(ngx_http_requ { ngx_table_elt_t *h, **old; - if (hv->offset) { - old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset); - - } else { - old = NULL; - } + old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset); r->headers_out.last_modified_time = -1; - if (old == NULL || *old == NULL) { + if (*old == NULL) { if (value->len == 0) { return NGX_OK; @@ -386,6 +385,8 @@ ngx_http_set_last_modified(ngx_http_requ return NGX_ERROR; } + *old = h; + } else { h = *old; @@ -395,7 +396,7 @@ ngx_http_set_last_modified(ngx_http_requ } } - h->hash = hv->hash; + h->hash = 1; h->key = hv->key; h->value = *value; @@ -420,7 +421,7 @@ ngx_http_headers_create_conf(ngx_conf_t * conf->expires_time = 0; */ - conf->expires = NGX_CONF_UNSET_UINT; + conf->expires = NGX_HTTP_EXPIRES_UNSET; return conf; } @@ -432,11 +433,11 @@ ngx_http_headers_merge_conf(ngx_conf_t * ngx_http_headers_conf_t *prev = parent; ngx_http_headers_conf_t *conf = child; - if (conf->expires == NGX_CONF_UNSET_UINT) { + if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { conf->expires = prev->expires; conf->expires_time = prev->expires_time; - if (conf->expires == NGX_CONF_UNSET_UINT) { + if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { conf->expires = NGX_HTTP_EXPIRES_OFF; } } @@ -467,7 +468,7 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_uint_t minus, n; ngx_str_t *value; - if (hcf->expires != NGX_CONF_UNSET_UINT) { + if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) { return "is duplicate"; } @@ -576,7 +577,6 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - hv->hash = 1; hv->key = value[1]; hv->handler = ngx_http_add_header; hv->offset = 0; diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -80,6 +80,8 @@ static ssize_t ngx_http_log_script_write static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); +static u_char *ngx_http_log_connection_requests(ngx_http_request_t *r, + u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, @@ -193,6 +195,8 @@ static ngx_str_t ngx_http_combined_fmt static ngx_http_log_var_t ngx_http_log_vars[] = { { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection }, + { ngx_string("connection_requests"), NGX_INT_T_LEN, + ngx_http_log_connection_requests }, { ngx_string("pipe"), 1, ngx_http_log_pipe }, { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, ngx_http_log_time }, @@ -501,7 +505,15 @@ static u_char * ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) { - return ngx_sprintf(buf, "%ui", r->connection->number); + return ngx_sprintf(buf, "%uA", r->connection->number); +} + + +static u_char * +ngx_http_log_connection_requests(ngx_http_request_t *r, u_char *buf, + ngx_http_log_op_t *op) +{ + return ngx_sprintf(buf, "%ui", r->connection->requests); } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -16,13 +16,7 @@ typedef struct { - in_addr_t mask; - in_addr_t addr; -} ngx_http_realip_from_t; - - -typedef struct { - ngx_array_t *from; /* array of ngx_http_realip_from_t */ + ngx_array_t *from; /* array of ngx_in_cidr_t */ ngx_uint_t type; ngx_uint_t hash; ngx_str_t header; @@ -114,9 +108,9 @@ ngx_http_realip_handler(ngx_http_request ngx_list_part_t *part; ngx_table_elt_t *header; struct sockaddr_in *sin; + ngx_in_cidr_t *from; ngx_connection_t *c; ngx_http_realip_ctx_t *ctx; - ngx_http_realip_from_t *from; ngx_http_realip_loc_conf_t *rlcf; ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); @@ -317,7 +311,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx ngx_int_t rc; ngx_str_t *value; ngx_cidr_t cidr; - ngx_http_realip_from_t *from; + ngx_in_cidr_t *from; value = cf->args->elts; @@ -332,7 +326,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx if (rlcf->from == NULL) { rlcf->from = ngx_array_create(cf->pool, 2, - sizeof(ngx_http_realip_from_t)); + sizeof(ngx_in_cidr_t)); if (rlcf->from == NULL) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_split_clients_module.c b/src/http/modules/ngx_http_split_clients_module.c --- a/src/http/modules/ngx_http_split_clients_module.c +++ b/src/http/modules/ngx_http_split_clients_module.c @@ -97,7 +97,7 @@ ngx_http_split_clients_variable(ngx_http ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http split: %uD %uD", hash, part[i].percent); - if (hash < part[i].percent) { + if (hash < part[i].percent || part[i].percent == 0) { *v = part[i].value; return NGX_OK; } @@ -111,8 +111,9 @@ static char * ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; + uint32_t sum, last; ngx_str_t *value, name; - ngx_uint_t i, sum, last; + ngx_uint_t i; ngx_conf_t save; ngx_http_variable_t *var; ngx_http_split_clients_ctx_t *ctx; @@ -175,19 +176,15 @@ ngx_conf_split_clients_block(ngx_conf_t for (i = 0; i < ctx->parts.nelts; i++) { sum = part[i].percent ? sum + part[i].percent : 10000; if (sum > 10000) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "percent sum is more than 100%%"); - return NGX_CONF_ERROR; + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "percent sum is more than 100%%"); + return NGX_CONF_ERROR; } if (part[i].percent) { - part[i].percent = (uint32_t) - (last + 0xffffffff / 10000 * part[i].percent); - } else { - part[i].percent = 0xffffffff; + last += part[i].percent * (uint64_t) 0xffffffff / 10000; + part[i].percent = last; } - - last = part[i].percent; } return rv; diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c --- a/src/http/modules/ngx_http_xslt_filter_module.c +++ b/src/http/modules/ngx_http_xslt_filter_module.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #if (NGX_HAVE_EXSLT) @@ -27,38 +28,47 @@ typedef struct { - u_char *name; - void *data; + u_char *name; + void *data; } ngx_http_xslt_file_t; typedef struct { - ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ - ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ + ngx_array_t dtd_files; /* ngx_http_xslt_file_t */ + ngx_array_t sheet_files; /* ngx_http_xslt_file_t */ } ngx_http_xslt_filter_main_conf_t; typedef struct { - xsltStylesheetPtr stylesheet; - ngx_array_t params; /* ngx_http_complex_value_t */ + u_char *name; + ngx_http_complex_value_t value; + ngx_uint_t quote; /* unsigned quote:1; */ +} ngx_http_xslt_param_t; + + +typedef struct { + xsltStylesheetPtr stylesheet; + ngx_array_t params; /* ngx_http_xslt_param_t */ } ngx_http_xslt_sheet_t; typedef struct { - xmlDtdPtr dtd; - ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ - ngx_hash_t types; - ngx_array_t *types_keys; + xmlDtdPtr dtd; + ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ + ngx_hash_t types; + ngx_array_t *types_keys; + ngx_array_t *params; /* ngx_http_xslt_param_t */ } ngx_http_xslt_filter_loc_conf_t; typedef struct { - xmlDocPtr doc; - xmlParserCtxtPtr ctxt; - ngx_http_request_t *request; - ngx_array_t params; + xmlDocPtr doc; + xmlParserCtxtPtr ctxt; + xsltTransformContextPtr transform; + ngx_http_request_t *request; + ngx_array_t params; - ngx_uint_t done; /* unsigned done:1; */ + ngx_uint_t done; /* unsigned done:1; */ } ngx_http_xslt_filter_ctx_t; @@ -76,7 +86,7 @@ static void ngx_cdecl ngx_http_xslt_sax_ static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx); static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, - ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); + ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params, ngx_uint_t final); static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); static void ngx_http_xslt_cleanup(void *data); @@ -85,6 +95,8 @@ static char *ngx_http_xslt_entities(ngx_ void *conf); static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static void ngx_http_xslt_cleanup_dtd(void *data); static void ngx_http_xslt_cleanup_stylesheet(void *data); static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf); @@ -117,6 +129,20 @@ static ngx_command_t ngx_http_xslt_filt 0, NULL }, + { ngx_string("xslt_param"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_http_xslt_param, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("xslt_string_param"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_http_xslt_param, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) 1 }, + { ngx_string("xslt_types"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_types_slot, @@ -336,15 +362,14 @@ ngx_http_xslt_add_chunk(ngx_http_request "xmlCreatePushParserCtxt() failed"); return NGX_ERROR; } + xmlCtxtUseOptions(ctxt, XML_PARSE_NOENT|XML_PARSE_DTDLOAD + |XML_PARSE_NOWARNING); ctxt->sax->externalSubset = ngx_http_xslt_sax_external_subset; ctxt->sax->setDocumentLocator = NULL; - ctxt->sax->warning = NULL; ctxt->sax->error = ngx_http_xslt_sax_error; ctxt->sax->fatalError = ngx_http_xslt_sax_error; ctxt->sax->_private = ctx; - ctxt->replaceEntities = 1; - ctxt->loadsubset = 1; ctx->ctxt = ctxt; ctx->request = r; @@ -469,13 +494,31 @@ ngx_http_xslt_apply_stylesheet(ngx_http_ for (i = 0; i < conf->sheets.nelts; i++) { - if (ngx_http_xslt_params(r, ctx, &sheet[i].params) != NGX_OK) { + ctx->transform = xsltNewTransformContext(sheet[i].stylesheet, doc); + if (ctx->transform == NULL) { xmlFreeDoc(doc); return NULL; } - res = xsltApplyStylesheet(sheet[i].stylesheet, doc, ctx->params.elts); + if (conf->params + && ngx_http_xslt_params(r, ctx, conf->params, 0) != NGX_OK) + { + xsltFreeTransformContext(ctx->transform); + xmlFreeDoc(doc); + return NULL; + } + if (ngx_http_xslt_params(r, ctx, &sheet[i].params, 1) != NGX_OK) { + xsltFreeTransformContext(ctx->transform); + xmlFreeDoc(doc); + return NULL; + } + + res = xsltApplyStylesheetUser(sheet[i].stylesheet, doc, + ctx->params.elts, NULL, NULL, + ctx->transform); + + xsltFreeTransformContext(ctx->transform); xmlFreeDoc(doc); if (res == NULL) { @@ -565,27 +608,68 @@ ngx_http_xslt_apply_stylesheet(ngx_http_ static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, - ngx_array_t *params) + ngx_array_t *params, ngx_uint_t final) { - u_char *p, *last, *value, *dst, *src, **s; - size_t len; - ngx_uint_t i; - ngx_str_t string; - ngx_http_complex_value_t *param; + u_char *p, *last, *value, *dst, *src, **s; + size_t len; + ngx_uint_t i; + ngx_str_t string; + ngx_http_xslt_param_t *param; param = params->elts; for (i = 0; i < params->nelts; i++) { - if (ngx_http_complex_value(r, ¶m[i], &string) != NGX_OK) { + if (ngx_http_complex_value(r, ¶m[i].value, &string) != NGX_OK) { return NGX_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xslt filter param: \"%s\"", string.data); + if (param[i].name) { + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "xslt filter param name: \"%s\"", param[i].name); + + if (param[i].quote) { + if (xsltQuoteOneUserParam(ctx->transform, param[i].name, + string.data) + != 0) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "xsltQuoteOneUserParam(\"%s\", \"%s\") failed", + param[i].name, string.data); + return NGX_ERROR; + } + + continue; + } + + s = ngx_array_push(&ctx->params); + if (s == NULL) { + return NGX_ERROR; + } + + *s = param[i].name; + + s = ngx_array_push(&ctx->params); + if (s == NULL) { + return NGX_ERROR; + } + + *s = string.data; + + continue; + } + + /* + * parse param1=value1:param2=value2 syntax as used by parameters + * specified in xslt_stylesheet directives + */ + p = string.data; - last = string.data + string.len - 1; + last = string.data + string.len; while (p && *p) { @@ -641,13 +725,15 @@ ngx_http_xslt_params(ngx_http_request_t } } - s = ngx_array_push(&ctx->params); - if (s == NULL) { - return NGX_ERROR; + if (final) { + s = ngx_array_push(&ctx->params); + if (s == NULL) { + return NGX_ERROR; + } + + *s = NULL; } - *s = NULL; - return NGX_OK; } @@ -768,7 +854,7 @@ ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_pool_cleanup_t *cln; ngx_http_xslt_file_t *file; ngx_http_xslt_sheet_t *sheet; - ngx_http_complex_value_t *param; + ngx_http_xslt_param_t *param; ngx_http_compile_complex_value_t ccv; ngx_http_xslt_filter_main_conf_t *xmcf; @@ -837,7 +923,7 @@ found: } if (ngx_array_init(&sheet->params, cf->pool, n - 2, - sizeof(ngx_http_complex_value_t)) + sizeof(ngx_http_xslt_param_t)) != NGX_OK) { return NGX_CONF_ERROR; @@ -850,11 +936,12 @@ found: return NGX_CONF_ERROR; } + ngx_memzero(param, sizeof(ngx_http_xslt_param_t)); ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[i]; - ccv.complex_value = param; + ccv.complex_value = ¶m->value; ccv.zero = 1; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { @@ -866,6 +953,48 @@ found: } +static char * +ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_xslt_filter_loc_conf_t *xlcf = conf; + + ngx_http_xslt_param_t *param; + ngx_http_compile_complex_value_t ccv; + ngx_str_t *value; + + value = cf->args->elts; + + if (xlcf->params == NULL) { + xlcf->params = ngx_array_create(cf->pool, 2, + sizeof(ngx_http_xslt_param_t)); + if (xlcf->params == NULL) { + return NGX_CONF_ERROR; + } + } + + param = ngx_array_push(xlcf->params); + if (param == NULL) { + return NGX_CONF_ERROR; + } + + param->name = value[1].data; + param->quote = (cmd->post == NULL) ? 0 : 1; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[2]; + ccv.complex_value = ¶m->value; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + static void ngx_http_xslt_cleanup_dtd(void *data) { @@ -925,6 +1054,7 @@ ngx_http_xslt_filter_create_conf(ngx_con * conf->sheets = { NULL }; * conf->types = { NULL }; * conf->types_keys = NULL; + * conf->params = NULL; */ return conf; @@ -945,6 +1075,10 @@ ngx_http_xslt_filter_merge_conf(ngx_conf conf->sheets = prev->sheets; } + if (conf->params == NULL) { + conf->params = prev->params; + } + if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, &prev->types_keys, &prev->types, ngx_http_xslt_default_types) 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 @@ -50,7 +50,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '1.1.17'; +our $VERSION = '1.1.18'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -74,7 +74,7 @@ ngx_module_t ngx_http_copy_filter_modul }; -static ngx_http_output_body_filter_pt ngx_http_next_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t @@ -115,7 +115,8 @@ ngx_http_copy_filter(ngx_http_request_t ctx->bufs = conf->bufs; ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module; - ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter; + ctx->output_filter = (ngx_output_chain_filter_pt) + ngx_http_next_body_filter; ctx->filter_ctx = r; #if (NGX_HAVE_FILE_AIO) @@ -292,7 +293,7 @@ ngx_http_copy_filter_merge_conf(ngx_conf static ngx_int_t ngx_http_copy_filter_init(ngx_conf_t *cf) { - ngx_http_next_filter = ngx_http_top_body_filter; + ngx_http_next_body_filter = ngx_http_top_body_filter; ngx_http_top_body_filter = ngx_http_copy_filter; return NGX_OK; 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 @@ -3568,8 +3568,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_bitmask_value(conf->keepalive_disable, prev->keepalive_disable, (NGX_CONF_BITMASK_SET - |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6 - |NGX_HTTP_KEEPALIVE_DISABLE_SAFARI)); + |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6)); ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy, NGX_HTTP_SATISFY_ALL); ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since, @@ -4647,7 +4646,7 @@ ngx_http_core_error_log(ngx_conf_t *cf, { ngx_http_core_loc_conf_t *clcf = conf; - ngx_str_t *value; + ngx_str_t *value, name; if (clcf->error_log) { return "is duplicate"; @@ -4655,7 +4654,14 @@ ngx_http_core_error_log(ngx_conf_t *cf, value = cf->args->elts; - clcf->error_log = ngx_log_create(cf->cycle, &value[1]); + if (ngx_strcmp(value[1].data, "stderr") == 0) { + ngx_str_null(&name); + + } else { + name = value[1]; + } + + clcf->error_log = ngx_log_create(cf->cycle, &name); if (clcf->error_log == NULL) { return NGX_CONF_ERROR; } diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -1153,6 +1153,7 @@ ngx_http_parse_complex_uri(ngx_http_requ break; case '+': r->plus_in_uri = 1; + /* fall through */ default: *u++ = ch; break; diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -46,7 +46,7 @@ ngx_module_t ngx_http_postpone_filter_m }; -static ngx_http_output_body_filter_pt ngx_http_next_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t @@ -80,7 +80,7 @@ ngx_http_postpone_filter(ngx_http_reques if (r->postponed == NULL) { if (in || c->buffered) { - return ngx_http_next_filter(r->main, in); + return ngx_http_next_body_filter(r->main, in); } return NGX_OK; @@ -116,7 +116,7 @@ ngx_http_postpone_filter(ngx_http_reques "http postpone filter output \"%V?%V\"", &r->uri, &r->args); - if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) { + if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) { return NGX_ERROR; } } @@ -171,7 +171,7 @@ found: static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf) { - ngx_http_next_filter = ngx_http_top_body_filter; + ngx_http_next_body_filter = ngx_http_top_body_filter; ngx_http_top_body_filter = ngx_http_postpone_filter; return NGX_OK; 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 @@ -1493,7 +1493,9 @@ ngx_http_process_user_agent(ngx_http_req } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) { r->headers_in.chrome = 1; - } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)) { + } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1) + && ngx_strstrn(user_agent, "Mac OS X", 8 - 1)) + { r->headers_in.safari = 1; } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) { diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -3312,6 +3312,8 @@ ngx_http_upstream_process_accel_expires( switch (n) { case 0: u->cacheable = 0; + /* fall through */ + case NGX_ERROR: return NGX_OK; @@ -4460,6 +4462,8 @@ ngx_http_upstream_bind_set_slot(ngx_conf case NGX_DECLINED: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid address \"%V\"", &value[1]); + /* fall through */ + default: return NGX_CONF_ERROR; } diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -34,6 +34,10 @@ static ngx_int_t ngx_http_variable_cooki ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +#if (NGX_HAVE_TCP_INFO) +static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#endif static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -259,6 +263,20 @@ static ngx_http_variable_t ngx_http_cor { ngx_string("pid"), NULL, ngx_http_variable_pid, 0, 0, 0 }, +#if (NGX_HAVE_TCP_INFO) + { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo, + 1, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo, + 2, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + + { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo, + 3, NGX_HTTP_VAR_NOCACHEABLE, 0 }, +#endif + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -384,7 +402,7 @@ ngx_http_get_variable_index(ngx_conf_t * v->flags = 0; v->index = cmcf->variables.nelts - 1; - return cmcf->variables.nelts - 1; + return v->index; } @@ -884,6 +902,61 @@ ngx_http_variable_argument(ngx_http_requ } +#if (NGX_HAVE_TCP_INFO) + +static ngx_int_t +ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + struct tcp_info ti; + socklen_t len; + uint32_t value; + + len = sizeof(struct tcp_info); + if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) { + v->not_found = 1; + return NGX_OK; + } + + v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (data) { + case 0: + value = ti.tcpi_rtt; + break; + + case 1: + value = ti.tcpi_rttvar; + break; + + case 2: + value = ti.tcpi_snd_cwnd; + break; + + case 3: + value = ti.tcpi_rcv_space; + break; + + /* suppress warning */ + default: + value = 0; + break; + } + + v->len = ngx_sprintf(v->data, "%uD", value) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + +#endif + + static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) @@ -1200,10 +1273,13 @@ static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + u_char *real; size_t len; ngx_str_t path; ngx_http_core_loc_conf_t *clcf; - u_char real[NGX_MAX_PATH]; +#if (NGX_HAVE_MAX_PATH) + u_char buffer[NGX_MAX_PATH]; +#endif clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -1225,7 +1301,15 @@ ngx_http_variable_realpath_root(ngx_http } } - if (ngx_realpath(path.data, real) == NULL) { +#if (NGX_HAVE_MAX_PATH) + real = buffer; +#else + real = NULL; +#endif + + real = ngx_realpath(path.data, real); + + if (real == NULL) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_realpath_n " \"%s\" failed", path.data); return NGX_ERROR; @@ -1235,6 +1319,9 @@ ngx_http_variable_realpath_root(ngx_http v->data = ngx_pnalloc(r->pool, len); if (v->data == NULL) { +#if !(NGX_HAVE_MAX_PATH) + ngx_free(real); +#endif return NGX_ERROR; } @@ -1245,6 +1332,10 @@ ngx_http_variable_realpath_root(ngx_http ngx_memcpy(v->data, real, len); +#if !(NGX_HAVE_MAX_PATH) + ngx_free(real); +#endif + return NGX_OK; } diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -200,14 +200,25 @@ void ngx_close_file_mapping(ngx_file_map #endif -#define ngx_realpath(p, r) realpath((char *) p, (char *) r) +#define ngx_realpath(p, r) (u_char *) realpath((char *) p, (char *) r) #define ngx_realpath_n "realpath()" #define ngx_getcwd(buf, size) (getcwd((char *) buf, size) != NULL) #define ngx_getcwd_n "getcwd()" #define ngx_path_separator(c) ((c) == '/') + +#if defined(PATH_MAX) + +#define NGX_HAVE_MAX_PATH 1 #define NGX_MAX_PATH PATH_MAX +#else + +#define NGX_MAX_PATH 4096 + +#endif + + #define NGX_DIR_MASK_LEN 0 diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -23,6 +23,7 @@ #include #include #include +#include #include /* ALIGN() */ #include /* statfs() */ diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -45,6 +45,7 @@ #include #include #include +#include #if (NGX_HAVE_SYS_PARAM_H) #include /* statfs() */ #endif diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h --- a/src/os/unix/ngx_process.h +++ b/src/os/unix/ngx_process.h @@ -9,6 +9,7 @@ #define _NGX_PROCESS_H_INCLUDED_ +#include #include 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 @@ -62,7 +62,7 @@ ngx_int_t ngx_threads_n; #endif -u_long cpu_affinity; +uint64_t cpu_affinity; static u_char master_process[] = "master process"; @@ -913,23 +913,10 @@ ngx_worker_process_init(ngx_cycle_t *cyc } } -#if (NGX_HAVE_SCHED_SETAFFINITY) - if (cpu_affinity) { - ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, - "sched_setaffinity(0x%08Xl)", cpu_affinity); - - if (sched_setaffinity(0, sizeof(cpu_affinity), - (cpu_set_t *) &cpu_affinity) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "sched_setaffinity(0x%08Xl) failed", cpu_affinity); - } + ngx_setaffinity(cpu_affinity, cycle->log); } -#endif - #if (NGX_HAVE_PR_SET_DUMPABLE) /* allow coredump after setuid() in Linux 2.4.x */ diff --git a/src/os/unix/ngx_setaffinity.c b/src/os/unix/ngx_setaffinity.c new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_setaffinity.c @@ -0,0 +1,69 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#if (NGX_HAVE_CPUSET_SETAFFINITY) + +#include + +void +ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +{ + cpuset_t mask; + ngx_uint_t i; + + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "cpuset_setaffinity(0x%08Xl)", cpu_affinity); + + CPU_ZERO(&mask); + i = 0; + do { + if (cpu_affinity & 1) { + CPU_SET(i, &mask); + } + i++; + cpu_affinity >>= 1; + } while (cpu_affinity); + + if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, + sizeof(cpuset_t), &mask) == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "cpuset_setaffinity() failed"); + } +} + +#elif (NGX_HAVE_SCHED_SETAFFINITY) + +void +ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +{ + cpu_set_t mask; + ngx_uint_t i; + + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "sched_setaffinity(0x%08Xl)", cpu_affinity); + + CPU_ZERO(&mask); + i = 0; + do { + if (cpu_affinity & 1) { + CPU_SET(i, &mask); + } + i++; + cpu_affinity >>= 1; + } while (cpu_affinity); + + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sched_setaffinity() failed"); + } +} + +#endif diff --git a/src/os/unix/ngx_setaffinity.h b/src/os/unix/ngx_setaffinity.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_setaffinity.h @@ -0,0 +1,23 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + +#ifndef _NGX_SETAFFINITY_H_INCLUDED_ +#define _NGX_SETAFFINITY_H_INCLUDED_ + + +#if (NGX_HAVE_SCHED_SETAFFINITY || NGX_HAVE_CPUSET_SETAFFINITY) + +#define NGX_HAVE_CPU_AFFINITY 1 + +void ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log); + +#else + +#define ngx_setaffinity(cpu_affinity, log) + +#endif + + +#endif /* _NGX_SETAFFINITY_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -29,6 +29,7 @@ #include #include #include +#include #include /* statvfs() */ #include /* FIONBIO */