diff -Nru nginx-1.9.11/auto/cc/conf nginx-1.9.12/auto/cc/conf --- nginx-1.9.11/auto/cc/conf 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/cc/conf 2016-02-24 09:53:23.000000000 -0500 @@ -225,6 +225,16 @@ . auto/feature + ngx_feature="gcc builtin 64 bit byteswap" + ngx_feature_name="NGX_HAVE_GCC_BSWAP64" + ngx_feature_run=no + ngx_feature_incs= + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test="__builtin_bswap64(0)" + . auto/feature + + # ngx_feature="inline" # ngx_feature_name= # ngx_feature_run=no diff -Nru nginx-1.9.11/auto/cc/msvc nginx-1.9.12/auto/cc/msvc --- nginx-1.9.11/auto/cc/msvc 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/cc/msvc 2016-02-24 09:53:23.000000000 -0500 @@ -3,9 +3,24 @@ # Copyright (C) Nginx, Inc. -# MSVC 6.0 SP2 -# MSVC Toolkit 2003 (7.1) -# MSVC 2005 Express Edition SP1 (8.0) +# MSVC 6.0 SP2 cl 12.00 +# MSVC Toolkit 2003 (7.1) cl 13.10 +# MSVC 2005 Express Edition SP1 (8.0) cl 14.00 +# MSVC 2008 Express Edition (9.0) cl 15.00 +# MSVC 2010 (10.0) cl 16.00 +# MSVC 2015 (14.0) cl 19.00 + + +NGX_MSVC_VER=`$NGX_WINE $CC 2>&1 | grep 'Compiler Version' 2>&1 \ + | sed -e 's/^.* Version \(.*\)/\1/'` + +echo " + cl version: $NGX_MSVC_VER" + +have=NGX_COMPILER value="\"cl $NGX_MSVC_VER\"" . auto/define + + +ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'` + # optimizations @@ -90,17 +105,17 @@ #CORE_LINK="$CORE_LINK -subsystem:windows -entry:mainCRTStartup" # debug -# msvc8 under Wine issues -# Program database manager mismatch; please check your installation -if [ $NGX_CC_NAME != msvc8 ]; then +# msvc under Wine issues +# C1902: Program database manager mismatch; please check your installation +if [ -z "$NGX_WINE" ]; then CFLAGS="$CFLAGS -Zi" CORE_LINK="$CORE_LINK -debug" fi # MSVC 2005 supports C99 variadic macros -if [ $NGX_CC_NAME = msvc8 ]; then - have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have +if [ "$ngx_msvc_ver" -ge 14 ]; then + have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have fi diff -Nru nginx-1.9.11/auto/cc/name nginx-1.9.12/auto/cc/name --- nginx-1.9.11/auto/cc/name 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/cc/name 2016-02-24 09:53:23.000000000 -0500 @@ -25,31 +25,8 @@ if [ "$CC" = cl ]; then - if `$NGX_WINE $CC -v 2>&1 \ - | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16' \ - >/dev/null 2>&1`; then - - NGX_CC_NAME=msvc10 - echo " + using Microsoft Visual C++ 10 compiler" - - elif `$NGX_WINE $CC -v 2>&1 \ - | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14' \ - >/dev/null 2>&1`; then - - NGX_CC_NAME=msvc8 - echo " + using Microsoft Visual C++ 8 compiler" - - elif `$NGX_WINE $CC -v 2>&1 \ - | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13' \ - >/dev/null 2>&1`; then - - NGX_CC_NAME=msvc7 - echo " + using Microsoft Visual C++ 7 compiler" - - else - NGX_CC_NAME=msvc - echo " + using Microsoft Visual C++ compiler" - fi + NGX_CC_NAME=msvc + echo " + using Microsoft Visual C++ compiler" elif [ "$CC" = wcl386 ]; then NGX_CC_NAME=owc diff -Nru nginx-1.9.11/auto/install nginx-1.9.12/auto/install --- nginx-1.9.11/auto/install 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/install 2016-02-24 09:53:23.000000000 -0500 @@ -104,8 +104,7 @@ -e "s|%%ERROR_LOG_PATH%%|${NGX_ERROR_LOG_PATH:-stderr}|" \\ < $NGX_MAN > \$@ -install: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \ - $NGX_INSTALL_PERL_MODULES +install: build $NGX_INSTALL_PERL_MODULES test -d '\$(DESTDIR)$NGX_PREFIX' || mkdir -p '\$(DESTDIR)$NGX_PREFIX' test -d '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' \ @@ -187,8 +186,6 @@ build: \$(MAKE) -f $NGX_MAKEFILE - \$(MAKE) -f $NGX_MAKEFILE modules - \$(MAKE) -f $NGX_MAKEFILE manpage install: \$(MAKE) -f $NGX_MAKEFILE install diff -Nru nginx-1.9.11/auto/lib/md5/conf nginx-1.9.12/auto/lib/md5/conf --- nginx-1.9.11/auto/lib/md5/conf 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/md5/conf 2016-02-24 09:53:23.000000000 -0500 @@ -20,12 +20,12 @@ case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) LINK_DEPS="$LINK_DEPS $MD5/md5.lib" CORE_LIBS="$CORE_LIBS $MD5/md5.lib" ;; - icc*) + icc) LINK_DEPS="$LINK_DEPS $MD5/libmd5.a" # to allow -ipo optimization we link with the *.o but not library diff -Nru nginx-1.9.11/auto/lib/md5/make nginx-1.9.12/auto/lib/md5/make --- nginx-1.9.11/auto/lib/md5/make 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/md5/make 2016-02-24 09:53:23.000000000 -0500 @@ -5,13 +5,13 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC MD5_ASM=$MD5_ASM" ngx_md5="MD5=\"$MD5\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_md5=`echo MD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff -Nru nginx-1.9.11/auto/lib/openssl/conf nginx-1.9.12/auto/lib/openssl/conf --- nginx-1.9.11/auto/lib/openssl/conf 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/openssl/conf 2016-02-24 09:53:23.000000000 -0500 @@ -32,6 +32,7 @@ CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a" + CORE_LIBS="$CORE_LIBS $NGX_LIBDL" if [ "$NGX_PLATFORM" = win32 ]; then CORE_LIBS="$CORE_LIBS -lgdi32 -lcrypt32 -lws2_32" @@ -50,7 +51,7 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= - ngx_feature_libs="-lssl -lcrypto" + ngx_feature_libs="-lssl -lcrypto $NGX_LIBDL" ngx_feature_test="SSL_library_init()" . auto/feature @@ -62,9 +63,9 @@ ngx_feature_path="/usr/local/include" if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto" + ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto $NGX_LIBDL" else - ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto" + ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto $NGX_LIBDL" fi . auto/feature @@ -78,9 +79,9 @@ ngx_feature_path="/usr/pkg/include" if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto" + ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto $NGX_LIBDL" else - ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto" + ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto $NGX_LIBDL" fi . auto/feature @@ -94,9 +95,9 @@ ngx_feature_path="/opt/local/include" if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto" + ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto $NGX_LIBDL" else - ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto" + ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto $NGX_LIBDL" fi . auto/feature diff -Nru nginx-1.9.11/auto/lib/openssl/make nginx-1.9.12/auto/lib/openssl/make --- nginx-1.9.11/auto/lib/openssl/make 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/openssl/make 2016-02-24 09:53:23.000000000 -0500 @@ -53,7 +53,7 @@ && if [ -f Makefile ]; then \$(MAKE) clean; fi \\ && ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\ && \$(MAKE) \\ - && \$(MAKE) install LIBDIR=lib + && \$(MAKE) install_sw LIBDIR=lib END diff -Nru nginx-1.9.11/auto/lib/pcre/conf nginx-1.9.12/auto/lib/pcre/conf --- nginx-1.9.11/auto/lib/pcre/conf 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/pcre/conf 2016-02-24 09:53:23.000000000 -0500 @@ -8,7 +8,7 @@ case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) have=NGX_PCRE . auto/have have=PCRE_STATIC . auto/have CORE_DEPS="$CORE_DEPS $PCRE/pcre.h" @@ -16,7 +16,7 @@ CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib" ;; - icc* ) + icc) have=NGX_PCRE . auto/have CORE_DEPS="$CORE_DEPS $PCRE/pcre.h" diff -Nru nginx-1.9.11/auto/lib/pcre/make nginx-1.9.12/auto/lib/pcre/make --- nginx-1.9.11/auto/lib/pcre/make 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/pcre/make 2016-02-24 09:53:23.000000000 -0500 @@ -5,13 +5,13 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC" ngx_pcre="PCRE=\"$PCRE\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff -Nru nginx-1.9.11/auto/lib/sha1/conf nginx-1.9.12/auto/lib/sha1/conf --- nginx-1.9.11/auto/lib/sha1/conf 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/sha1/conf 2016-02-24 09:53:23.000000000 -0500 @@ -10,12 +10,12 @@ case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) LINK_DEPS="$LINK_DEPS $SHA1/sha1.lib" CORE_LIBS="$CORE_LIBS $SHA1/sha1.lib" ;; - icc*) + icc) LINK_DEPS="$LINK_DEPS $SHA1/libsha.a" # to allow -ipo optimization we link with the *.o but not library diff -Nru nginx-1.9.11/auto/lib/sha1/make nginx-1.9.12/auto/lib/sha1/make --- nginx-1.9.11/auto/lib/sha1/make 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/sha1/make 2016-02-24 09:53:23.000000000 -0500 @@ -5,13 +5,13 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC SHA1_ASM=$SHA1_ASM" ngx_sha1="SHA1=\"$SHA1\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_sha1=`echo SHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff -Nru nginx-1.9.11/auto/lib/zlib/conf nginx-1.9.12/auto/lib/zlib/conf --- nginx-1.9.11/auto/lib/zlib/conf 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/zlib/conf 2016-02-24 09:53:23.000000000 -0500 @@ -8,13 +8,13 @@ case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) have=NGX_ZLIB . auto/have LINK_DEPS="$LINK_DEPS $ZLIB/zlib.lib" CORE_LIBS="$CORE_LIBS $ZLIB/zlib.lib" ;; - icc*) + icc) have=NGX_ZLIB . auto/have LINK_DEPS="$LINK_DEPS $ZLIB/libz.a" diff -Nru nginx-1.9.11/auto/lib/zlib/make nginx-1.9.12/auto/lib/zlib/make --- nginx-1.9.11/auto/lib/zlib/make 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/lib/zlib/make 2016-02-24 09:53:23.000000000 -0500 @@ -5,14 +5,14 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC" ngx_zlib="ZLIB=\"$ZLIB\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_zlib=`echo ZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff -Nru nginx-1.9.11/auto/make nginx-1.9.12/auto/make --- nginx-1.9.11/auto/make 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/make 2016-02-24 09:53:23.000000000 -0500 @@ -223,6 +223,10 @@ cat << END >> $NGX_MAKEFILE +build: binary modules manpage + +binary: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} + $NGX_OBJS${ngx_dirsep}nginx${ngx_binext}: $ngx_deps$ngx_spacer \$(LINK) ${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link $ngx_rcc diff -Nru nginx-1.9.11/auto/modules nginx-1.9.12/auto/modules --- nginx-1.9.11/auto/modules 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/modules 2016-02-24 09:53:23.000000000 -0500 @@ -530,11 +530,10 @@ ngx_module_incs= ngx_module_deps= ngx_module_srcs=src/http/modules/ngx_http_auth_basic_module.c - ngx_module_libs= + ngx_module_libs=$CRYPT_LIB ngx_module_link=$HTTP_AUTH_BASIC . auto/module - CORE_LIBS="$CORE_LIBS $CRYPT_LIB" fi if [ $HTTP_ACCESS = YES ]; then diff -Nru nginx-1.9.11/auto/unix nginx-1.9.12/auto/unix --- nginx-1.9.11/auto/unix 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/auto/unix 2016-02-24 09:53:23.000000000 -0500 @@ -272,6 +272,7 @@ if [ $ngx_found = yes ]; then CORE_LIBS="$CORE_LIBS -ldl" + NGX_LIBDL="-ldl" fi fi diff -Nru nginx-1.9.11/CHANGES nginx-1.9.12/CHANGES --- nginx-1.9.11/CHANGES 2016-02-09 09:12:02.000000000 -0500 +++ nginx-1.9.12/CHANGES 2016-02-24 09:53:28.000000000 -0500 @@ -1,4 +1,34 @@ +Changes with nginx 1.9.12 24 Feb 2016 + + *) Feature: Huffman encoding of response headers in HTTP/2. + Thanks to Vlad Krasnov. + + *) Feature: the "worker_cpu_affinity" directive now supports more than + 64 CPUs. + + *) Bugfix: compatibility with 3rd party C++ modules; the bug had + appeared in 1.9.11. + Thanks to Piotr Sikora. + + *) Bugfix: nginx could not be built statically with OpenSSL on Linux; + the bug had appeared in 1.9.11. + + *) Bugfix: the "add_header ... always" directive with an empty value did + not delete "Last-Modified" and "ETag" header lines from error + responses. + + *) Workaround: "called a function you should not call" and "shutdown + while in init" messages might appear in logs when using OpenSSL + 1.0.2f. + + *) Bugfix: invalid headers might be logged incorrectly. + + *) Bugfix: socket leak when using HTTP/2. + + *) Bugfix: in the ngx_http_v2_module. + + Changes with nginx 1.9.11 09 Feb 2016 *) Feature: TCP support in resolver. diff -Nru nginx-1.9.11/CHANGES.ru nginx-1.9.12/CHANGES.ru --- nginx-1.9.11/CHANGES.ru 2016-02-09 09:12:00.000000000 -0500 +++ nginx-1.9.12/CHANGES.ru 2016-02-24 09:53:27.000000000 -0500 @@ -1,4 +1,33 @@ +Изменения в nginx 1.9.12 24.02.2016 + + *) Добавление: кодирование Хаффмана заголовков ответов в HTTP/2. + Спасибо Владу Краснову. + + *) Добавление: директива worker_cpu_affinity теперь поддерживает более + 64 процессоров. + + *) Исправление: совместимость со сторонними модулями на C++; ошибка + появилась в 1.9.11. + Спасибо Piotr Sikora. + + *) Исправление: nginx не собирался статически с OpenSSL на Linux; ошибка + появилась в 1.9.11. + + *) Исправление: директива "add_header ... always" с пустым значением не + удаляла из заголовков ошибочных ответов строки Last-Modified и ETag. + + *) Изменение: при использовании OpenSSL 1.0.2f в логах могли появляться + сообщения "called a function you should not call" и "shutdown while + in init". + + *) Исправление: ошибочные заголовки могли логгироваться некорректно. + + *) Исправление: утечки сокетов при использовании HTTP/2. + + *) Исправление: в модуле ngx_http_v2_module. + + Изменения в nginx 1.9.11 09.02.2016 *) Добавление: теперь resolver поддерживает TCP. diff -Nru nginx-1.9.11/debian/changelog nginx-1.9.12/debian/changelog --- nginx-1.9.11/debian/changelog 2016-02-19 14:22:39.000000000 -0500 +++ nginx-1.9.12/debian/changelog 2016-02-24 13:04:57.000000000 -0500 @@ -1,3 +1,12 @@ +nginx (1.9.12-0ubuntu1) xenial; urgency=medium + + * New upstream release (1.9.12) - full changelog available at upstream + website - http://nginx.org/en/CHANGES (LP: #1549347) + * All Ubuntu specific changes from 1.9.11-0ubuntu1 and -0ubuntu2 remain + included in this upload. + + -- Thomas Ward Wed, 24 Feb 2016 10:26:31 -0500 + nginx (1.9.11-0ubuntu2) xenial; urgency=medium * This is a bug-fix only upload and does not include any new changes to diff -Nru nginx-1.9.11/debian/patches/ubuntu-branding.patch nginx-1.9.12/debian/patches/ubuntu-branding.patch --- nginx-1.9.11/debian/patches/ubuntu-branding.patch 2016-02-09 10:35:08.000000000 -0500 +++ nginx-1.9.12/debian/patches/ubuntu-branding.patch 2016-02-24 10:25:35.000000000 -0500 @@ -9,8 +9,8 @@ +++ b/src/core/nginx.h @@ -11,7 +11,7 @@ - #define nginx_version 1009011 - #define NGINX_VERSION "1.9.11" + #define nginx_version 1009012 + #define NGINX_VERSION "1.9.12" -#define NGINX_VER "nginx/" NGINX_VERSION +#define NGINX_VER "nginx/" NGINX_VERSION " (Ubuntu)" diff -Nru nginx-1.9.11/src/core/nginx.c nginx-1.9.12/src/core/nginx.c --- nginx-1.9.11/src/core/nginx.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/core/nginx.c 2016-02-24 09:53:23.000000000 -0500 @@ -481,6 +481,12 @@ } } + if (v != p) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, + "invalid socket number \"%s\" in " NGINX_VAR + " environment variable, ignoring", v); + } + ngx_inherited = 1; return ngx_set_inherited_sockets(cycle); @@ -1264,16 +1270,16 @@ #if (NGX_HAVE_CPU_AFFINITY) ngx_core_conf_t *ccf = conf; - u_char ch; - uint64_t *mask; + u_char ch, *p; ngx_str_t *value; ngx_uint_t i, n; + ngx_cpuset_t *mask; if (ccf->cpu_affinity) { return "is duplicate"; } - mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t)); + mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t)); if (mask == NULL) { return NGX_CONF_ERROR; } @@ -1293,7 +1299,12 @@ } ccf->cpu_affinity_auto = 1; - mask[0] = (uint64_t) -1 >> (64 - ngx_min(64, ngx_ncpu)); + + CPU_ZERO(&mask[0]); + for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) { + CPU_SET(i, &mask[0]); + } + n = 2; } else { @@ -1302,30 +1313,34 @@ for ( /* void */ ; n < cf->args->nelts; n++) { - if (value[n].len > 64) { + if (value[n].len > CPU_SETSIZE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"worker_cpu_affinity\" supports up to 64 CPUs only"); + "\"worker_cpu_affinity\" supports up to %d CPUs only", + CPU_SETSIZE); return NGX_CONF_ERROR; } - mask[n - 1] = 0; + i = 0; + CPU_ZERO(&mask[n - 1]); - for (i = 0; i < value[n].len; i++) { - - ch = value[n].data[i]; + for (p = value[n].data + value[n].len - 1; + p >= value[n].data; + p--) + { + ch = *p; if (ch == ' ') { continue; } - mask[n - 1] <<= 1; + i++; if (ch == '0') { continue; } if (ch == '1') { - mask[n - 1] |= 1; + CPU_SET(i - 1, &mask[n - 1]); continue; } @@ -1347,43 +1362,57 @@ } -uint64_t +ngx_cpuset_t * ngx_get_cpu_affinity(ngx_uint_t n) { - uint64_t mask; - ngx_uint_t i; +#if (NGX_HAVE_CPU_AFFINITY) + ngx_uint_t i, j; + ngx_cpuset_t *mask; ngx_core_conf_t *ccf; + static ngx_cpuset_t result; + ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_core_module); if (ccf->cpu_affinity == NULL) { - return 0; + return NULL; } if (ccf->cpu_affinity_auto) { - mask = ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; - if (mask == 0) { - return 0; - } + for (i = 0, j = n; /* void */ ; i++) { - for (i = 0; /* void */ ; i++) { - if ((mask & ((uint64_t) 1 << (i % 64))) && n-- == 0) { + if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) { break; } + if (i == CPU_SETSIZE && j == n) { + /* empty mask */ + return NULL; + } + /* void */ } - return (uint64_t) 1 << (i % 64); + CPU_ZERO(&result); + CPU_SET(i % CPU_SETSIZE, &result); + + return &result; } if (ccf->cpu_affinity_n > n) { - return ccf->cpu_affinity[n]; + return &ccf->cpu_affinity[n]; } - return ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + +#else + + return NULL; + +#endif } diff -Nru nginx-1.9.11/src/core/nginx.h nginx-1.9.12/src/core/nginx.h --- nginx-1.9.11/src/core/nginx.h 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/core/nginx.h 2016-02-24 09:53:23.000000000 -0500 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009011 -#define NGINX_VERSION "1.9.11" +#define nginx_version 1009012 +#define NGINX_VERSION "1.9.12" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff -Nru nginx-1.9.11/src/core/ngx_cycle.h nginx-1.9.12/src/core/ngx_cycle.h --- nginx-1.9.11/src/core/ngx_cycle.h 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/core/ngx_cycle.h 2016-02-24 09:53:23.000000000 -0500 @@ -94,7 +94,7 @@ ngx_uint_t cpu_affinity_auto; ngx_uint_t cpu_affinity_n; - uint64_t *cpu_affinity; + ngx_cpuset_t *cpu_affinity; char *username; ngx_uid_t user; @@ -121,7 +121,7 @@ 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); -uint64_t ngx_get_cpu_affinity(ngx_uint_t n); +ngx_cpuset_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 -Nru nginx-1.9.11/src/core/ngx_module.c nginx-1.9.12/src/core/ngx_module.c --- nginx-1.9.11/src/core/ngx_module.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/core/ngx_module.c 2016-02-24 09:53:23.000000000 -0500 @@ -171,7 +171,7 @@ if (module->version != nginx_version) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "module \"%V\" version %ui instead of %ui", - file, module->version, nginx_version); + file, module->version, (ngx_uint_t) nginx_version); return NGX_ERROR; } diff -Nru nginx-1.9.11/src/core/ngx_module.h nginx-1.9.12/src/core/ngx_module.h --- nginx-1.9.11/src/core/ngx_module.h 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/core/ngx_module.h 2016-02-24 09:53:23.000000000 -0500 @@ -253,7 +253,7 @@ ngx_uint_t spare1; ngx_uint_t version; - char *signature; + const char *signature; void *ctx; ngx_command_t *commands; diff -Nru nginx-1.9.11/src/event/ngx_event_openssl.c nginx-1.9.12/src/event/ngx_event_openssl.c --- nginx-1.9.11/src/event/ngx_event_openssl.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/event/ngx_event_openssl.c 2016-02-24 09:53:23.000000000 -0500 @@ -1767,6 +1767,19 @@ int n, sslerr, mode; ngx_err_t err; + if (SSL_in_init(c->ssl->connection)) { + /* + * OpenSSL 1.0.2f complains if SSL_shutdown() is called during + * an SSL handshake, while previous versions always return 0. + * Avoid calling SSL_shutdown() if handshake wasn't completed. + */ + + SSL_free(c->ssl->connection); + c->ssl = NULL; + + return NGX_OK; + } + if (c->timedout) { mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; SSL_set_quiet_shutdown(c->ssl->connection, 1); @@ -1797,7 +1810,7 @@ sslerr = 0; - /* SSL_shutdown() never returns -1, on error it returns 0 */ + /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */ if (n != 1 && ERR_peek_error()) { sslerr = SSL_get_error(c->ssl->connection, n); diff -Nru nginx-1.9.11/src/http/modules/ngx_http_headers_filter_module.c nginx-1.9.12/src/http/modules/ngx_http_headers_filter_module.c --- nginx-1.9.11/src/http/modules/ngx_http_headers_filter_module.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/http/modules/ngx_http_headers_filter_module.c 2016-02-24 09:53:24.000000000 -0500 @@ -712,17 +712,17 @@ if (value[2].len == 0) { ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t)); - return NGX_CONF_OK; - } - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + } else { + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - ccv.cf = cf; - ccv.value = &value[2]; - ccv.complex_value = &hv->value; + ccv.cf = cf; + ccv.value = &value[2]; + ccv.complex_value = &hv->value; - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } } if (cf->args->nelts == 3) { diff -Nru nginx-1.9.11/src/http/ngx_http_request.c nginx-1.9.12/src/http/ngx_http_request.c --- nginx-1.9.11/src/http/ngx_http_request.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/http/ngx_http_request.c 2016-02-24 09:53:24.000000000 -0500 @@ -1351,12 +1351,11 @@ continue; } - /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid header line: \"%*s\\r...\"", - r->header_end - r->header_name_start, - r->header_name_start); + "client sent invalid header line"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } @@ -2574,12 +2573,6 @@ ngx_http_test_reading; r->write_event_handler = ngx_http_writer; -#if (NGX_HTTP_V2) - if (r->stream) { - return NGX_OK; - } -#endif - wev = r->connection->write; if (wev->ready && wev->delayed) { @@ -2665,12 +2658,6 @@ if (r->buffered || r->postponed || (r == r->main && c->buffered)) { -#if (NGX_HTTP_V2) - if (r->stream) { - return; - } -#endif - if (!wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } diff -Nru nginx-1.9.11/src/http/v2/ngx_http_v2.c nginx-1.9.12/src/http/v2/ngx_http_v2.c --- nginx-1.9.11/src/http/v2/ngx_http_v2.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/http/v2/ngx_http_v2.c 2016-02-24 09:53:24.000000000 -0500 @@ -112,10 +112,10 @@ u_char *pos, u_char *end); static u_char *ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end); -static u_char *ngx_http_v2_state_skip_headers(ngx_http_v2_connection_t *h2c, - u_char *pos, u_char *end); static u_char *ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); +static u_char *ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); static u_char *ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, ngx_uint_t err); @@ -164,6 +164,7 @@ static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); static void ngx_http_v2_run_request(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); +static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream, ngx_uint_t status); @@ -432,6 +433,10 @@ "run http2 stream %ui", stream->node->id); wev = stream->request->connection->write; + + wev->active = 0; + wev->ready = 1; + wev->handler(wev); } @@ -885,6 +890,7 @@ ngx_buf_t *buf; ngx_int_t rc; ngx_temp_file_t *tf; + ngx_connection_t *fc; ngx_http_request_t *r; ngx_http_v2_stream_t *stream; ngx_http_request_body_t *rb; @@ -921,6 +927,7 @@ return ngx_http_v2_state_skip_padded(h2c, pos, end); } + fc = r->connection; rb = r->request_body; tf = rb->temp_file; buf = rb->buf; @@ -931,7 +938,7 @@ if (r->headers_in.content_length_n != -1 && r->headers_in.content_length_n < rb->rest) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client intended to send body data " "larger than declared"); @@ -944,7 +951,7 @@ if (clcf->client_max_body_size && clcf->client_max_body_size < rb->rest) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, fc->log, 0, "client intended to send " "too large chunked body: %O bytes", rb->rest); @@ -984,6 +991,11 @@ } if (h2c->state.length) { + if (rb->post_handler) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); + } + return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_read_data); } @@ -995,7 +1007,7 @@ r->headers_in.content_length_n = rb->rest; } else if (r->headers_in.content_length_n != rb->rest) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client prematurely closed stream: " "only %O out of %O bytes of request body received", rb->rest, r->headers_in.content_length_n); @@ -1015,9 +1027,17 @@ } if (rb->post_handler) { + if (fc->read->timer_set) { + ngx_del_timer(fc->read); + } + r->read_event_handler = ngx_http_block_reading; rb->post_handler(r); } + + } else if (rb->post_handler) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); } if (h2c->state.padding) { @@ -1029,6 +1049,9 @@ error: if (rb->post_handler) { + if (fc->read->timer_set) { + ngx_del_timer(fc->read); + } if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) { rc = (r->headers_in.content_length_n == -1) @@ -1133,6 +1156,11 @@ h2c->last_sid = h2c->state.sid; + h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); + if (h2c->state.pool == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + if (depend == h2c->state.sid) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent HEADERS frame for stream %ui " @@ -1146,7 +1174,7 @@ NGX_HTTP_V2_INTERNAL_ERROR); } - return ngx_http_v2_state_skip_headers(h2c, pos, end); + return ngx_http_v2_state_header_block(h2c, pos, end); } h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -1166,7 +1194,7 @@ NGX_HTTP_V2_INTERNAL_ERROR); } - return ngx_http_v2_state_skip_headers(h2c, pos, end); + return ngx_http_v2_state_header_block(h2c, pos, end); } node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1); @@ -1185,6 +1213,11 @@ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } + h2c->state.stream = stream; + + stream->pool = h2c->state.pool; + h2c->state.keep_pool = 1; + stream->request->request_length = h2c->state.length; stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; @@ -1192,9 +1225,6 @@ node->stream = stream; - h2c->state.stream = stream; - h2c->state.pool = stream->request->pool; - if (priority || node->parent == NULL) { node->weight = weight; ngx_http_v2_set_dependency(h2c, node, depend, excl); @@ -1213,8 +1243,8 @@ ngx_uint_t indexed, size_update, prefix; if (end - pos < 1) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_header_block); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_header_block); } if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) @@ -1257,8 +1287,8 @@ if (value < 0) { if (value == NGX_AGAIN) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_header_block); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_header_block); } if (value == NGX_DECLINED) { @@ -1328,8 +1358,8 @@ } if (end - pos < 1) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_len); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_len); } huff = *pos >> 7; @@ -1337,8 +1367,8 @@ if (len < 0) { if (len == NGX_AGAIN) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_len); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_len); } if (len == NGX_DECLINED) { @@ -1430,8 +1460,8 @@ } if (h2c->state.length) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_huff); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_huff); } if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { @@ -1475,8 +1505,8 @@ } if (h2c->state.length) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_raw); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_raw); } if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { @@ -1686,7 +1716,6 @@ error: h2c->state.stream = NULL; - h2c->state.pool = NULL; return ngx_http_v2_state_header_complete(h2c, pos, end); } @@ -1699,8 +1728,7 @@ ngx_http_v2_stream_t *stream; if (h2c->state.length) { - h2c->state.handler = h2c->state.pool ? ngx_http_v2_state_header_block - : ngx_http_v2_state_skip_headers; + h2c->state.handler = ngx_http_v2_state_header_block; return pos; } @@ -1713,12 +1741,14 @@ if (stream) { ngx_http_v2_run_request(stream->request); + } - } else if (h2c->state.pool) { + if (!h2c->state.keep_pool) { ngx_destroy_pool(h2c->state.pool); } h2c->state.pool = NULL; + h2c->state.keep_pool = 0; if (h2c->state.padding) { return ngx_http_v2_state_skip_padded(h2c, pos, end); @@ -1749,7 +1779,7 @@ } if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) { - return ngx_http_v2_state_save(h2c, pos, end, handler); + return ngx_http_v2_state_headers_save(h2c, pos, end, handler); } p = pos + len; @@ -2224,8 +2254,10 @@ wev = stream->request->connection->write; - if (!wev->timer_set) { - wev->delayed = 0; + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { wev->handler(wev); } } @@ -2257,8 +2289,10 @@ wev = stream->request->connection->write; - if (!wev->timer_set) { - wev->delayed = 0; + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { wev->handler(wev); if (h2c->send_window == 0) { @@ -2337,19 +2371,6 @@ static u_char * -ngx_http_v2_state_skip_headers(ngx_http_v2_connection_t *h2c, u_char *pos, - u_char *end) -{ - h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); - if (h2c->state.pool == NULL) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); - } - - return ngx_http_v2_state_header_block(h2c, pos, end); -} - - -static u_char * ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, ngx_http_v2_handler_pt handler) { @@ -2379,6 +2400,28 @@ static u_char * +ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end, ngx_http_v2_handler_pt handler) +{ + ngx_event_t *rev; + ngx_http_request_t *r; + ngx_http_core_srv_conf_t *cscf; + + if (h2c->state.stream) { + r = h2c->state.stream->request; + rev = r->connection->read; + + if (!rev->timer_set) { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + ngx_add_timer(rev, cscf->client_header_timeout); + } + } + + return ngx_http_v2_state_save(h2c, pos, end, handler); +} + + +static u_char * ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, ngx_uint_t err) { @@ -2756,6 +2799,7 @@ ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); log->data = ctx; + log->action = "reading client request headers"; ngx_memzero(rev, sizeof(ngx_event_t)); @@ -3562,7 +3606,8 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler) { - ngx_http_v2_stream_t *stream; + ngx_http_v2_stream_t *stream; + ngx_http_core_loc_conf_t *clcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http2 read request body"); @@ -3598,13 +3643,48 @@ r->request_body->post_handler = post_handler; - r->read_event_handler = ngx_http_test_reading; + r->read_event_handler = ngx_http_v2_read_client_request_body_handler; r->write_event_handler = ngx_http_request_empty_handler; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(r->connection->read, clcf->client_body_timeout); + return NGX_AGAIN; } +static void +ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) +{ + ngx_connection_t *fc; + + fc = r->connection; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 read client request body handler"); + + if (fc->read->timedout) { + ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); + + fc->timedout = 1; + r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; + + ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + + if (fc->error) { + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client prematurely closed stream"); + + r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; + + ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } +} + + static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream, ngx_uint_t status) @@ -3633,6 +3713,7 @@ void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) { + ngx_pool_t *pool; ngx_event_t *ev; ngx_connection_t *fc; ngx_http_v2_node_t *node; @@ -3654,27 +3735,44 @@ if (!stream->out_closed) { if (ngx_http_v2_send_rst_stream(h2c, node->id, - NGX_HTTP_V2_INTERNAL_ERROR) + fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR + : NGX_HTTP_V2_INTERNAL_ERROR) != NGX_OK) { h2c->connection->error = 1; } } + if (h2c->state.stream == stream) { + h2c->state.stream = NULL; + } + node->stream = NULL; ngx_queue_insert_tail(&h2c->closed, &node->reuse); h2c->closed_nodes++; + /* + * This pool keeps decoded request headers which can be used by log phase + * handlers in ngx_http_free_request(). + * + * The pointer is stored into local variable because the stream object + * will be destroyed after a call to ngx_http_free_request(). + */ + pool = stream->pool; + ngx_http_free_request(stream->request, rc); - ev = fc->read; + if (pool != h2c->state.pool) { + ngx_destroy_pool(pool); - if (ev->active || ev->disabled) { - ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, - "fake read event was activated"); + } else { + /* pool will be destroyed when the complete header is parsed */ + h2c->state.keep_pool = 0; } + ev = fc->read; + if (ev->timer_set) { ngx_del_timer(ev); } @@ -3685,11 +3783,6 @@ ev = fc->write; - if (ev->active || ev->disabled) { - ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, - "fake write event was activated"); - } - if (ev->timer_set) { ngx_del_timer(ev); } @@ -3723,9 +3816,18 @@ fc = ev->data; r = fc->data; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 close stream handler"); + if (ev->timedout) { + ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); + + fc->timedout = 1; + + ngx_http_v2_close_stream(r->stream, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + ngx_http_v2_close_stream(r->stream, 0); } @@ -3733,7 +3835,11 @@ static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev) { - ngx_connection_t *c; + ngx_connection_t *c; + ngx_http_v2_connection_t *h2c; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, + "http2 handle connection handler"); rev->handler = ngx_http_v2_read_handler; @@ -3743,6 +3849,12 @@ } c = rev->data; + h2c = c->data; + + if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { + ngx_http_v2_finalize_connection(h2c, 0); + return; + } ngx_http_v2_handle_connection(c->data); } @@ -3821,7 +3933,6 @@ if (h2c->state.stream) { h2c->state.stream->out_closed = 1; - h2c->state.pool = NULL; ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); } @@ -3865,9 +3976,7 @@ if (stream->queued) { stream->queued = 0; - ev = fc->write; - ev->delayed = 0; } else { ev = fc->read; @@ -3936,8 +4045,10 @@ wev = stream->request->connection->write; - if (!wev->timer_set) { - wev->delayed = 0; + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { wev->handler(wev); } } diff -Nru nginx-1.9.11/src/http/v2/ngx_http_v2_filter_module.c nginx-1.9.12/src/http/v2/ngx_http_v2_filter_module.c --- nginx-1.9.11/src/http/v2/ngx_http_v2_filter_module.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/http/v2/ngx_http_v2_filter_module.c 2016-02-24 09:53:24.000000000 -0500 @@ -25,6 +25,11 @@ #define ngx_http_v2_indexed(i) (128 + (i)) #define ngx_http_v2_inc_indexed(i) (64 + (i)) +#define ngx_http_v2_write_name(dst, src, len, tmp) \ + ngx_http_v2_string_encode(dst, src, len, tmp, 1) +#define ngx_http_v2_write_value(dst, src, len, tmp) \ + ngx_http_v2_string_encode(dst, src, len, tmp, 0) + #define NGX_HTTP_V2_ENCODE_RAW 0 #define NGX_HTTP_V2_ENCODE_HUFF 0x80 @@ -46,6 +51,8 @@ #define NGX_HTTP_V2_VARY_INDEX 59 +static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, + u_char *tmp, ngx_uint_t lower); static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value); static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( @@ -119,8 +126,8 @@ static ngx_int_t ngx_http_v2_header_filter(ngx_http_request_t *r) { - u_char status, *pos, *start, *p; - size_t len; + u_char status, *pos, *start, *p, *tmp; + size_t len, tmp_len; ngx_str_t host, location; ngx_uint_t i, port; ngx_list_part_t *part; @@ -136,6 +143,14 @@ #endif u_char addr[NGX_SOCKADDR_STRLEN]; + static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; +#if (NGX_HTTP_GZIP) + static const u_char accept_encoding[12] = + "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f"; +#endif + + static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER); + static u_char nginx_ver[ngx_http_v2_literal_size(NGINX_VER)]; if (!r->stream) { return ngx_http_next_header_filter(r); @@ -215,8 +230,7 @@ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { - len += 1 + (clcf->server_tokens ? ngx_http_v2_literal_size(NGINX_VER) - : ngx_http_v2_literal_size("nginx")); + len += 1 + (clcf->server_tokens ? nginx_ver_len : sizeof(nginx)); } if (r->headers_out.date == NULL) { @@ -340,10 +354,12 @@ len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.location->value.len; } + tmp_len = len; + #if (NGX_HTTP_GZIP) if (r->gzip_vary) { if (clcf->gzip_vary) { - len += 1 + ngx_http_v2_literal_size("Accept-Encoding"); + len += 1 + sizeof(accept_encoding); } else { r->gzip_vary = 0; @@ -371,14 +387,14 @@ } if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + ngx_log_error(NGX_LOG_CRIT, fc->log, 0, "too long response header name: \"%V\"", &header[i].key); return NGX_ERROR; } if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + ngx_log_error(NGX_LOG_CRIT, fc->log, 0, "too long response header value: \"%V: %V\"", &header[i].key, &header[i].value); return NGX_ERROR; @@ -386,15 +402,29 @@ len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; + + if (header[i].key.len > tmp_len) { + tmp_len = header[i].key.len; + } + + if (header[i].value.len > tmp_len) { + tmp_len = header[i].value.len; + } } - pos = ngx_palloc(r->pool, len); - if (pos == NULL) { + tmp = ngx_palloc(r->pool, tmp_len); + pos = ngx_pnalloc(r->pool, len); + + if (pos == NULL || tmp == NULL) { return NGX_ERROR; } start = pos; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \":status: %03ui\"", + r->headers_out.status); + if (status) { *pos++ = status; @@ -405,24 +435,34 @@ } if (r->headers_out.server == NULL) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"server: %s\"", + clcf->server_tokens ? NGINX_VER : "nginx"); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); if (clcf->server_tokens) { - *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof(NGINX_VER) - 1); - pos = ngx_cpymem(pos, NGINX_VER, sizeof(NGINX_VER) - 1); + if (nginx_ver[0] == '\0') { + p = ngx_http_v2_write_value(nginx_ver, (u_char *) NGINX_VER, + sizeof(NGINX_VER) - 1, tmp); + nginx_ver_len = p - nginx_ver; + } + + pos = ngx_cpymem(pos, nginx_ver, nginx_ver_len); } else { - *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("nginx") - 1); - pos = ngx_cpymem(pos, "nginx", sizeof("nginx") - 1); + pos = ngx_cpymem(pos, nginx, sizeof(nginx)); } } if (r->headers_out.date == NULL) { - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); - *pos++ = (u_char) ngx_cached_http_time.len; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"date: %V\"", + &ngx_cached_http_time); - pos = ngx_cpymem(pos, ngx_cached_http_time.data, - ngx_cached_http_time.len); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); + pos = ngx_http_v2_write_value(pos, ngx_cached_http_time.data, + ngx_cached_http_time.len, tmp); } if (r->headers_out.content_type.len) { @@ -431,39 +471,43 @@ if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - r->headers_out.content_type.len - + sizeof("; charset=") - 1 - + r->headers_out.charset.len); - - p = pos; + len = r->headers_out.content_type.len + sizeof("; charset=") - 1 + + r->headers_out.charset.len; - pos = ngx_cpymem(pos, r->headers_out.content_type.data, - r->headers_out.content_type.len); + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } - pos = ngx_cpymem(pos, "; charset=", sizeof("; charset=") - 1); + p = ngx_cpymem(p, r->headers_out.content_type.data, + r->headers_out.content_type.len); - pos = ngx_cpymem(pos, r->headers_out.charset.data, - r->headers_out.charset.len); + p = ngx_cpymem(p, "; charset=", sizeof("; charset=") - 1); - /* update r->headers_out.content_type for possible logging */ + p = ngx_cpymem(p, r->headers_out.charset.data, + r->headers_out.charset.len); - r->headers_out.content_type.len = pos - p; - r->headers_out.content_type.data = p; + /* updated r->headers_out.content_type is also needed for logging */ - } else { - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - r->headers_out.content_type.len); - pos = ngx_cpymem(pos, r->headers_out.content_type.data, - r->headers_out.content_type.len); + r->headers_out.content_type.len = len; + r->headers_out.content_type.data = p - len; } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"content-type: %V\"", + &r->headers_out.content_type); + + pos = ngx_http_v2_write_value(pos, r->headers_out.content_type.data, + r->headers_out.content_type.len, tmp); } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"content-length: %O\"", + r->headers_out.content_length_n); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); p = pos; @@ -476,26 +520,37 @@ { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX); - *pos++ = NGX_HTTP_V2_ENCODE_RAW - | (sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1); - pos = ngx_http_time(pos, r->headers_out.last_modified_time); + ngx_http_time(pos, r->headers_out.last_modified_time); + len = sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"last-modified: %*s\"", + len, pos); + + /* + * Date will always be encoded using huffman in the temporary buffer, + * so it's safe here to use src and dst pointing to the same address. + */ + pos = ngx_http_v2_write_value(pos, pos, len, tmp); } if (r->headers_out.location && r->headers_out.location->value.len) { - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"location: %V\"", + &r->headers_out.location->value); - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - r->headers_out.location->value.len); - pos = ngx_cpymem(pos, r->headers_out.location->value.data, - r->headers_out.location->value.len); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + pos = ngx_http_v2_write_value(pos, r->headers_out.location->value.data, + r->headers_out.location->value.len, tmp); } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"vary: Accept-Encoding\""); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); - *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("Accept-Encoding") - 1); - pos = ngx_cpymem(pos, "Accept-Encoding", sizeof("Accept-Encoding") - 1); + pos = ngx_cpymem(pos, accept_encoding, sizeof(accept_encoding)); } #endif @@ -518,18 +573,23 @@ continue; } +#if (NGX_DEBUG) + if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) { + ngx_strlow(tmp, header[i].key.data, header[i].key.len); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"%*s: %V\"", + header[i].key.len, tmp, &header[i].value); + } +#endif + *pos++ = 0; - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - header[i].key.len); - ngx_strlow(pos, header[i].key.data, header[i].key.len); - pos += header[i].key.len; - - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - header[i].value.len); - pos = ngx_cpymem(pos, header[i].value.data, header[i].value.len); + pos = ngx_http_v2_write_name(pos, header[i].key.data, + header[i].key.len, tmp); + + pos = ngx_http_v2_write_value(pos, header[i].value.data, + header[i].value.len, tmp); } frame = ngx_http_v2_create_headers_frame(r, start, pos); @@ -557,6 +617,32 @@ static u_char * +ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, + ngx_uint_t lower) +{ + size_t hlen; + + hlen = ngx_http_v2_huff_encode(src, len, tmp, lower); + + if (hlen > 0) { + *dst = NGX_HTTP_V2_ENCODE_HUFF; + dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), hlen); + return ngx_cpymem(dst, tmp, hlen); + } + + *dst = NGX_HTTP_V2_ENCODE_RAW; + dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), len); + + if (lower) { + ngx_strlow(dst, src, len); + return dst + len; + } + + return ngx_cpymem(dst, src, len); +} + + +static u_char * ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) { if (value < prefix) { @@ -713,7 +799,9 @@ if (in == NULL) { if (stream->queued) { - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; + } else { fc->buffered &= ~NGX_HTTP_V2_BUFFERED; } @@ -724,7 +812,8 @@ h2c = stream->connection; if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; return in; } @@ -861,7 +950,8 @@ } if (in && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; } return in; @@ -992,7 +1082,8 @@ if (stream->queued) { fc->buffered |= NGX_HTTP_V2_BUFFERED; - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; return NGX_AGAIN; } @@ -1230,14 +1321,7 @@ wev = stream->request->connection->write; - /* - * This timer can only be set if the stream was delayed because of rate - * limit. In that case the event should be triggered by the timer. - */ - - if (!wev->timer_set) { - wev->delayed = 0; - + if (!wev->delayed) { stream->handled = 1; ngx_queue_insert_tail(&h2c->posted, &stream->queue); } diff -Nru nginx-1.9.11/src/http/v2/ngx_http_v2.h nginx-1.9.12/src/http/v2/ngx_http_v2.h --- nginx-1.9.11/src/http/v2/ngx_http_v2.h 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/http/v2/ngx_http_v2.h 2016-02-24 09:53:24.000000000 -0500 @@ -73,6 +73,7 @@ unsigned flags:8; unsigned incomplete:1; + unsigned keep_pool:1; /* HPACK */ unsigned parse_name:1; @@ -186,6 +187,8 @@ size_t header_limit; + ngx_pool_t *pool; + unsigned handled:1; unsigned blocked:1; unsigned exhausted:1; @@ -274,6 +277,8 @@ ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, ngx_uint_t last, ngx_log_t *log); +size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, + ngx_uint_t lower); #define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1) diff -Nru nginx-1.9.11/src/http/v2/ngx_http_v2_huff_encode.c nginx-1.9.12/src/http/v2/ngx_http_v2_huff_encode.c --- nginx-1.9.11/src/http/v2/ngx_http_v2_huff_encode.c 2016-02-09 09:11:57.000000000 -0500 +++ nginx-1.9.12/src/http/v2/ngx_http_v2_huff_encode.c 2016-02-24 09:53:24.000000000 -0500 @@ -2,9 +2,253 @@ /* * Copyright (C) Nginx, Inc. * Copyright (C) Valentin V. Bartenev + * Copyright (C) 2015 Vlad Krasnov */ #include #include #include + + +typedef struct { + uint32_t code; + uint32_t len; +} ngx_http_v2_huff_encode_code_t; + + +static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table[256] = +{ + {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, + {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, + {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28}, + {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28}, + {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28}, + {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28}, + {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28}, + {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28}, + {0x00000014, 6}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12}, + {0x00001ff9, 13}, {0x00000015, 6}, {0x000000f8, 8}, {0x000007fa, 11}, + {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f9, 8}, {0x000007fb, 11}, + {0x000000fa, 8}, {0x00000016, 6}, {0x00000017, 6}, {0x00000018, 6}, + {0x00000000, 5}, {0x00000001, 5}, {0x00000002, 5}, {0x00000019, 6}, + {0x0000001a, 6}, {0x0000001b, 6}, {0x0000001c, 6}, {0x0000001d, 6}, + {0x0000001e, 6}, {0x0000001f, 6}, {0x0000005c, 7}, {0x000000fb, 8}, + {0x00007ffc, 15}, {0x00000020, 6}, {0x00000ffb, 12}, {0x000003fc, 10}, + {0x00001ffa, 13}, {0x00000021, 6}, {0x0000005d, 7}, {0x0000005e, 7}, + {0x0000005f, 7}, {0x00000060, 7}, {0x00000061, 7}, {0x00000062, 7}, + {0x00000063, 7}, {0x00000064, 7}, {0x00000065, 7}, {0x00000066, 7}, + {0x00000067, 7}, {0x00000068, 7}, {0x00000069, 7}, {0x0000006a, 7}, + {0x0000006b, 7}, {0x0000006c, 7}, {0x0000006d, 7}, {0x0000006e, 7}, + {0x0000006f, 7}, {0x00000070, 7}, {0x00000071, 7}, {0x00000072, 7}, + {0x000000fc, 8}, {0x00000073, 7}, {0x000000fd, 8}, {0x00001ffb, 13}, + {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x00000022, 6}, + {0x00007ffd, 15}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, + {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, + {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, + {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, + {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, + {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, + {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00007ffe, 15}, + {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28}, + {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20}, + {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23}, + {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23}, + {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23}, + {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23}, + {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23}, + {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23}, + {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24}, + {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22}, + {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21}, + {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24}, + {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23}, + {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21}, + {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23}, + {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22}, + {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23}, + {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19}, + {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25}, + {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27}, + {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25}, + {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27}, + {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24}, + {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26}, + {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27}, + {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21}, + {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23}, + {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25}, + {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23}, + {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26}, + {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27}, + {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27}, + {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26} +}; + + +/* same as above, but embeds lowercase transformation */ +static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] = +{ + {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, + {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, + {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28}, + {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28}, + {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28}, + {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28}, + {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28}, + {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28}, + {0x00000014, 6}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12}, + {0x00001ff9, 13}, {0x00000015, 6}, {0x000000f8, 8}, {0x000007fa, 11}, + {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f9, 8}, {0x000007fb, 11}, + {0x000000fa, 8}, {0x00000016, 6}, {0x00000017, 6}, {0x00000018, 6}, + {0x00000000, 5}, {0x00000001, 5}, {0x00000002, 5}, {0x00000019, 6}, + {0x0000001a, 6}, {0x0000001b, 6}, {0x0000001c, 6}, {0x0000001d, 6}, + {0x0000001e, 6}, {0x0000001f, 6}, {0x0000005c, 7}, {0x000000fb, 8}, + {0x00007ffc, 15}, {0x00000020, 6}, {0x00000ffb, 12}, {0x000003fc, 10}, + {0x00001ffa, 13}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, + {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, + {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, + {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, + {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, + {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, + {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00001ffb, 13}, + {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x00000022, 6}, + {0x00007ffd, 15}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, + {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, + {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, + {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, + {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, + {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, + {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00007ffe, 15}, + {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28}, + {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20}, + {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23}, + {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23}, + {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23}, + {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23}, + {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23}, + {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23}, + {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24}, + {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22}, + {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21}, + {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24}, + {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23}, + {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21}, + {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23}, + {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22}, + {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23}, + {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19}, + {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25}, + {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27}, + {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25}, + {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27}, + {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24}, + {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26}, + {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27}, + {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21}, + {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23}, + {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25}, + {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23}, + {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26}, + {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27}, + {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27}, + {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26} +}; + + +#if (NGX_PTR_SIZE == 8) + +#if (NGX_HAVE_LITTLE_ENDIAN) + +#if (NGX_HAVE_GCC_BSWAP64) +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + (*(uint64_t *) (dst) = __builtin_bswap64(buf)) +#else +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + ((dst)[0] = (u_char) ((buf) >> 56), \ + (dst)[1] = (u_char) ((buf) >> 48), \ + (dst)[2] = (u_char) ((buf) >> 40), \ + (dst)[3] = (u_char) ((buf) >> 32), \ + (dst)[4] = (u_char) ((buf) >> 24), \ + (dst)[5] = (u_char) ((buf) >> 16), \ + (dst)[6] = (u_char) ((buf) >> 8), \ + (dst)[7] = (u_char) (buf)) +#endif + +#else /* !NGX_HAVE_LITTLE_ENDIAN */ +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + (*(uint64_t *) (dst) = (buf)) +#endif + +#else /* NGX_PTR_SIZE == 4 */ + +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + (*(uint32_t *) (dst) = htonl(buf)) + +#endif + + +size_t +ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower) +{ + u_char *end; + size_t hlen; + ngx_uint_t buf, pending, code; + ngx_http_v2_huff_encode_code_t *table, *next; + + table = lower ? ngx_http_v2_huff_encode_table_lc + : ngx_http_v2_huff_encode_table; + hlen = 0; + buf = 0; + pending = 0; + + end = src + len; + + while (src != end) { + next = &table[*src++]; + + code = next->code; + pending += next->len; + + /* accumulate bits */ + if (pending < sizeof(buf) * 8) { + buf |= code << (sizeof(buf) * 8 - pending); + continue; + } + + if (hlen + sizeof(buf) >= len) { + return 0; + } + + pending -= sizeof(buf) * 8; + + buf |= code >> pending; + + ngx_http_v2_huff_encode_buf(&dst[hlen], buf); + + hlen += sizeof(buf); + + buf = pending ? code << (sizeof(buf) * 8 - pending) : 0; + } + + if (pending == 0) { + return hlen; + } + + buf |= (ngx_uint_t) -1 >> pending; + + pending = ngx_align(pending, 8); + + if (hlen + pending / 8 >= len) { + return 0; + } + + buf >>= sizeof(buf) * 8 - pending; + + do { + pending -= 8; + dst[hlen++] = (u_char) (buf >> pending); + } while (pending); + + return hlen; +} diff -Nru nginx-1.9.11/src/os/unix/ngx_process_cycle.c nginx-1.9.12/src/os/unix/ngx_process_cycle.c --- nginx-1.9.11/src/os/unix/ngx_process_cycle.c 2016-02-09 09:11:58.000000000 -0500 +++ nginx-1.9.12/src/os/unix/ngx_process_cycle.c 2016-02-24 09:53:24.000000000 -0500 @@ -784,9 +784,9 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) { sigset_t set; - uint64_t cpu_affinity; ngx_int_t n; ngx_uint_t i; + ngx_cpuset_t *cpu_affinity; struct rlimit rlmt; ngx_core_conf_t *ccf; ngx_listening_t *ls; diff -Nru nginx-1.9.11/src/os/unix/ngx_setaffinity.c nginx-1.9.12/src/os/unix/ngx_setaffinity.c --- nginx-1.9.11/src/os/unix/ngx_setaffinity.c 2016-02-09 09:11:58.000000000 -0500 +++ nginx-1.9.12/src/os/unix/ngx_setaffinity.c 2016-02-24 09:53:24.000000000 -0500 @@ -10,29 +10,20 @@ #if (NGX_HAVE_CPUSET_SETAFFINITY) -#include - void -ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +ngx_setaffinity(ngx_cpuset_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); + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, cpu_affinity)) { + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "cpuset_setaffinity(): using cpu #%ui", i); } - i++; - cpu_affinity >>= 1; - } while (cpu_affinity); + } if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, - sizeof(cpuset_t), &mask) == -1) + sizeof(cpuset_t), cpu_affinity) == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "cpuset_setaffinity() failed"); @@ -42,25 +33,18 @@ #elif (NGX_HAVE_SCHED_SETAFFINITY) void -ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +ngx_setaffinity(ngx_cpuset_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); + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, cpu_affinity)) { + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "sched_setaffinity(): using cpu #%ui", i); } - i++; - cpu_affinity >>= 1; - } while (cpu_affinity); + } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + if (sched_setaffinity(0, sizeof(cpu_set_t), cpu_affinity) == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sched_setaffinity() failed"); } diff -Nru nginx-1.9.11/src/os/unix/ngx_setaffinity.h nginx-1.9.12/src/os/unix/ngx_setaffinity.h --- nginx-1.9.11/src/os/unix/ngx_setaffinity.h 2016-02-09 09:11:58.000000000 -0500 +++ nginx-1.9.12/src/os/unix/ngx_setaffinity.h 2016-02-24 09:53:24.000000000 -0500 @@ -11,12 +11,26 @@ #define NGX_HAVE_CPU_AFFINITY 1 -void ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log); +#if (NGX_HAVE_SCHED_SETAFFINITY) + +typedef cpu_set_t ngx_cpuset_t; + +#elif (NGX_HAVE_CPUSET_SETAFFINITY) + +#include + +typedef cpuset_t ngx_cpuset_t; + +#endif + +void ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log); #else #define ngx_setaffinity(cpu_affinity, log) +typedef uint64_t ngx_cpuset_t; + #endif diff -Nru nginx-1.9.11/src/stream/ngx_stream_proxy_module.c nginx-1.9.12/src/stream/ngx_stream_proxy_module.c --- nginx-1.9.11/src/stream/ngx_stream_proxy_module.c 2016-02-09 09:11:58.000000000 -0500 +++ nginx-1.9.12/src/stream/ngx_stream_proxy_module.c 2016-02-24 09:53:24.000000000 -0500 @@ -10,9 +10,6 @@ #include -typedef void (*ngx_stream_proxy_handler_pt)(ngx_stream_session_t *s); - - typedef struct { ngx_msec_t connect_timeout; ngx_msec_t timeout; @@ -435,8 +432,6 @@ ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc); - pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - if (rc == NGX_ERROR) { ngx_stream_proxy_finalize(s, NGX_ERROR); return; @@ -471,6 +466,8 @@ pc->read->handler = ngx_stream_proxy_connect_handler; pc->write->handler = ngx_stream_proxy_connect_handler; + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + ngx_add_timer(pc->write, pscf->connect_timeout); }