New upstream version 1.24.0
This commit is contained in:
parent
dbf15d0b7a
commit
8094197df9
129 changed files with 10228 additions and 1745 deletions
148
CHANGES
148
CHANGES
|
|
@ -1,15 +1,157 @@
|
|||
|
||||
Changes with nginx 1.22.1 19 Oct 2022
|
||||
Changes with nginx 1.24.0 11 Apr 2023
|
||||
|
||||
*) 1.24.x stable branch.
|
||||
|
||||
|
||||
Changes with nginx 1.23.4 28 Mar 2023
|
||||
|
||||
*) Change: now TLSv1.3 protocol is enabled by default.
|
||||
|
||||
*) Change: now nginx issues a warning if protocol parameters of a
|
||||
listening socket are redefined.
|
||||
|
||||
*) Change: now nginx closes connections with lingering if pipelining was
|
||||
used by the client.
|
||||
|
||||
*) Feature: byte ranges support in the ngx_http_gzip_static_module.
|
||||
|
||||
*) Bugfix: port ranges in the "listen" directive did not work; the bug
|
||||
had appeared in 1.23.3.
|
||||
Thanks to Valentin Bartenev.
|
||||
|
||||
*) Bugfix: incorrect location might be chosen to process a request if a
|
||||
prefix location longer than 255 characters was used in the
|
||||
configuration.
|
||||
|
||||
*) Bugfix: non-ASCII characters in file names on Windows were not
|
||||
supported by the ngx_http_autoindex_module, the ngx_http_dav_module,
|
||||
and the "include" directive.
|
||||
|
||||
*) Change: the logging level of the "data length too long", "length too
|
||||
short", "bad legacy version", "no shared signature algorithms", "bad
|
||||
digest length", "missing sigalgs extension", "encrypted length too
|
||||
long", "bad length", "bad key update", "mixed handshake and non
|
||||
handshake data", "ccs received early", "data between ccs and
|
||||
finished", "packet length too long", "too many warn alerts", "record
|
||||
too small", and "got a fin before a ccs" SSL errors has been lowered
|
||||
from "crit" to "info".
|
||||
|
||||
*) Bugfix: a socket leak might occur when using HTTP/2 and the
|
||||
"error_page" directive to redirect errors with code 400.
|
||||
|
||||
*) Bugfix: messages about logging to syslog errors did not contain
|
||||
information that the errors happened while logging to syslog.
|
||||
Thanks to Safar Safarly.
|
||||
|
||||
*) Workaround: "gzip filter failed to use preallocated memory" alerts
|
||||
appeared in logs when using zlib-ng.
|
||||
|
||||
*) Bugfix: in the mail proxy server.
|
||||
|
||||
|
||||
Changes with nginx 1.23.3 13 Dec 2022
|
||||
|
||||
*) Bugfix: an error might occur when reading PROXY protocol version 2
|
||||
header with large number of TLVs.
|
||||
|
||||
*) Bugfix: a segmentation fault might occur in a worker process if SSI
|
||||
was used to process subrequests created by other modules.
|
||||
Thanks to Ciel Zhao.
|
||||
|
||||
*) Workaround: when a hostname used in the "listen" directive resolves
|
||||
to multiple addresses, nginx now ignores duplicates within these
|
||||
addresses.
|
||||
|
||||
*) Bugfix: nginx might hog CPU during unbuffered proxying if SSL
|
||||
connections to backends were used.
|
||||
|
||||
|
||||
Changes with nginx 1.23.2 19 Oct 2022
|
||||
|
||||
*) Security: processing of a specially crafted mp4 file by the
|
||||
ngx_http_mp4_module might cause a worker process crash, worker
|
||||
process memory disclosure, or might have potential other impact
|
||||
(CVE-2022-41741, CVE-2022-41742).
|
||||
|
||||
*) Feature: the "$proxy_protocol_tlv_..." variables.
|
||||
|
||||
Changes with nginx 1.22.0 24 May 2022
|
||||
*) Feature: TLS session tickets encryption keys are now automatically
|
||||
rotated when using shared memory in the "ssl_session_cache"
|
||||
directive.
|
||||
|
||||
*) 1.22.x stable branch.
|
||||
*) Change: the logging level of the "bad record type" SSL errors has
|
||||
been lowered from "crit" to "info".
|
||||
Thanks to Murilo Andrade.
|
||||
|
||||
*) Change: now when using shared memory in the "ssl_session_cache"
|
||||
directive the "could not allocate new session" errors are logged at
|
||||
the "warn" level instead of "alert" and not more often than once per
|
||||
second.
|
||||
|
||||
*) Bugfix: nginx/Windows could not be built with OpenSSL 3.0.x.
|
||||
|
||||
*) Bugfix: in logging of the PROXY protocol errors.
|
||||
Thanks to Sergey Brester.
|
||||
|
||||
*) Workaround: shared memory from the "ssl_session_cache" directive was
|
||||
spent on sessions using TLS session tickets when using TLSv1.3 with
|
||||
OpenSSL.
|
||||
|
||||
*) Workaround: timeout specified with the "ssl_session_timeout"
|
||||
directive did not work when using TLSv1.3 with OpenSSL or BoringSSL.
|
||||
|
||||
|
||||
Changes with nginx 1.23.1 19 Jul 2022
|
||||
|
||||
*) Feature: memory usage optimization in configurations with SSL
|
||||
proxying.
|
||||
|
||||
*) Feature: looking up of IPv4 addresses while resolving now can be
|
||||
disabled with the "ipv4=off" parameter of the "resolver" directive.
|
||||
|
||||
*) Change: the logging level of the "bad key share", "bad extension",
|
||||
"bad cipher", and "bad ecpoint" SSL errors has been lowered from
|
||||
"crit" to "info".
|
||||
|
||||
*) Bugfix: while returning byte ranges nginx did not remove the
|
||||
"Content-Range" header line if it was present in the original backend
|
||||
response.
|
||||
|
||||
*) Bugfix: a proxied response might be truncated during reconfiguration
|
||||
on Linux; the bug had appeared in 1.17.5.
|
||||
|
||||
|
||||
Changes with nginx 1.23.0 21 Jun 2022
|
||||
|
||||
*) Change in internal API: now header lines are represented as linked
|
||||
lists.
|
||||
|
||||
*) Change: now nginx combines arbitrary header lines with identical
|
||||
names when sending to FastCGI, SCGI, and uwsgi backends, in the
|
||||
$r->header_in() method of the ngx_http_perl_module, and during lookup
|
||||
of the "$http_...", "$sent_http_...", "$sent_trailer_...",
|
||||
"$upstream_http_...", and "$upstream_trailer_..." variables.
|
||||
|
||||
*) Bugfix: if there were multiple "Vary" header lines in the backend
|
||||
response, nginx only used the last of them when caching.
|
||||
|
||||
*) Bugfix: if there were multiple "WWW-Authenticate" header lines in the
|
||||
backend response and errors with code 401 were intercepted or the
|
||||
"auth_request" directive was used, nginx only sent the first of the
|
||||
header lines to the client.
|
||||
|
||||
*) Change: the logging level of the "application data after close
|
||||
notify" SSL errors has been lowered from "crit" to "info".
|
||||
|
||||
*) Bugfix: connections might hang if nginx was built on Linux 2.6.17 or
|
||||
newer, but was used on systems without EPOLLRDHUP support, notably
|
||||
with epoll emulation layers; the bug had appeared in 1.17.5.
|
||||
Thanks to Marcus Ball.
|
||||
|
||||
*) Bugfix: nginx did not cache the response if the "Expires" response
|
||||
header line disabled caching, but following "Cache-Control" header
|
||||
line enabled caching.
|
||||
|
||||
|
||||
Changes with nginx 1.21.6 25 Jan 2022
|
||||
|
|
|
|||
150
CHANGES.ru
150
CHANGES.ru
|
|
@ -1,5 +1,75 @@
|
|||
|
||||
Изменения в nginx 1.22.1 19.10.2022
|
||||
Изменения в nginx 1.24.0 11.04.2023
|
||||
|
||||
*) Стабильная ветка 1.24.x.
|
||||
|
||||
|
||||
Изменения в nginx 1.23.4 28.03.2023
|
||||
|
||||
*) Изменение: теперь протокол TLSv1.3 разрешён по умолчанию.
|
||||
|
||||
*) Изменение: теперь nginx выдаёт предупреждение при переопределении
|
||||
параметров listen-сокета, задающих используемые протоколы.
|
||||
|
||||
*) Изменение: теперь, если клиент использует pipelining, nginx закрывает
|
||||
соединения с ожиданием дополнительных данных (lingering close).
|
||||
|
||||
*) Добавление: поддержка byte ranges для ответов модуля
|
||||
ngx_http_gzip_static_module.
|
||||
|
||||
*) Исправление: диапазоны портов в директиве listen не работали; ошибка
|
||||
появилась в 1.23.3.
|
||||
Спасибо Валентину Бартеневу.
|
||||
|
||||
*) Исправление: для обработки запроса мог быть выбран неверный location,
|
||||
если в конфигурации использовался префиксный location длиннее 255
|
||||
символов.
|
||||
|
||||
*) Исправление: не-ASCII символы в именах файлов на Windows не
|
||||
поддерживались модулями ngx_http_autoindex_module и
|
||||
ngx_http_dav_module, а также директивой include.
|
||||
|
||||
*) Изменение: уровень логгирования ошибок SSL "data length too long",
|
||||
"length too short", "bad legacy version", "no shared signature
|
||||
algorithms", "bad digest length", "missing sigalgs extension",
|
||||
"encrypted length too long", "bad length", "bad key update", "mixed
|
||||
handshake and non handshake data", "ccs received early", "data
|
||||
between ccs and finished", "packet length too long", "too many warn
|
||||
alerts", "record too small", и "got a fin before a ccs" понижен с
|
||||
уровня crit до info.
|
||||
|
||||
*) Исправление: при использовании HTTP/2 и директивы error_page для
|
||||
перенаправления ошибок с кодом 400 могла происходить утечка сокетов.
|
||||
|
||||
*) Исправление: сообщения об ошибках записи в syslog не содержали
|
||||
информации о том, что ошибки происходили в процессе записи в syslog.
|
||||
Спасибо Safar Safarly.
|
||||
|
||||
*) Изменение: при использовании zlib-ng в логах появлялись сообщения
|
||||
"gzip filter failed to use preallocated memory".
|
||||
|
||||
*) Исправление: в почтовом прокси-сервере.
|
||||
|
||||
|
||||
Изменения в nginx 1.23.3 13.12.2022
|
||||
|
||||
*) Исправление: при чтении заголовка протокола PROXY версии 2,
|
||||
содержащего большое количество TLV, могла возникать ошибка.
|
||||
|
||||
*) Исправление: при использовании SSI для обработки подзапросов,
|
||||
созданных другими модулями, в рабочем процессе мог произойти
|
||||
segmentation fault.
|
||||
Спасибо Ciel Zhao.
|
||||
|
||||
*) Изменение: теперь, если при преобразовании в адреса имени хоста,
|
||||
указанного в директиве listen, возвращается несколько адресов, nginx
|
||||
игнорирует дубликаты среди этих адресов.
|
||||
|
||||
*) Исправление: nginx мог нагружать процессор при небуферизированном
|
||||
проксировании, если использовались SSL-соединения с бэкендами.
|
||||
|
||||
|
||||
Изменения в nginx 1.23.2 19.10.2022
|
||||
|
||||
*) Безопасность: обработка специально созданного mp4-файла модулем
|
||||
ngx_http_mp4_module могла приводить к падению рабочего процесса,
|
||||
|
|
@ -7,10 +77,84 @@
|
|||
потенциально могла иметь другие последствия (CVE-2022-41741,
|
||||
CVE-2022-41742).
|
||||
|
||||
*) Добавление: переменные "$proxy_protocol_tlv_...".
|
||||
|
||||
Изменения в nginx 1.22.0 24.05.2022
|
||||
*) Добавление: ключи шифрования TLS session tickets теперь автоматически
|
||||
меняются при использовании разделяемой памяти в ssl_session_cache.
|
||||
|
||||
*) Стабильная ветка 1.22.x.
|
||||
*) Изменение: уровень логгирования ошибок SSL "bad record type" понижен
|
||||
с уровня crit до info.
|
||||
Спасибо Murilo Andrade.
|
||||
|
||||
*) Изменение: теперь при использовании разделяемой памяти в
|
||||
ssl_session_cache сообщения "could not allocate new session"
|
||||
логгируются на уровне warn вместо alert и не чаще одного раза в
|
||||
секунду.
|
||||
|
||||
*) Исправление: nginx/Windows не собирался с OpenSSL 3.0.x.
|
||||
|
||||
*) Исправление: в логгировании ошибок протокола PROXY.
|
||||
Спасибо Сергею Брестеру.
|
||||
|
||||
*) Изменение: при использовании TLSv1.3 с OpenSSL разделяемая память из
|
||||
ssl_session_cache расходовалась в том числе на сессии, использующие
|
||||
TLS session tickets.
|
||||
|
||||
*) Изменение: таймаут, заданный с помощью директивы ssl_session_timeout,
|
||||
не работал при использовании TLSv1.3 с OpenSSL или BoringSSL.
|
||||
|
||||
|
||||
Изменения в nginx 1.23.1 19.07.2022
|
||||
|
||||
*) Добавление: оптимизация использования памяти в конфигурациях с
|
||||
SSL-проксированием.
|
||||
|
||||
*) Добавление: теперь с помощью параметра "ipv4=off" директивы
|
||||
"resolver" можно запретить поиск IPv4-адресов при преобразовании имён
|
||||
в адреса.
|
||||
|
||||
*) Изменение: уровень логгирования ошибок SSL "bad key share", "bad
|
||||
extension", "bad cipher" и "bad ecpoint" понижен с уровня crit до
|
||||
info.
|
||||
|
||||
*) Исправление: при возврате диапазонов nginx не удалял строку заголовка
|
||||
"Content-Range", если она присутствовала в исходном ответе бэкенда.
|
||||
|
||||
*) Исправление: проксированный ответ мог быть отправлен не полностью при
|
||||
переконфигурации на Linux; ошибка появилась в 1.17.5.
|
||||
|
||||
|
||||
Изменения в nginx 1.23.0 21.06.2022
|
||||
|
||||
*) Изменение во внутреннем API: теперь строки заголовков представлены
|
||||
связными списками.
|
||||
|
||||
*) Изменение: теперь nginx объединяет произвольные строки заголовков с
|
||||
одинаковыми именами при отправке на FastCGI-, SCGI- и uwsgi-бэкенды,
|
||||
в методе $r->header_in() модуля ngx_http_perl_module, и при доступе
|
||||
через переменные "$http_...", "$sent_http_...", "$sent_trailer_...",
|
||||
"$upstream_http_..." и "$upstream_trailer_...".
|
||||
|
||||
*) Исправление: если в заголовке ответа бэкенда было несколько строк
|
||||
"Vary", при кэшировании nginx учитывал только последнюю из них.
|
||||
|
||||
*) Исправление: если в заголовке ответа бэкенда было несколько строк
|
||||
"WWW-Authenticate" и использовался перехват ошибок с кодом 401 от
|
||||
бэкенда или директива auth_request, nginx пересылал клиенту только
|
||||
первую из этих строк.
|
||||
|
||||
*) Изменение: уровень логгирования ошибок SSL "application data after
|
||||
close notify" понижен с уровня crit до info.
|
||||
|
||||
*) Исправление: соединения могли зависать, если nginx был собран на
|
||||
Linux 2.6.17 и новее, а использовался на системах без поддержки
|
||||
EPOLLRDHUP, в частности, на системах с эмуляцией epoll; ошибка
|
||||
появилась в 1.17.5.
|
||||
Спасибо Marcus Ball.
|
||||
|
||||
*) Исправление: nginx не кэшировал ответ, если строка заголовка ответа
|
||||
"Expires" запрещала кэширование, а последующая строка заголовка
|
||||
"Cache-Control" разрешала кэширование.
|
||||
|
||||
|
||||
Изменения в nginx 1.21.6 25.01.2022
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ else
|
|||
. auto/cc/acc
|
||||
;;
|
||||
|
||||
msvc*)
|
||||
msvc)
|
||||
# MSVC++ 6.0 SP2, MSVC++ Toolkit 2003
|
||||
|
||||
. auto/cc/msvc
|
||||
|
|
|
|||
19
auto/cc/msvc
19
auto/cc/msvc
|
|
@ -11,8 +11,8 @@
|
|||
# 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/'`
|
||||
NGX_MSVC_VER=`$NGX_WINE $CC 2>&1 | grep 'C/C++.* [0-9][0-9]*\.[0-9]' 2>&1 \
|
||||
| sed -e 's/^.* \([0-9][0-9]*\.[0-9].*\)/\1/'`
|
||||
|
||||
echo " + cl version: $NGX_MSVC_VER"
|
||||
|
||||
|
|
@ -22,6 +22,21 @@ have=NGX_COMPILER value="\"cl $NGX_MSVC_VER\"" . auto/define
|
|||
ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'`
|
||||
|
||||
|
||||
# detect x64 builds
|
||||
|
||||
case "$NGX_MSVC_VER" in
|
||||
|
||||
*x64)
|
||||
NGX_MACHINE=amd64
|
||||
;;
|
||||
|
||||
*)
|
||||
NGX_MACHINE=i386
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
|
||||
# optimizations
|
||||
|
||||
# maximize speed, equivalent to -Og -Oi -Ot -Oy -Ob2 -Gs -GF -Gy
|
||||
|
|
|
|||
|
|
@ -7,11 +7,24 @@ case "$CC" in
|
|||
|
||||
cl)
|
||||
|
||||
case "$NGX_MACHINE" in
|
||||
|
||||
amd64)
|
||||
OPENSSL_TARGET=VC-WIN64A
|
||||
;;
|
||||
|
||||
*)
|
||||
OPENSSL_TARGET=VC-WIN32
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
|
||||
$OPENSSL/openssl/include/openssl/ssl.h: $NGX_MAKEFILE
|
||||
\$(MAKE) -f auto/lib/openssl/makefile.msvc \
|
||||
OPENSSL="$OPENSSL" OPENSSL_OPT="$OPENSSL_OPT"
|
||||
OPENSSL="$OPENSSL" OPENSSL_OPT="$OPENSSL_OPT" \
|
||||
OPENSSL_TARGET="$OPENSSL_TARGET"
|
||||
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
all:
|
||||
cd $(OPENSSL)
|
||||
|
||||
perl Configure VC-WIN32 no-shared \
|
||||
perl Configure $(OPENSSL_TARGET) no-shared no-threads \
|
||||
--prefix="%cd%/openssl" \
|
||||
--openssldir="%cd%/openssl/ssl" \
|
||||
$(OPENSSL_OPT)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ case "$NGX_MACHINE" in
|
|||
NGX_MACH_CACHE_LINE=64
|
||||
;;
|
||||
|
||||
aarch64 )
|
||||
aarch64 | arm64)
|
||||
have=NGX_ALIGNMENT value=16 . auto/define
|
||||
NGX_MACH_CACHE_LINE=64
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -232,4 +232,19 @@ ngx_feature_test="struct crypt_data cd;
|
|||
ngx_include="sys/vfs.h"; . auto/include
|
||||
|
||||
|
||||
# UDP segmentation offloading
|
||||
|
||||
ngx_feature="UDP_SEGMENT"
|
||||
ngx_feature_name="NGX_HAVE_UDP_SEGMENT"
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="#include <sys/socket.h>
|
||||
#include <netinet/udp.h>"
|
||||
ngx_feature_path=
|
||||
ngx_feature_libs=
|
||||
ngx_feature_test="socklen_t optlen = sizeof(int);
|
||||
int val;
|
||||
getsockopt(0, SOL_UDP, UDP_SEGMENT, &val, &optlen)"
|
||||
. auto/feature
|
||||
|
||||
|
||||
CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ EVENT_DEPS="src/event/ngx_event.h \
|
|||
src/event/ngx_event_timer.h \
|
||||
src/event/ngx_event_posted.h \
|
||||
src/event/ngx_event_connect.h \
|
||||
src/event/ngx_event_pipe.h"
|
||||
src/event/ngx_event_pipe.h \
|
||||
src/event/ngx_event_udp.h"
|
||||
|
||||
EVENT_SRCS="src/event/ngx_event.c \
|
||||
src/event/ngx_event_timer.c \
|
||||
|
|
|
|||
1
configure
vendored
1
configure
vendored
|
|
@ -44,6 +44,7 @@ if test -z "$NGX_PLATFORM"; then
|
|||
else
|
||||
echo "building for $NGX_PLATFORM"
|
||||
NGX_SYSTEM=$NGX_PLATFORM
|
||||
NGX_MACHINE=i386
|
||||
fi
|
||||
|
||||
. auto/cc/conf
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,8 +9,8 @@
|
|||
#define _NGINX_H_INCLUDED_
|
||||
|
||||
|
||||
#define nginx_version 1022001
|
||||
#define NGINX_VERSION "1.22.1"
|
||||
#define nginx_version 1024000
|
||||
#define NGINX_VERSION "1.24.0"
|
||||
#define NGINX_VER "nginx/" NGINX_VERSION
|
||||
|
||||
#ifdef NGX_BUILD
|
||||
|
|
|
|||
|
|
@ -544,8 +544,8 @@ ngx_conf_read_token(ngx_conf_t *cf)
|
|||
}
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"unexpected end of file, "
|
||||
"expecting \";\" or \"}\"");
|
||||
"unexpected end of file, "
|
||||
"expecting \";\" or \"}\"");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -660,7 +660,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
/*
|
||||
* on OpenVZ after suspend/resume EADDRINUSE
|
||||
* may be returned by listen() instead of bind(), see
|
||||
* https://bugzilla.openvz.org/show_bug.cgi?id=2470
|
||||
* https://bugs.openvz.org/browse/OVZ-5587
|
||||
*/
|
||||
|
||||
if (err != NGX_EADDRINUSE || !ngx_test_config) {
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ struct ngx_connection_s {
|
|||
unsigned timedout:1;
|
||||
unsigned error:1;
|
||||
unsigned destroyed:1;
|
||||
unsigned pipeline:1;
|
||||
|
||||
unsigned idle:1;
|
||||
unsigned reusable:1;
|
||||
|
|
@ -184,6 +185,7 @@ struct ngx_connection_s {
|
|||
unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */
|
||||
|
||||
unsigned need_last_buf:1;
|
||||
unsigned need_flush_buf:1;
|
||||
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT)
|
||||
unsigned busy_count:2;
|
||||
|
|
|
|||
|
|
@ -89,12 +89,15 @@ typedef struct {
|
|||
} ngx_hash_keys_arrays_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct ngx_table_elt_s ngx_table_elt_t;
|
||||
|
||||
struct ngx_table_elt_s {
|
||||
ngx_uint_t hash;
|
||||
ngx_str_t key;
|
||||
ngx_str_t value;
|
||||
u_char *lowcase_key;
|
||||
} ngx_table_elt_t;
|
||||
ngx_table_elt_t *next;
|
||||
};
|
||||
|
||||
|
||||
void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,15 @@
|
|||
#define NGX_PROXY_PROTOCOL_AF_INET6 2
|
||||
|
||||
|
||||
#define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1])
|
||||
#define ngx_proxy_protocol_parse_uint16(p) \
|
||||
( ((uint16_t) (p)[0] << 8) \
|
||||
+ ( (p)[1]) )
|
||||
|
||||
#define ngx_proxy_protocol_parse_uint32(p) \
|
||||
( ((uint32_t) (p)[0] << 24) \
|
||||
+ ( (p)[1] << 16) \
|
||||
+ ( (p)[2] << 8) \
|
||||
+ ( (p)[3]) )
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -40,12 +48,52 @@ typedef struct {
|
|||
} ngx_proxy_protocol_inet6_addrs_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char type;
|
||||
u_char len[2];
|
||||
} ngx_proxy_protocol_tlv_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char client;
|
||||
u_char verify[4];
|
||||
} ngx_proxy_protocol_tlv_ssl_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
ngx_uint_t type;
|
||||
} ngx_proxy_protocol_tlv_entry_t;
|
||||
|
||||
|
||||
static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
|
||||
u_char *last, ngx_str_t *addr);
|
||||
static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
|
||||
in_port_t *port, u_char sep);
|
||||
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
|
||||
u_char *last);
|
||||
static ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c,
|
||||
ngx_str_t *tlvs, ngx_uint_t type, ngx_str_t *value);
|
||||
|
||||
|
||||
static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_entries[] = {
|
||||
{ ngx_string("alpn"), 0x01 },
|
||||
{ ngx_string("authority"), 0x02 },
|
||||
{ ngx_string("unique_id"), 0x05 },
|
||||
{ ngx_string("ssl"), 0x20 },
|
||||
{ ngx_string("netns"), 0x30 },
|
||||
{ ngx_null_string, 0x00 }
|
||||
};
|
||||
|
||||
|
||||
static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_ssl_entries[] = {
|
||||
{ ngx_string("version"), 0x21 },
|
||||
{ ngx_string("cn"), 0x22 },
|
||||
{ ngx_string("cipher"), 0x23 },
|
||||
{ ngx_string("sig_alg"), 0x24 },
|
||||
{ ngx_string("key_alg"), 0x25 },
|
||||
{ ngx_null_string, 0x00 }
|
||||
};
|
||||
|
||||
|
||||
u_char *
|
||||
|
|
@ -61,7 +109,7 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||
len = last - buf;
|
||||
|
||||
if (len >= sizeof(ngx_proxy_protocol_header_t)
|
||||
&& memcmp(p, signature, sizeof(signature) - 1) == 0)
|
||||
&& ngx_memcmp(p, signature, sizeof(signature) - 1) == 0)
|
||||
{
|
||||
return ngx_proxy_protocol_v2_read(c, buf, last);
|
||||
}
|
||||
|
|
@ -139,8 +187,14 @@ skip:
|
|||
|
||||
invalid:
|
||||
|
||||
for (p = buf; p < last; p++) {
|
||||
if (*p == CR || *p == LF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"broken header: \"%*s\"", (size_t) (last - buf), buf);
|
||||
"broken header: \"%*s\"", (size_t) (p - buf), buf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -227,7 +281,9 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||
{
|
||||
ngx_uint_t port, lport;
|
||||
|
||||
if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) {
|
||||
if (last - buf < NGX_PROXY_PROTOCOL_V1_MAX_HEADER) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"too small buffer for PROXY protocol");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -340,11 +396,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||
|
||||
src_sockaddr.sockaddr_in.sin_family = AF_INET;
|
||||
src_sockaddr.sockaddr_in.sin_port = 0;
|
||||
memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
|
||||
ngx_memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
|
||||
|
||||
dst_sockaddr.sockaddr_in.sin_family = AF_INET;
|
||||
dst_sockaddr.sockaddr_in.sin_port = 0;
|
||||
memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
|
||||
ngx_memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
|
||||
|
||||
pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
|
||||
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
|
||||
|
|
@ -367,11 +423,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||
|
||||
src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
|
||||
src_sockaddr.sockaddr_in6.sin6_port = 0;
|
||||
memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
|
||||
ngx_memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
|
||||
|
||||
dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
|
||||
dst_sockaddr.sockaddr_in6.sin6_port = 0;
|
||||
memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
|
||||
ngx_memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
|
||||
|
||||
pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
|
||||
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
|
||||
|
|
@ -412,11 +468,147 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
|
||||
|
||||
if (buf < end) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||
"PROXY protocol v2 %z bytes of tlv ignored", end - buf);
|
||||
pp->tlvs.data = ngx_pnalloc(c->pool, end - buf);
|
||||
if (pp->tlvs.data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ngx_memcpy(pp->tlvs.data, buf, end - buf);
|
||||
pp->tlvs.len = end - buf;
|
||||
}
|
||||
|
||||
c->proxy_protocol = pp;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
|
||||
ngx_str_t *value)
|
||||
{
|
||||
u_char *p;
|
||||
size_t n;
|
||||
uint32_t verify;
|
||||
ngx_str_t ssl, *tlvs;
|
||||
ngx_int_t rc, type;
|
||||
ngx_proxy_protocol_tlv_ssl_t *tlv_ssl;
|
||||
ngx_proxy_protocol_tlv_entry_t *te;
|
||||
|
||||
if (c->proxy_protocol == NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||
"PROXY protocol v2 get tlv \"%V\"", name);
|
||||
|
||||
te = ngx_proxy_protocol_tlv_entries;
|
||||
tlvs = &c->proxy_protocol->tlvs;
|
||||
|
||||
p = name->data;
|
||||
n = name->len;
|
||||
|
||||
if (n >= 4 && p[0] == 's' && p[1] == 's' && p[2] == 'l' && p[3] == '_') {
|
||||
|
||||
rc = ngx_proxy_protocol_lookup_tlv(c, tlvs, 0x20, &ssl);
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
p += 4;
|
||||
n -= 4;
|
||||
|
||||
if (n == 6 && ngx_strncmp(p, "verify", 6) == 0) {
|
||||
|
||||
tlv_ssl = (ngx_proxy_protocol_tlv_ssl_t *) ssl.data;
|
||||
verify = ngx_proxy_protocol_parse_uint32(tlv_ssl->verify);
|
||||
|
||||
value->data = ngx_pnalloc(c->pool, NGX_INT32_LEN);
|
||||
if (value->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
value->len = ngx_sprintf(value->data, "%uD", verify)
|
||||
- value->data;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t);
|
||||
ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t);
|
||||
|
||||
te = ngx_proxy_protocol_tlv_ssl_entries;
|
||||
tlvs = &ssl;
|
||||
}
|
||||
|
||||
if (n >= 2 && p[0] == '0' && p[1] == 'x') {
|
||||
|
||||
type = ngx_hextoi(p + 2, n - 2);
|
||||
if (type == NGX_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"invalid PROXY protocol TLV \"%V\"", name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return ngx_proxy_protocol_lookup_tlv(c, tlvs, type, value);
|
||||
}
|
||||
|
||||
for ( /* void */ ; te->type; te++) {
|
||||
if (te->name.len == n && ngx_strncmp(te->name.data, p, n) == 0) {
|
||||
return ngx_proxy_protocol_lookup_tlv(c, tlvs, te->type, value);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"unknown PROXY protocol TLV \"%V\"", name);
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs,
|
||||
ngx_uint_t type, ngx_str_t *value)
|
||||
{
|
||||
u_char *p;
|
||||
size_t n, len;
|
||||
ngx_proxy_protocol_tlv_t *tlv;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||
"PROXY protocol v2 lookup tlv:%02xi", type);
|
||||
|
||||
p = tlvs->data;
|
||||
n = tlvs->len;
|
||||
|
||||
while (n) {
|
||||
if (n < sizeof(ngx_proxy_protocol_tlv_t)) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
tlv = (ngx_proxy_protocol_tlv_t *) p;
|
||||
len = ngx_proxy_protocol_parse_uint16(tlv->len);
|
||||
|
||||
p += sizeof(ngx_proxy_protocol_tlv_t);
|
||||
n -= sizeof(ngx_proxy_protocol_tlv_t);
|
||||
|
||||
if (n < len) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (tlv->type == type) {
|
||||
value->data = p;
|
||||
value->len = len;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
p += len;
|
||||
n -= len;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
|
||||
#define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107
|
||||
#define NGX_PROXY_PROTOCOL_MAX_HEADER 4096
|
||||
|
||||
|
||||
struct ngx_proxy_protocol_s {
|
||||
|
|
@ -21,6 +22,7 @@ struct ngx_proxy_protocol_s {
|
|||
ngx_str_t dst_addr;
|
||||
in_port_t src_port;
|
||||
in_port_t dst_port;
|
||||
ngx_str_t tlvs;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -28,6 +30,8 @@ u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
|
|||
u_char *last);
|
||||
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
|
||||
u_char *last);
|
||||
ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
|
||||
ngx_str_t *value);
|
||||
|
||||
|
||||
#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
|||
cln->handler = ngx_resolver_cleanup;
|
||||
cln->data = r;
|
||||
|
||||
r->ipv4 = 1;
|
||||
|
||||
ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
|
||||
ngx_resolver_rbtree_insert_value);
|
||||
|
||||
|
|
@ -225,6 +227,23 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
|||
}
|
||||
|
||||
#if (NGX_HAVE_INET6)
|
||||
if (ngx_strncmp(names[i].data, "ipv4=", 5) == 0) {
|
||||
|
||||
if (ngx_strcmp(&names[i].data[5], "on") == 0) {
|
||||
r->ipv4 = 1;
|
||||
|
||||
} else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
|
||||
r->ipv4 = 0;
|
||||
|
||||
} else {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid parameter: %V", &names[i]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
|
||||
|
||||
if (ngx_strcmp(&names[i].data[5], "on") == 0) {
|
||||
|
|
@ -273,6 +292,14 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_INET6)
|
||||
if (r->ipv4 + r->ipv6 == 0) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"ipv4\" and \"ipv6\" cannot both be \"off\"");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (n && r->connections.nelts == 0) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no name servers defined");
|
||||
return NULL;
|
||||
|
|
@ -836,7 +863,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
|
|||
r->last_connection = 0;
|
||||
}
|
||||
|
||||
rn->naddrs = (u_short) -1;
|
||||
rn->naddrs = r->ipv4 ? (u_short) -1 : 0;
|
||||
rn->tcp = 0;
|
||||
#if (NGX_HAVE_INET6)
|
||||
rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
|
||||
|
|
@ -1263,7 +1290,7 @@ ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
|
|||
rec->log.action = "resolving";
|
||||
}
|
||||
|
||||
if (rn->naddrs == (u_short) -1) {
|
||||
if (rn->query && rn->naddrs == (u_short) -1) {
|
||||
rc = rn->tcp ? ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen)
|
||||
: ngx_resolver_send_udp_query(r, rec, rn->query, rn->qlen);
|
||||
|
||||
|
|
@ -1389,6 +1416,7 @@ ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec,
|
|||
|
||||
rec->tcp->data = rec;
|
||||
rec->tcp->write->handler = ngx_resolver_tcp_write;
|
||||
rec->tcp->write->cancelable = 1;
|
||||
rec->tcp->read->handler = ngx_resolver_tcp_read;
|
||||
rec->tcp->read->resolver = 1;
|
||||
|
||||
|
|
@ -1764,10 +1792,13 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||
q = ngx_queue_next(q))
|
||||
{
|
||||
rn = ngx_queue_data(q, ngx_resolver_node_t, queue);
|
||||
qident = (rn->query[0] << 8) + rn->query[1];
|
||||
|
||||
if (qident == ident) {
|
||||
goto dns_error_name;
|
||||
if (rn->query) {
|
||||
qident = (rn->query[0] << 8) + rn->query[1];
|
||||
|
||||
if (qident == ident) {
|
||||
goto dns_error_name;
|
||||
}
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_INET6)
|
||||
|
|
@ -3644,7 +3675,7 @@ ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
|
|||
len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
|
||||
|
||||
#if (NGX_HAVE_INET6)
|
||||
p = ngx_resolver_alloc(r, r->ipv6 ? len * 2 : len);
|
||||
p = ngx_resolver_alloc(r, len * (r->ipv4 + r->ipv6));
|
||||
#else
|
||||
p = ngx_resolver_alloc(r, len);
|
||||
#endif
|
||||
|
|
@ -3657,19 +3688,21 @@ ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
|
|||
|
||||
#if (NGX_HAVE_INET6)
|
||||
if (r->ipv6) {
|
||||
rn->query6 = p + len;
|
||||
rn->query6 = r->ipv4 ? (p + len) : p;
|
||||
}
|
||||
#endif
|
||||
|
||||
query = (ngx_resolver_hdr_t *) p;
|
||||
|
||||
ident = ngx_random();
|
||||
if (r->ipv4) {
|
||||
ident = ngx_random();
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
|
||||
"resolve: \"%V\" A %i", name, ident & 0xffff);
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
|
||||
"resolve: \"%V\" A %i", name, ident & 0xffff);
|
||||
|
||||
query->ident_hi = (u_char) ((ident >> 8) & 0xff);
|
||||
query->ident_lo = (u_char) (ident & 0xff);
|
||||
query->ident_hi = (u_char) ((ident >> 8) & 0xff);
|
||||
query->ident_lo = (u_char) (ident & 0xff);
|
||||
}
|
||||
|
||||
/* recursion query */
|
||||
query->flags_hi = 1; query->flags_lo = 0;
|
||||
|
|
@ -3730,7 +3763,9 @@ ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
|
|||
|
||||
p = rn->query6;
|
||||
|
||||
ngx_memcpy(p, rn->query, rn->qlen);
|
||||
if (r->ipv4) {
|
||||
ngx_memcpy(p, rn->query, rn->qlen);
|
||||
}
|
||||
|
||||
query = (ngx_resolver_hdr_t *) p;
|
||||
|
||||
|
|
|
|||
|
|
@ -175,8 +175,10 @@ struct ngx_resolver_s {
|
|||
ngx_queue_t srv_expire_queue;
|
||||
ngx_queue_t addr_expire_queue;
|
||||
|
||||
unsigned ipv4:1;
|
||||
|
||||
#if (NGX_HAVE_INET6)
|
||||
ngx_uint_t ipv6; /* unsigned ipv6:1; */
|
||||
unsigned ipv6:1;
|
||||
ngx_rbtree_t addr6_rbtree;
|
||||
ngx_rbtree_node_t addr6_sentinel;
|
||||
ngx_queue_t addr6_resend_queue;
|
||||
|
|
|
|||
|
|
@ -1364,7 +1364,12 @@ ngx_utf8_decode(u_char **p, size_t n)
|
|||
|
||||
u = **p;
|
||||
|
||||
if (u >= 0xf0) {
|
||||
if (u >= 0xf8) {
|
||||
|
||||
(*p)++;
|
||||
return 0xffffffff;
|
||||
|
||||
} else if (u >= 0xf0) {
|
||||
|
||||
u &= 0x07;
|
||||
valid = 0xffff;
|
||||
|
|
|
|||
|
|
@ -140,12 +140,12 @@ ngx_copy(u_char *dst, u_char *src, size_t len)
|
|||
#endif
|
||||
|
||||
|
||||
#define ngx_memmove(dst, src, n) (void) memmove(dst, src, n)
|
||||
#define ngx_movemem(dst, src, n) (((u_char *) memmove(dst, src, n)) + (n))
|
||||
#define ngx_memmove(dst, src, n) (void) memmove(dst, src, n)
|
||||
#define ngx_movemem(dst, src, n) (((u_char *) memmove(dst, src, n)) + (n))
|
||||
|
||||
|
||||
/* msvc and icc7 compile memcmp() to the inline loop */
|
||||
#define ngx_memcmp(s1, s2, n) memcmp((const char *) s1, (const char *) s2, n)
|
||||
#define ngx_memcmp(s1, s2, n) memcmp(s1, s2, n)
|
||||
|
||||
|
||||
u_char *ngx_cpystrn(u_char *dst, u_char *src, size_t n);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
static char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer);
|
||||
static ngx_int_t ngx_syslog_init_peer(ngx_syslog_peer_t *peer);
|
||||
static void ngx_syslog_cleanup(void *data);
|
||||
static u_char *ngx_syslog_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
||||
|
||||
|
||||
static char *facilities[] = {
|
||||
|
|
@ -66,6 +67,9 @@ ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
|
|||
ngx_str_set(&peer->tag, "nginx");
|
||||
}
|
||||
|
||||
peer->hostname = &cf->cycle->hostname;
|
||||
peer->logp = &cf->cycle->new_log;
|
||||
|
||||
peer->conn.fd = (ngx_socket_t) -1;
|
||||
|
||||
peer->conn.read = &ngx_syslog_dummy_event;
|
||||
|
|
@ -243,7 +247,7 @@ ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf)
|
|||
}
|
||||
|
||||
return ngx_sprintf(buf, "<%ui>%V %V %V: ", pri, &ngx_cached_syslog_time,
|
||||
&ngx_cycle->hostname, &peer->tag);
|
||||
peer->hostname, &peer->tag);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -286,15 +290,19 @@ ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len)
|
|||
{
|
||||
ssize_t n;
|
||||
|
||||
if (peer->log.handler == NULL) {
|
||||
peer->log = *peer->logp;
|
||||
peer->log.handler = ngx_syslog_log_error;
|
||||
peer->log.data = peer;
|
||||
peer->log.action = "logging to syslog";
|
||||
}
|
||||
|
||||
if (peer->conn.fd == (ngx_socket_t) -1) {
|
||||
if (ngx_syslog_init_peer(peer) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* log syslog socket events with valid log */
|
||||
peer->conn.log = ngx_cycle->log;
|
||||
|
||||
if (ngx_send) {
|
||||
n = ngx_send(&peer->conn, buf, len);
|
||||
|
||||
|
|
@ -306,7 +314,7 @@ ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len)
|
|||
if (n == NGX_ERROR) {
|
||||
|
||||
if (ngx_close_socket(peer->conn.fd) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, &peer->log, ngx_socket_errno,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
|
||||
|
|
@ -324,24 +332,25 @@ ngx_syslog_init_peer(ngx_syslog_peer_t *peer)
|
|||
|
||||
fd = ngx_socket(peer->server.sockaddr->sa_family, SOCK_DGRAM, 0);
|
||||
if (fd == (ngx_socket_t) -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, &peer->log, ngx_socket_errno,
|
||||
ngx_socket_n " failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_nonblocking(fd) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, &peer->log, ngx_socket_errno,
|
||||
ngx_nonblocking_n " failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (connect(fd, peer->server.sockaddr, peer->server.socklen) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, &peer->log, ngx_socket_errno,
|
||||
"connect() failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
peer->conn.fd = fd;
|
||||
peer->conn.log = &peer->log;
|
||||
|
||||
/* UDP sockets are always ready to write */
|
||||
peer->conn.write->ready = 1;
|
||||
|
|
@ -351,7 +360,7 @@ ngx_syslog_init_peer(ngx_syslog_peer_t *peer)
|
|||
failed:
|
||||
|
||||
if (ngx_close_socket(fd) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, &peer->log, ngx_socket_errno,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +381,30 @@ ngx_syslog_cleanup(void *data)
|
|||
}
|
||||
|
||||
if (ngx_close_socket(peer->conn.fd) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
|
||||
ngx_log_error(NGX_LOG_ALERT, &peer->log, ngx_socket_errno,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_syslog_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_syslog_peer_t *peer;
|
||||
|
||||
p = buf;
|
||||
|
||||
if (log->action) {
|
||||
p = ngx_snprintf(buf, len, " while %s", log->action);
|
||||
len -= p - buf;
|
||||
}
|
||||
|
||||
peer = log->data;
|
||||
|
||||
if (peer) {
|
||||
p = ngx_snprintf(p, len, ", server: %V", &peer->server.name);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,14 +9,20 @@
|
|||
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t facility;
|
||||
ngx_uint_t severity;
|
||||
ngx_str_t tag;
|
||||
ngx_uint_t facility;
|
||||
ngx_uint_t severity;
|
||||
ngx_str_t tag;
|
||||
|
||||
ngx_addr_t server;
|
||||
ngx_connection_t conn;
|
||||
unsigned busy:1;
|
||||
unsigned nohostname:1;
|
||||
ngx_str_t *hostname;
|
||||
|
||||
ngx_addr_t server;
|
||||
ngx_connection_t conn;
|
||||
|
||||
ngx_log_t log;
|
||||
ngx_log_t *logp;
|
||||
|
||||
unsigned busy:1;
|
||||
unsigned nohostname:1;
|
||||
} ngx_syslog_peer_t;
|
||||
|
||||
|
||||
|
|
|
|||
379
src/event/modules/ngx_iocp_module.c
Normal file
379
src/event/modules/ngx_iocp_module.c
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_iocp_module.h>
|
||||
|
||||
|
||||
static ngx_int_t ngx_iocp_init(ngx_cycle_t *cycle, ngx_msec_t timer);
|
||||
static ngx_thread_value_t __stdcall ngx_iocp_timer(void *data);
|
||||
static void ngx_iocp_done(ngx_cycle_t *cycle);
|
||||
static ngx_int_t ngx_iocp_add_event(ngx_event_t *ev, ngx_int_t event,
|
||||
ngx_uint_t key);
|
||||
static ngx_int_t ngx_iocp_del_connection(ngx_connection_t *c, ngx_uint_t flags);
|
||||
static ngx_int_t ngx_iocp_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
||||
ngx_uint_t flags);
|
||||
static void *ngx_iocp_create_conf(ngx_cycle_t *cycle);
|
||||
static char *ngx_iocp_init_conf(ngx_cycle_t *cycle, void *conf);
|
||||
|
||||
|
||||
static ngx_str_t iocp_name = ngx_string("iocp");
|
||||
|
||||
static ngx_command_t ngx_iocp_commands[] = {
|
||||
|
||||
{ ngx_string("iocp_threads"),
|
||||
NGX_EVENT_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot,
|
||||
0,
|
||||
offsetof(ngx_iocp_conf_t, threads),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("post_acceptex"),
|
||||
NGX_EVENT_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot,
|
||||
0,
|
||||
offsetof(ngx_iocp_conf_t, post_acceptex),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("acceptex_read"),
|
||||
NGX_EVENT_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
0,
|
||||
offsetof(ngx_iocp_conf_t, acceptex_read),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
static ngx_event_module_t ngx_iocp_module_ctx = {
|
||||
&iocp_name,
|
||||
ngx_iocp_create_conf, /* create configuration */
|
||||
ngx_iocp_init_conf, /* init configuration */
|
||||
|
||||
{
|
||||
ngx_iocp_add_event, /* add an event */
|
||||
NULL, /* delete an event */
|
||||
NULL, /* enable an event */
|
||||
NULL, /* disable an event */
|
||||
NULL, /* add an connection */
|
||||
ngx_iocp_del_connection, /* delete an connection */
|
||||
NULL, /* trigger a notify */
|
||||
ngx_iocp_process_events, /* process the events */
|
||||
ngx_iocp_init, /* init the events */
|
||||
ngx_iocp_done /* done the events */
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ngx_module_t ngx_iocp_module = {
|
||||
NGX_MODULE_V1,
|
||||
&ngx_iocp_module_ctx, /* module context */
|
||||
ngx_iocp_commands, /* module directives */
|
||||
NGX_EVENT_MODULE, /* module type */
|
||||
NULL, /* init master */
|
||||
NULL, /* init module */
|
||||
NULL, /* init process */
|
||||
NULL, /* init thread */
|
||||
NULL, /* exit thread */
|
||||
NULL, /* exit process */
|
||||
NULL, /* exit master */
|
||||
NGX_MODULE_V1_PADDING
|
||||
};
|
||||
|
||||
|
||||
ngx_os_io_t ngx_iocp_io = {
|
||||
ngx_overlapped_wsarecv,
|
||||
NULL,
|
||||
ngx_udp_overlapped_wsarecv,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ngx_overlapped_wsasend_chain,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
static HANDLE iocp;
|
||||
static ngx_tid_t timer_thread;
|
||||
static ngx_msec_t msec;
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_iocp_init(ngx_cycle_t *cycle, ngx_msec_t timer)
|
||||
{
|
||||
ngx_iocp_conf_t *cf;
|
||||
|
||||
cf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
|
||||
|
||||
if (iocp == NULL) {
|
||||
iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,
|
||||
cf->threads);
|
||||
}
|
||||
|
||||
if (iocp == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateIoCompletionPort() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_io = ngx_iocp_io;
|
||||
|
||||
ngx_event_actions = ngx_iocp_module_ctx.actions;
|
||||
|
||||
ngx_event_flags = NGX_USE_IOCP_EVENT;
|
||||
|
||||
if (timer == 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The waitable timer could not be used, because
|
||||
* GetQueuedCompletionStatus() does not set a thread to alertable state
|
||||
*/
|
||||
|
||||
if (timer_thread == NULL) {
|
||||
|
||||
msec = timer;
|
||||
|
||||
if (ngx_create_thread(&timer_thread, ngx_iocp_timer, &msec, cycle->log)
|
||||
!= 0)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_event_flags |= NGX_USE_TIMER_EVENT;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_thread_value_t __stdcall
|
||||
ngx_iocp_timer(void *data)
|
||||
{
|
||||
ngx_msec_t timer = *(ngx_msec_t *) data;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
|
||||
"THREAD %p %p", &msec, data);
|
||||
|
||||
for ( ;; ) {
|
||||
Sleep(timer);
|
||||
|
||||
ngx_time_update();
|
||||
#if 1
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__WATCOMC__) || defined(__GNUC__)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_iocp_done(ngx_cycle_t *cycle)
|
||||
{
|
||||
if (CloseHandle(iocp) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"iocp CloseHandle() failed");
|
||||
}
|
||||
|
||||
iocp = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_iocp_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t key)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = (ngx_connection_t *) ev->data;
|
||||
|
||||
c->read->active = 1;
|
||||
c->write->active = 1;
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
|
||||
"iocp add: fd:%d k:%ui ov:%p", c->fd, key, &ev->ovlp);
|
||||
|
||||
if (CreateIoCompletionPort((HANDLE) c->fd, iocp, key, 0) == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||
"CreateIoCompletionPort() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_iocp_del_connection(ngx_connection_t *c, ngx_uint_t flags)
|
||||
{
|
||||
#if 0
|
||||
if (flags & NGX_CLOSE_EVENT) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (CancelIo((HANDLE) c->fd) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "CancelIo() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_iocp_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
|
||||
{
|
||||
int rc;
|
||||
u_int key;
|
||||
u_long bytes;
|
||||
ngx_err_t err;
|
||||
ngx_msec_t delta;
|
||||
ngx_event_t *ev;
|
||||
ngx_event_ovlp_t *ovlp;
|
||||
|
||||
if (timer == NGX_TIMER_INFINITE) {
|
||||
timer = INFINITE;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "iocp timer: %M", timer);
|
||||
|
||||
rc = GetQueuedCompletionStatus(iocp, &bytes, (PULONG_PTR) &key,
|
||||
(LPOVERLAPPED *) &ovlp, (u_long) timer);
|
||||
|
||||
if (rc == 0) {
|
||||
err = ngx_errno;
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
|
||||
delta = ngx_current_msec;
|
||||
|
||||
if (flags & NGX_UPDATE_TIME) {
|
||||
ngx_time_update();
|
||||
}
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
||||
"iocp: %d b:%d k:%d ov:%p", rc, bytes, key, ovlp);
|
||||
|
||||
if (timer != INFINITE) {
|
||||
delta = ngx_current_msec - delta;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
||||
"iocp timer: %M, delta: %M", timer, delta);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (ovlp == NULL) {
|
||||
if (err != WAIT_TIMEOUT) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
|
||||
"GetQueuedCompletionStatus() failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ovlp->error = err;
|
||||
}
|
||||
|
||||
if (ovlp == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"GetQueuedCompletionStatus() returned no operation");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ev = ovlp->event;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, err, "iocp event:%p", ev);
|
||||
|
||||
|
||||
if (err == ERROR_NETNAME_DELETED /* the socket was closed */
|
||||
|| err == ERROR_OPERATION_ABORTED /* the operation was canceled */)
|
||||
{
|
||||
|
||||
/*
|
||||
* the WSA_OPERATION_ABORTED completion notification
|
||||
* for a file descriptor that was closed
|
||||
*/
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, err,
|
||||
"iocp: aborted event %p", ev);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
|
||||
"GetQueuedCompletionStatus() returned operation error");
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
|
||||
case NGX_IOCP_ACCEPT:
|
||||
if (bytes) {
|
||||
ev->ready = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case NGX_IOCP_IO:
|
||||
ev->complete = 1;
|
||||
ev->ready = 1;
|
||||
break;
|
||||
|
||||
case NGX_IOCP_CONNECT:
|
||||
ev->ready = 1;
|
||||
}
|
||||
|
||||
ev->available = bytes;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
||||
"iocp event handler: %p", ev->handler);
|
||||
|
||||
ev->handler(ev);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_iocp_create_conf(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_iocp_conf_t *cf;
|
||||
|
||||
cf = ngx_palloc(cycle->pool, sizeof(ngx_iocp_conf_t));
|
||||
if (cf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cf->threads = NGX_CONF_UNSET;
|
||||
cf->post_acceptex = NGX_CONF_UNSET;
|
||||
cf->acceptex_read = NGX_CONF_UNSET;
|
||||
|
||||
return cf;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_iocp_init_conf(ngx_cycle_t *cycle, void *conf)
|
||||
{
|
||||
ngx_iocp_conf_t *cf = conf;
|
||||
|
||||
ngx_conf_init_value(cf->threads, 0);
|
||||
ngx_conf_init_value(cf->post_acceptex, 10);
|
||||
ngx_conf_init_value(cf->acceptex_read, 1);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
22
src/event/modules/ngx_iocp_module.h
Normal file
22
src/event/modules/ngx_iocp_module.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_IOCP_MODULE_H_INCLUDED_
|
||||
#define _NGX_IOCP_MODULE_H_INCLUDED_
|
||||
|
||||
|
||||
typedef struct {
|
||||
int threads;
|
||||
int post_acceptex;
|
||||
int acceptex_read;
|
||||
} ngx_iocp_conf_t;
|
||||
|
||||
|
||||
extern ngx_module_t ngx_iocp_module;
|
||||
|
||||
|
||||
#endif /* _NGX_IOCP_MODULE_H_INCLUDED_ */
|
||||
|
|
@ -416,6 +416,7 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
|
|||
{
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
ngx_uint_t i;
|
||||
ngx_core_conf_t *ccf;
|
||||
ngx_listening_t *ls;
|
||||
#endif
|
||||
|
||||
|
|
@ -442,7 +443,9 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
|
|||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
|
||||
if (!ngx_test_config) {
|
||||
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
||||
|
||||
if (!ngx_test_config && ccf->master) {
|
||||
|
||||
ls = cycle->listening.elts;
|
||||
for (i = 0; i < cycle->listening.nelts; i++) {
|
||||
|
|
@ -810,7 +813,9 @@ ngx_event_process_init(ngx_cycle_t *cycle)
|
|||
rev->deferred_accept = ls[i].deferred_accept;
|
||||
#endif
|
||||
|
||||
if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
|
||||
if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)
|
||||
&& cycle->old_cycle)
|
||||
{
|
||||
if (ls[i].previous) {
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -494,12 +494,6 @@ extern ngx_module_t ngx_event_core_module;
|
|||
|
||||
|
||||
void ngx_event_accept(ngx_event_t *ev);
|
||||
#if !(NGX_WIN32)
|
||||
void ngx_event_recvmsg(ngx_event_t *ev);
|
||||
void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
||||
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
|
||||
#endif
|
||||
void ngx_delete_udp_connection(void *data);
|
||||
ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle);
|
||||
ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
|
||||
u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
||||
|
|
@ -529,6 +523,7 @@ ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat);
|
|||
|
||||
#include <ngx_event_timer.h>
|
||||
#include <ngx_event_posted.h>
|
||||
#include <ngx_event_udp.h>
|
||||
|
||||
#if (NGX_WIN32)
|
||||
#include <ngx_iocp_module.h>
|
||||
|
|
|
|||
229
src/event/ngx_event_acceptex.c
Normal file
229
src/event/ngx_event_acceptex.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
static void ngx_close_posted_connection(ngx_connection_t *c);
|
||||
|
||||
|
||||
void
|
||||
ngx_event_acceptex(ngx_event_t *rev)
|
||||
{
|
||||
ngx_listening_t *ls;
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = rev->data;
|
||||
ls = c->listening;
|
||||
|
||||
c->log->handler = ngx_accept_log_error;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "AcceptEx: %d", c->fd);
|
||||
|
||||
if (rev->ovlp.error) {
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, rev->ovlp.error,
|
||||
"AcceptEx() %V failed", &ls->addr_text);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */
|
||||
|
||||
if (setsockopt(c->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
|
||||
(char *) &ls->fd, sizeof(ngx_socket_t))
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
|
||||
"setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed for %V",
|
||||
&c->addr_text);
|
||||
/* TODO: close socket */
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_getacceptexsockaddrs(c->buffer->pos,
|
||||
ls->post_accept_buffer_size,
|
||||
ls->socklen + 16,
|
||||
ls->socklen + 16,
|
||||
&c->local_sockaddr, &c->local_socklen,
|
||||
&c->sockaddr, &c->socklen);
|
||||
|
||||
if (ls->post_accept_buffer_size) {
|
||||
c->buffer->last += rev->available;
|
||||
c->buffer->end = c->buffer->start + ls->post_accept_buffer_size;
|
||||
|
||||
} else {
|
||||
c->buffer = NULL;
|
||||
}
|
||||
|
||||
if (ls->addr_ntop) {
|
||||
c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len);
|
||||
if (c->addr_text.data == NULL) {
|
||||
/* TODO: close socket */
|
||||
return;
|
||||
}
|
||||
|
||||
c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen,
|
||||
c->addr_text.data,
|
||||
ls->addr_text_max_len, 0);
|
||||
if (c->addr_text.len == 0) {
|
||||
/* TODO: close socket */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_event_post_acceptex(ls, 1);
|
||||
|
||||
c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
|
||||
|
||||
c->start_time = ngx_current_msec;
|
||||
|
||||
ls->handler(c);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_event_post_acceptex(ngx_listening_t *ls, ngx_uint_t n)
|
||||
{
|
||||
u_long rcvd;
|
||||
ngx_err_t err;
|
||||
ngx_log_t *log;
|
||||
ngx_uint_t i;
|
||||
ngx_event_t *rev, *wev;
|
||||
ngx_socket_t s;
|
||||
ngx_connection_t *c;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
|
||||
/* TODO: look up reused sockets */
|
||||
|
||||
s = ngx_socket(ls->sockaddr->sa_family, ls->type, 0);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &ls->log, 0,
|
||||
ngx_socket_n " s:%d", s);
|
||||
|
||||
if (s == (ngx_socket_t) -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, &ls->log, ngx_socket_errno,
|
||||
ngx_socket_n " failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c = ngx_get_connection(s, &ls->log);
|
||||
|
||||
if (c == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->pool = ngx_create_pool(ls->pool_size, &ls->log);
|
||||
if (c->pool == NULL) {
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
log = ngx_palloc(c->pool, sizeof(ngx_log_t));
|
||||
if (log == NULL) {
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->buffer = ngx_create_temp_buf(c->pool, ls->post_accept_buffer_size
|
||||
+ 2 * (ls->socklen + 16));
|
||||
if (c->buffer == NULL) {
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->local_sockaddr = ngx_palloc(c->pool, ls->socklen);
|
||||
if (c->local_sockaddr == NULL) {
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->sockaddr = ngx_palloc(c->pool, ls->socklen);
|
||||
if (c->sockaddr == NULL) {
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*log = ls->log;
|
||||
c->log = log;
|
||||
|
||||
c->recv = ngx_recv;
|
||||
c->send = ngx_send;
|
||||
c->recv_chain = ngx_recv_chain;
|
||||
c->send_chain = ngx_send_chain;
|
||||
|
||||
c->listening = ls;
|
||||
|
||||
rev = c->read;
|
||||
wev = c->write;
|
||||
|
||||
rev->ovlp.event = rev;
|
||||
wev->ovlp.event = wev;
|
||||
rev->handler = ngx_event_acceptex;
|
||||
|
||||
rev->ready = 1;
|
||||
wev->ready = 1;
|
||||
|
||||
rev->log = c->log;
|
||||
wev->log = c->log;
|
||||
|
||||
if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) {
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_acceptex(ls->fd, s, c->buffer->pos, ls->post_accept_buffer_size,
|
||||
ls->socklen + 16, ls->socklen + 16,
|
||||
&rcvd, (LPOVERLAPPED) &rev->ovlp)
|
||||
== 0)
|
||||
{
|
||||
err = ngx_socket_errno;
|
||||
if (err != WSA_IO_PENDING) {
|
||||
ngx_log_error(NGX_LOG_ALERT, &ls->log, err,
|
||||
"AcceptEx() %V failed", &ls->addr_text);
|
||||
|
||||
ngx_close_posted_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_close_posted_connection(ngx_connection_t *c)
|
||||
{
|
||||
ngx_socket_t fd;
|
||||
|
||||
ngx_free_connection(c);
|
||||
|
||||
fd = c->fd;
|
||||
c->fd = (ngx_socket_t) -1;
|
||||
|
||||
if (ngx_close_socket(fd) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
|
||||
if (c->pool) {
|
||||
ngx_destroy_pool(c->pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u_char *
|
||||
ngx_acceptex_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
||||
{
|
||||
return ngx_snprintf(buf, len, " while posting AcceptEx() on %V", log->data);
|
||||
}
|
||||
|
|
@ -179,6 +179,8 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
|
|||
c->recv = ngx_udp_recv;
|
||||
c->send = ngx_send;
|
||||
c->send_chain = ngx_udp_send_chain;
|
||||
|
||||
c->need_flush_buf = 1;
|
||||
}
|
||||
|
||||
c->log_error = pc->log_error;
|
||||
|
|
|
|||
206
src/event/ngx_event_connectex.c
Normal file
206
src/event/ngx_event_connectex.c
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
#define NGX_MAX_PENDING_CONN 10
|
||||
|
||||
|
||||
static CRITICAL_SECTION connect_lock;
|
||||
static int nconnects;
|
||||
static ngx_connection_t pending_connects[NGX_MAX_PENDING_CONN];
|
||||
|
||||
static HANDLE pending_connect_event;
|
||||
|
||||
__declspec(thread) int nevents = 0;
|
||||
__declspec(thread) WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS + 1];
|
||||
__declspec(thread) ngx_connection_t *conn[WSA_MAXIMUM_WAIT_EVENTS + 1];
|
||||
|
||||
|
||||
|
||||
int ngx_iocp_wait_connect(ngx_connection_t *c)
|
||||
{
|
||||
for ( ;; ) {
|
||||
EnterCriticalSection(&connect_lock);
|
||||
|
||||
if (nconnects < NGX_MAX_PENDING_CONN) {
|
||||
pending_connects[--nconnects] = c;
|
||||
LeaveCriticalSection(&connect_lock);
|
||||
|
||||
if (SetEvent(pending_connect_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||
"SetEvent() failed");
|
||||
return NGX_ERROR;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&connect_lock);
|
||||
ngx_log_error(NGX_LOG_NOTICE, c->log, 0,
|
||||
"max number of pending connect()s is %d",
|
||||
NGX_MAX_PENDING_CONN);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
if (ngx_iocp_new_thread(1) == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
started = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
int ngx_iocp_new_thread(int main)
|
||||
{
|
||||
u_int id;
|
||||
|
||||
if (main) {
|
||||
pending_connect_event = CreateEvent(NULL, 0, 1, NULL);
|
||||
if (pending_connect_event == INVALID_HANDLE_VALUE) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||
"CreateThread() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (CreateThread(NULL, 0, ngx_iocp_wait_events, main, 0, &id)
|
||||
== INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||
"CreateThread() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
SetEvent(event) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||
"SetEvent() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
int ngx_iocp_new_connect()
|
||||
{
|
||||
EnterCriticalSection(&connect_lock);
|
||||
c = pending_connects[--nconnects];
|
||||
LeaveCriticalSection(&connect_lock);
|
||||
|
||||
conn[nevents] = c;
|
||||
|
||||
events[nevents] = WSACreateEvent();
|
||||
if (events[nevents] == INVALID_HANDLE_VALUE) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
|
||||
"WSACreateEvent() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (WSAEventSelect(c->fd, events[nevents], FD_CONNECT) == -1)
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
|
||||
"WSAEventSelect() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
nevents++;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void ngx_iocp_wait_events(int main)
|
||||
{
|
||||
WSANETWORKEVENTS ne;
|
||||
|
||||
nevents = 1;
|
||||
events[0] = pending_connect_event;
|
||||
conn[0] = NULL;
|
||||
|
||||
for ( ;; ) {
|
||||
offset = (nevents == WSA_MAXIMUM_WAIT_EVENTS + 1) ? 1 : 0;
|
||||
timeout = (nevents == 1 && !first) ? 60000 : INFINITE;
|
||||
|
||||
n = WSAWaitForMultipleEvents(nevents - offset, events[offset],
|
||||
0, timeout, 0);
|
||||
if (n == WAIT_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
|
||||
"WSAWaitForMultipleEvents() failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == WAIT_TIMEOUT) {
|
||||
if (nevents == 2 && !main) {
|
||||
ExitThread(0);
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, log, 0,
|
||||
"WSAWaitForMultipleEvents() "
|
||||
"returned unexpected WAIT_TIMEOUT");
|
||||
continue;
|
||||
}
|
||||
|
||||
n -= WSA_WAIT_EVENT_0;
|
||||
|
||||
if (events[n] == NULL) {
|
||||
|
||||
/* the pending_connect_event */
|
||||
|
||||
if (nevents == WSA_MAXIMUM_WAIT_EVENTS) {
|
||||
ngx_iocp_new_thread(0);
|
||||
} else {
|
||||
ngx_iocp_new_connect();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (WSAEnumNetworkEvents(c[n].fd, events[n], &ne) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
|
||||
"WSAEnumNetworkEvents() failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ne.lNetworkEvents & FD_CONNECT) {
|
||||
conn[n].write->ovlp.error = ne.iErrorCode[FD_CONNECT_BIT];
|
||||
|
||||
if (PostQueuedCompletionStatus(iocp, 0, NGX_IOCP_CONNECT,
|
||||
&conn[n].write->ovlp) == 0)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
|
||||
"PostQueuedCompletionStatus() failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n < nevents) {
|
||||
conn[n] = conn[nevents];
|
||||
events[n] = events[nevents];
|
||||
}
|
||||
|
||||
nevents--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ne.lNetworkEvents & FD_ACCEPT) {
|
||||
|
||||
/* CHECK ERROR ??? */
|
||||
|
||||
ngx_event_post_acceptex(conn[n].listening, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, c[n].log, 0,
|
||||
"WSAWaitForMultipleEvents() "
|
||||
"returned unexpected network event %ul",
|
||||
ne.lNetworkEvents);
|
||||
}
|
||||
}
|
||||
|
|
@ -71,10 +71,11 @@ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
|||
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
|
||||
static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
||||
static int ngx_ssl_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
||||
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
|
||||
HMAC_CTX *hctx, int enc);
|
||||
static void ngx_ssl_session_ticket_keys_cleanup(void *data);
|
||||
static ngx_int_t ngx_ssl_rotate_ticket_keys(SSL_CTX *ssl_ctx, ngx_log_t *log);
|
||||
static void ngx_ssl_ticket_keys_cleanup(void *data);
|
||||
#endif
|
||||
|
||||
#ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
|
||||
|
|
@ -131,7 +132,7 @@ ngx_module_t ngx_openssl_module = {
|
|||
int ngx_ssl_connection_index;
|
||||
int ngx_ssl_server_conf_index;
|
||||
int ngx_ssl_session_cache_index;
|
||||
int ngx_ssl_session_ticket_keys_index;
|
||||
int ngx_ssl_ticket_keys_index;
|
||||
int ngx_ssl_ocsp_index;
|
||||
int ngx_ssl_certificate_index;
|
||||
int ngx_ssl_next_certificate_index;
|
||||
|
|
@ -208,9 +209,9 @@ ngx_ssl_init(ngx_log_t *log)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (ngx_ssl_session_ticket_keys_index == -1) {
|
||||
ngx_ssl_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if (ngx_ssl_ticket_keys_index == -1) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
|
||||
"SSL_CTX_get_ex_new_index() failed");
|
||||
return NGX_ERROR;
|
||||
|
|
@ -1083,6 +1084,53 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TLS1_3_VERSION
|
||||
|
||||
if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP
|
||||
&& SSL_version(ssl_conn) == TLS1_3_VERSION)
|
||||
{
|
||||
time_t now, time, timeout, conf_timeout;
|
||||
SSL_SESSION *sess;
|
||||
|
||||
/*
|
||||
* OpenSSL with TLSv1.3 updates the session creation time on
|
||||
* session resumption and keeps the session timeout unmodified,
|
||||
* making it possible to maintain the session forever, bypassing
|
||||
* client certificate expiration and revocation. To make sure
|
||||
* session timeouts are actually used, we now update the session
|
||||
* creation time and reduce the session timeout accordingly.
|
||||
*
|
||||
* BoringSSL with TLSv1.3 ignores configured session timeouts
|
||||
* and uses a hardcoded timeout instead, 7 days. So we update
|
||||
* session timeout to the configured value as soon as a session
|
||||
* is created.
|
||||
*/
|
||||
|
||||
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
|
||||
sess = SSL_get0_session(ssl_conn);
|
||||
|
||||
if (!c->ssl->session_timeout_set && sess) {
|
||||
c->ssl->session_timeout_set = 1;
|
||||
|
||||
now = ngx_time();
|
||||
time = SSL_SESSION_get_time(sess);
|
||||
timeout = SSL_SESSION_get_timeout(sess);
|
||||
conf_timeout = SSL_CTX_get_timeout(c->ssl->session_ctx);
|
||||
|
||||
timeout = ngx_min(timeout, conf_timeout);
|
||||
|
||||
if (now - time >= timeout) {
|
||||
SSL_SESSION_set1_id_context(sess, (unsigned char *) "", 0);
|
||||
|
||||
} else {
|
||||
SSL_SESSION_set_time(sess, now);
|
||||
SSL_SESSION_set_timeout(sess, timeout - (now - time));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
|
||||
|
|
@ -1426,9 +1474,9 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
|
|||
|
||||
SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
|
||||
|
||||
#if SSL_CTRL_SET_ECDH_AUTO
|
||||
#ifdef SSL_CTRL_SET_ECDH_AUTO
|
||||
/* not needed in OpenSSL 1.1.0+ */
|
||||
SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
|
||||
(void) SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
|
||||
#endif
|
||||
|
||||
if (ngx_strcmp(name->data, "auto") == 0) {
|
||||
|
|
@ -1769,7 +1817,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BIO_get_ktls_send
|
||||
#if (defined BIO_get_ktls_send && !NGX_WIN32)
|
||||
|
||||
if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
|
|
@ -1914,7 +1962,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
|
|||
c->read->ready = 1;
|
||||
c->write->ready = 1;
|
||||
|
||||
#ifdef BIO_get_ktls_send
|
||||
#if (defined BIO_get_ktls_send && !NGX_WIN32)
|
||||
|
||||
if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
|
|
@ -2156,6 +2204,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||
#endif
|
||||
|
||||
if (c->ssl->last == NGX_ERROR) {
|
||||
c->read->ready = 0;
|
||||
c->read->error = 1;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
|
@ -2222,6 +2271,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||
#if (NGX_HAVE_FIONREAD)
|
||||
|
||||
if (ngx_socket_nread(c->fd, &c->read->available) == -1) {
|
||||
c->read->ready = 0;
|
||||
c->read->error = 1;
|
||||
ngx_connection_error(c, ngx_socket_errno,
|
||||
ngx_socket_nread_n " failed");
|
||||
|
|
@ -2258,6 +2308,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||
return 0;
|
||||
|
||||
case NGX_ERROR:
|
||||
c->read->ready = 0;
|
||||
c->read->error = 1;
|
||||
|
||||
/* fall through */
|
||||
|
|
@ -2278,6 +2329,7 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
|
|||
size_t readbytes;
|
||||
|
||||
if (c->ssl->last == NGX_ERROR) {
|
||||
c->read->ready = 0;
|
||||
c->read->error = 1;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
|
@ -2377,6 +2429,7 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
|
|||
return 0;
|
||||
|
||||
case NGX_ERROR:
|
||||
c->read->ready = 0;
|
||||
c->read->error = 1;
|
||||
|
||||
/* fall through */
|
||||
|
|
@ -2943,7 +2996,7 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
|
|||
static ssize_t
|
||||
ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
|
||||
{
|
||||
#ifdef BIO_get_ktls_send
|
||||
#if (defined BIO_get_ktls_send && !NGX_WIN32)
|
||||
|
||||
int sslerr, flags;
|
||||
ssize_t n;
|
||||
|
|
@ -2972,7 +3025,7 @@ ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
|
|||
n = SSL_sendfile(c->ssl->connection, file->file->fd, file->file_pos,
|
||||
size, flags);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_sendfile: %d", n);
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_sendfile: %z", n);
|
||||
|
||||
if (n > 0) {
|
||||
|
||||
|
|
@ -3336,30 +3389,74 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|
|||
|
||||
} else if (sslerr == SSL_ERROR_SSL) {
|
||||
|
||||
n = ERR_GET_REASON(ERR_peek_error());
|
||||
n = ERR_GET_REASON(ERR_peek_last_error());
|
||||
|
||||
/* handshake failures */
|
||||
if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC /* 103 */
|
||||
#ifdef SSL_R_NO_SUITABLE_KEY_SHARE
|
||||
|| n == SSL_R_NO_SUITABLE_KEY_SHARE /* 101 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_ALERT
|
||||
|| n == SSL_R_BAD_ALERT /* 102 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_KEY_SHARE
|
||||
|| n == SSL_R_BAD_KEY_SHARE /* 108 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_EXTENSION
|
||||
|| n == SSL_R_BAD_EXTENSION /* 110 */
|
||||
#endif
|
||||
|| n == SSL_R_BAD_DIGEST_LENGTH /* 111 */
|
||||
#ifdef SSL_R_MISSING_SIGALGS_EXTENSION
|
||||
|| n == SSL_R_MISSING_SIGALGS_EXTENSION /* 112 */
|
||||
#endif
|
||||
|| n == SSL_R_BAD_PACKET_LENGTH /* 115 */
|
||||
#ifdef SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM
|
||||
|| n == SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM /* 118 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_KEY_UPDATE
|
||||
|| n == SSL_R_BAD_KEY_UPDATE /* 122 */
|
||||
#endif
|
||||
|| n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */
|
||||
|| n == SSL_R_CCS_RECEIVED_EARLY /* 133 */
|
||||
#ifdef SSL_R_DECODE_ERROR
|
||||
|| n == SSL_R_DECODE_ERROR /* 137 */
|
||||
#endif
|
||||
#ifdef SSL_R_DATA_BETWEEN_CCS_AND_FINISHED
|
||||
|| n == SSL_R_DATA_BETWEEN_CCS_AND_FINISHED /* 145 */
|
||||
#endif
|
||||
|| n == SSL_R_DATA_LENGTH_TOO_LONG /* 146 */
|
||||
|| n == SSL_R_DIGEST_CHECK_FAILED /* 149 */
|
||||
|| n == SSL_R_ENCRYPTED_LENGTH_TOO_LONG /* 150 */
|
||||
|| n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST /* 151 */
|
||||
|| n == SSL_R_EXCESSIVE_MESSAGE_SIZE /* 152 */
|
||||
#ifdef SSL_R_GOT_A_FIN_BEFORE_A_CCS
|
||||
|| n == SSL_R_GOT_A_FIN_BEFORE_A_CCS /* 154 */
|
||||
#endif
|
||||
|| n == SSL_R_HTTPS_PROXY_REQUEST /* 155 */
|
||||
|| n == SSL_R_HTTP_REQUEST /* 156 */
|
||||
|| n == SSL_R_LENGTH_MISMATCH /* 159 */
|
||||
#ifdef SSL_R_LENGTH_TOO_SHORT
|
||||
|| n == SSL_R_LENGTH_TOO_SHORT /* 160 */
|
||||
#endif
|
||||
#ifdef SSL_R_NO_RENEGOTIATION
|
||||
|| n == SSL_R_NO_RENEGOTIATION /* 182 */
|
||||
#endif
|
||||
#ifdef SSL_R_NO_CIPHERS_PASSED
|
||||
|| n == SSL_R_NO_CIPHERS_PASSED /* 182 */
|
||||
#endif
|
||||
|| n == SSL_R_NO_CIPHERS_SPECIFIED /* 183 */
|
||||
#ifdef SSL_R_BAD_CIPHER
|
||||
|| n == SSL_R_BAD_CIPHER /* 186 */
|
||||
#endif
|
||||
|| n == SSL_R_NO_COMPRESSION_SPECIFIED /* 187 */
|
||||
|| n == SSL_R_NO_SHARED_CIPHER /* 193 */
|
||||
#ifdef SSL_R_PACKET_LENGTH_TOO_LONG
|
||||
|| n == SSL_R_PACKET_LENGTH_TOO_LONG /* 198 */
|
||||
#endif
|
||||
|| n == SSL_R_RECORD_LENGTH_MISMATCH /* 213 */
|
||||
#ifdef SSL_R_TOO_MANY_WARNING_ALERTS
|
||||
|| n == SSL_R_TOO_MANY_WARNING_ALERTS /* 220 */
|
||||
#endif
|
||||
#ifdef SSL_R_CLIENTHELLO_TLSEXT
|
||||
|| n == SSL_R_CLIENTHELLO_TLSEXT /* 226 */
|
||||
#endif
|
||||
|
|
@ -3369,6 +3466,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|
|||
#ifdef SSL_R_CALLBACK_FAILED
|
||||
|| n == SSL_R_CALLBACK_FAILED /* 234 */
|
||||
#endif
|
||||
#ifdef SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
|
||||
|| n == SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG /* 234 */
|
||||
#endif
|
||||
#ifdef SSL_R_NO_APPLICATION_PROTOCOL
|
||||
|| n == SSL_R_NO_APPLICATION_PROTOCOL /* 235 */
|
||||
#endif
|
||||
|
|
@ -3378,13 +3478,44 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|
|||
|| n == SSL_R_UNKNOWN_PROTOCOL /* 252 */
|
||||
#ifdef SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS
|
||||
|| n == SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS /* 253 */
|
||||
#endif
|
||||
#ifdef SSL_R_INVALID_COMPRESSION_LIST
|
||||
|| n == SSL_R_INVALID_COMPRESSION_LIST /* 256 */
|
||||
#endif
|
||||
#ifdef SSL_R_MISSING_KEY_SHARE
|
||||
|| n == SSL_R_MISSING_KEY_SHARE /* 258 */
|
||||
#endif
|
||||
|| n == SSL_R_UNSUPPORTED_PROTOCOL /* 258 */
|
||||
#ifdef SSL_R_NO_SHARED_GROUP
|
||||
|| n == SSL_R_NO_SHARED_GROUP /* 266 */
|
||||
#endif
|
||||
|| n == SSL_R_WRONG_VERSION_NUMBER /* 267 */
|
||||
#ifdef SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA
|
||||
|| n == SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA /* 270 */
|
||||
#endif
|
||||
|| n == SSL_R_BAD_LENGTH /* 271 */
|
||||
|| n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */
|
||||
#ifdef SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY
|
||||
|| n == SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY /* 291 */
|
||||
#endif
|
||||
#ifdef SSL_R_APPLICATION_DATA_ON_SHUTDOWN
|
||||
|| n == SSL_R_APPLICATION_DATA_ON_SHUTDOWN /* 291 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_LEGACY_VERSION
|
||||
|| n == SSL_R_BAD_LEGACY_VERSION /* 292 */
|
||||
#endif
|
||||
#ifdef SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA
|
||||
|| n == SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA /* 293 */
|
||||
#endif
|
||||
#ifdef SSL_R_RECORD_TOO_SMALL
|
||||
|| n == SSL_R_RECORD_TOO_SMALL /* 298 */
|
||||
#endif
|
||||
#ifdef SSL_R_SSL3_SESSION_ID_TOO_LONG
|
||||
|| n == SSL_R_SSL3_SESSION_ID_TOO_LONG /* 300 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_ECPOINT
|
||||
|| n == SSL_R_BAD_ECPOINT /* 306 */
|
||||
#endif
|
||||
#ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
|
||||
|| n == SSL_R_RENEGOTIATE_EXT_TOO_LONG /* 335 */
|
||||
|| n == SSL_R_RENEGOTIATION_ENCODING_ERR /* 336 */
|
||||
|
|
@ -3399,11 +3530,23 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|
|||
#ifdef SSL_R_INAPPROPRIATE_FALLBACK
|
||||
|| n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */
|
||||
#endif
|
||||
#ifdef SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS
|
||||
|| n == SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS /* 376 */
|
||||
#endif
|
||||
#ifdef SSL_R_NO_SHARED_SIGATURE_ALGORITHMS
|
||||
|| n == SSL_R_NO_SHARED_SIGATURE_ALGORITHMS /* 376 */
|
||||
#endif
|
||||
#ifdef SSL_R_CERT_CB_ERROR
|
||||
|| n == SSL_R_CERT_CB_ERROR /* 377 */
|
||||
#endif
|
||||
#ifdef SSL_R_VERSION_TOO_LOW
|
||||
|| n == SSL_R_VERSION_TOO_LOW /* 396 */
|
||||
#endif
|
||||
#ifdef SSL_R_TOO_MANY_WARN_ALERTS
|
||||
|| n == SSL_R_TOO_MANY_WARN_ALERTS /* 409 */
|
||||
#endif
|
||||
#ifdef SSL_R_BAD_RECORD_TYPE
|
||||
|| n == SSL_R_BAD_RECORD_TYPE /* 443 */
|
||||
#endif
|
||||
|| n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
|
||||
#ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE
|
||||
|
|
@ -3749,6 +3892,12 @@ ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
|
|||
|
||||
ngx_queue_init(&cache->expire_queue);
|
||||
|
||||
cache->ticket_keys[0].expire = 0;
|
||||
cache->ticket_keys[1].expire = 0;
|
||||
cache->ticket_keys[2].expire = 0;
|
||||
|
||||
cache->fail_time = 0;
|
||||
|
||||
len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
|
||||
|
||||
shpool->log_ctx = ngx_slab_alloc(shpool, len);
|
||||
|
|
@ -3767,16 +3916,16 @@ ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)
|
|||
|
||||
/*
|
||||
* The length of the session id is 16 bytes for SSLv2 sessions and
|
||||
* between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes.
|
||||
* It seems that the typical length of the external ASN1 representation
|
||||
* of a session is 118 or 119 bytes for SSLv3/TSLv1.
|
||||
* between 1 and 32 bytes for SSLv3 and TLS, typically 32 bytes.
|
||||
* Typical length of the external ASN1 representation of a session
|
||||
* is about 150 bytes plus SNI server name.
|
||||
*
|
||||
* Thus on 32-bit platforms we allocate separately an rbtree node,
|
||||
* a session id, and an ASN1 representation, they take accordingly
|
||||
* 64, 32, and 128 bytes.
|
||||
* On 32-bit platforms we allocate an rbtree node, a session id, and
|
||||
* an ASN1 representation in a single allocation, it typically takes
|
||||
* 256 bytes.
|
||||
*
|
||||
* On 64-bit platforms we allocate separately an rbtree node + session_id,
|
||||
* and an ASN1 representation, they take accordingly 128 and 128 bytes.
|
||||
* and an ASN1 representation, they take accordingly 128 and 256 bytes.
|
||||
*
|
||||
* OpenSSL's i2d_SSL_SESSION() and d2i_SSL_SESSION are slow,
|
||||
* so they are outside the code locked by shared pool mutex
|
||||
|
|
@ -3786,7 +3935,8 @@ static int
|
|||
ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
||||
{
|
||||
int len;
|
||||
u_char *p, *id, *cached_sess, *session_id;
|
||||
u_char *p, *session_id;
|
||||
size_t n;
|
||||
uint32_t hash;
|
||||
SSL_CTX *ssl_ctx;
|
||||
unsigned int session_id_length;
|
||||
|
|
@ -3797,17 +3947,42 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
|||
ngx_ssl_session_cache_t *cache;
|
||||
u_char buf[NGX_SSL_MAX_SESSION_SIZE];
|
||||
|
||||
#ifdef TLS1_3_VERSION
|
||||
|
||||
/*
|
||||
* OpenSSL tries to save TLSv1.3 sessions into session cache
|
||||
* even when using tickets for stateless session resumption,
|
||||
* "because some applications just want to know about the creation
|
||||
* of a session"; do not cache such sessions
|
||||
*/
|
||||
|
||||
if (SSL_version(ssl_conn) == TLS1_3_VERSION
|
||||
&& (SSL_get_options(ssl_conn) & SSL_OP_NO_TICKET) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
len = i2d_SSL_SESSION(sess, NULL);
|
||||
|
||||
/* do not cache too big session */
|
||||
|
||||
if (len > (int) NGX_SSL_MAX_SESSION_SIZE) {
|
||||
if (len > NGX_SSL_MAX_SESSION_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
i2d_SSL_SESSION(sess, &p);
|
||||
|
||||
session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
|
||||
|
||||
/* do not cache sessions with too long session id */
|
||||
|
||||
if (session_id_length > 32) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
|
||||
ssl_ctx = c->ssl->session_ctx;
|
||||
|
|
@ -3821,23 +3996,13 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
|||
/* drop one or two expired sessions */
|
||||
ngx_ssl_expire_sessions(cache, shpool, 1);
|
||||
|
||||
cached_sess = ngx_slab_alloc_locked(shpool, len);
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
n = sizeof(ngx_ssl_sess_id_t);
|
||||
#else
|
||||
n = offsetof(ngx_ssl_sess_id_t, session) + len;
|
||||
#endif
|
||||
|
||||
if (cached_sess == NULL) {
|
||||
|
||||
/* drop the oldest non-expired session and try once more */
|
||||
|
||||
ngx_ssl_expire_sessions(cache, shpool, 0);
|
||||
|
||||
cached_sess = ngx_slab_alloc_locked(shpool, len);
|
||||
|
||||
if (cached_sess == NULL) {
|
||||
sess_id = NULL;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
|
||||
sess_id = ngx_slab_alloc_locked(shpool, n);
|
||||
|
||||
if (sess_id == NULL) {
|
||||
|
||||
|
|
@ -3845,41 +4010,34 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
|||
|
||||
ngx_ssl_expire_sessions(cache, shpool, 0);
|
||||
|
||||
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
|
||||
sess_id = ngx_slab_alloc_locked(shpool, n);
|
||||
|
||||
if (sess_id == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
|
||||
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
|
||||
id = sess_id->sess_id;
|
||||
sess_id->session = ngx_slab_alloc_locked(shpool, len);
|
||||
|
||||
#else
|
||||
|
||||
id = ngx_slab_alloc_locked(shpool, session_id_length);
|
||||
|
||||
if (id == NULL) {
|
||||
if (sess_id->session == NULL) {
|
||||
|
||||
/* drop the oldest non-expired session and try once more */
|
||||
|
||||
ngx_ssl_expire_sessions(cache, shpool, 0);
|
||||
|
||||
id = ngx_slab_alloc_locked(shpool, session_id_length);
|
||||
sess_id->session = ngx_slab_alloc_locked(shpool, len);
|
||||
|
||||
if (id == NULL) {
|
||||
if (sess_id->session == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ngx_memcpy(cached_sess, buf, len);
|
||||
|
||||
ngx_memcpy(id, session_id, session_id_length);
|
||||
ngx_memcpy(sess_id->session, buf, len);
|
||||
ngx_memcpy(sess_id->id, session_id, session_id_length);
|
||||
|
||||
hash = ngx_crc32_short(session_id, session_id_length);
|
||||
|
||||
|
|
@ -3889,9 +4047,7 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
|||
|
||||
sess_id->node.key = hash;
|
||||
sess_id->node.data = (u_char) session_id_length;
|
||||
sess_id->id = id;
|
||||
sess_id->len = len;
|
||||
sess_id->session = cached_sess;
|
||||
|
||||
sess_id->expire = ngx_time() + SSL_CTX_get_timeout(ssl_ctx);
|
||||
|
||||
|
|
@ -3905,18 +4061,17 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
|
|||
|
||||
failed:
|
||||
|
||||
if (cached_sess) {
|
||||
ngx_slab_free_locked(shpool, cached_sess);
|
||||
}
|
||||
|
||||
if (sess_id) {
|
||||
ngx_slab_free_locked(shpool, sess_id);
|
||||
}
|
||||
|
||||
ngx_shmtx_unlock(&shpool->mutex);
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"could not allocate new session%s", shpool->log_ctx);
|
||||
if (cache->fail_time != ngx_time()) {
|
||||
cache->fail_time = ngx_time();
|
||||
ngx_log_error(NGX_LOG_WARN, c->log, 0,
|
||||
"could not allocate new session%s", shpool->log_ctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4002,9 +4157,10 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
|
|||
|
||||
ngx_rbtree_delete(&cache->session_rbtree, node);
|
||||
|
||||
ngx_explicit_memzero(sess_id->session, sess_id->len);
|
||||
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
ngx_slab_free_locked(shpool, sess_id->session);
|
||||
#if (NGX_PTR_SIZE == 4)
|
||||
ngx_slab_free_locked(shpool, sess_id->id);
|
||||
#endif
|
||||
ngx_slab_free_locked(shpool, sess_id);
|
||||
|
||||
|
|
@ -4092,9 +4248,10 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
|
|||
|
||||
ngx_rbtree_delete(&cache->session_rbtree, node);
|
||||
|
||||
ngx_explicit_memzero(sess_id->session, sess_id->len);
|
||||
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
ngx_slab_free_locked(shpool, sess_id->session);
|
||||
#if (NGX_PTR_SIZE == 4)
|
||||
ngx_slab_free_locked(shpool, sess_id->id);
|
||||
#endif
|
||||
ngx_slab_free_locked(shpool, sess_id);
|
||||
|
||||
|
|
@ -4141,9 +4298,10 @@ ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache,
|
|||
|
||||
ngx_rbtree_delete(&cache->session_rbtree, &sess_id->node);
|
||||
|
||||
ngx_explicit_memzero(sess_id->session, sess_id->len);
|
||||
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
ngx_slab_free_locked(shpool, sess_id->session);
|
||||
#if (NGX_PTR_SIZE == 4)
|
||||
ngx_slab_free_locked(shpool, sess_id->id);
|
||||
#endif
|
||||
ngx_slab_free_locked(shpool, sess_id);
|
||||
}
|
||||
|
|
@ -4197,23 +4355,25 @@ ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
|||
ngx_int_t
|
||||
ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
|
||||
{
|
||||
u_char buf[80];
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_str_t *path;
|
||||
ngx_file_t file;
|
||||
ngx_uint_t i;
|
||||
ngx_array_t *keys;
|
||||
ngx_file_info_t fi;
|
||||
ngx_pool_cleanup_t *cln;
|
||||
ngx_ssl_session_ticket_key_t *key;
|
||||
u_char buf[80];
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_str_t *path;
|
||||
ngx_file_t file;
|
||||
ngx_uint_t i;
|
||||
ngx_array_t *keys;
|
||||
ngx_file_info_t fi;
|
||||
ngx_pool_cleanup_t *cln;
|
||||
ngx_ssl_ticket_key_t *key;
|
||||
|
||||
if (paths == NULL) {
|
||||
if (paths == NULL
|
||||
&& SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_session_cache_index) == NULL)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
keys = ngx_array_create(cf->pool, paths->nelts,
|
||||
sizeof(ngx_ssl_session_ticket_key_t));
|
||||
keys = ngx_array_create(cf->pool, paths ? paths->nelts : 3,
|
||||
sizeof(ngx_ssl_ticket_key_t));
|
||||
if (keys == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
|
@ -4223,9 +4383,41 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cln->handler = ngx_ssl_session_ticket_keys_cleanup;
|
||||
cln->handler = ngx_ssl_ticket_keys_cleanup;
|
||||
cln->data = keys;
|
||||
|
||||
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ticket_keys_index, keys) == 0) {
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
"SSL_CTX_set_ex_data() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, ngx_ssl_ticket_key_callback)
|
||||
== 0)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
||||
"nginx was built with Session Tickets support, however, "
|
||||
"now it is linked dynamically to an OpenSSL library "
|
||||
"which has no tlsext support, therefore Session Tickets "
|
||||
"are not available");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (paths == NULL) {
|
||||
|
||||
/* placeholder for keys in shared memory */
|
||||
|
||||
key = ngx_array_push_n(keys, 3);
|
||||
key[0].shared = 1;
|
||||
key[0].expire = 0;
|
||||
key[1].shared = 1;
|
||||
key[1].expire = 0;
|
||||
key[2].shared = 1;
|
||||
key[2].expire = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
path = paths->elts;
|
||||
for (i = 0; i < paths->nelts; i++) {
|
||||
|
||||
|
|
@ -4280,6 +4472,9 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
key->shared = 0;
|
||||
key->expire = 1;
|
||||
|
||||
if (size == 48) {
|
||||
key->size = 48;
|
||||
ngx_memcpy(key->name, buf, 16);
|
||||
|
|
@ -4301,25 +4496,6 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
|
|||
ngx_explicit_memzero(&buf, 80);
|
||||
}
|
||||
|
||||
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
|
||||
== 0)
|
||||
{
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
"SSL_CTX_set_ex_data() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
|
||||
ngx_ssl_session_ticket_key_callback)
|
||||
== 0)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
||||
"nginx was built with Session Tickets support, however, "
|
||||
"now it is linked dynamically to an OpenSSL library "
|
||||
"which has no tlsext support, therefore Session Tickets "
|
||||
"are not available");
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
failed:
|
||||
|
|
@ -4336,29 +4512,33 @@ failed:
|
|||
|
||||
|
||||
static int
|
||||
ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
||||
ngx_ssl_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
||||
unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
|
||||
HMAC_CTX *hctx, int enc)
|
||||
{
|
||||
size_t size;
|
||||
SSL_CTX *ssl_ctx;
|
||||
ngx_uint_t i;
|
||||
ngx_array_t *keys;
|
||||
ngx_connection_t *c;
|
||||
ngx_ssl_session_ticket_key_t *key;
|
||||
const EVP_MD *digest;
|
||||
const EVP_CIPHER *cipher;
|
||||
size_t size;
|
||||
SSL_CTX *ssl_ctx;
|
||||
ngx_uint_t i;
|
||||
ngx_array_t *keys;
|
||||
ngx_connection_t *c;
|
||||
ngx_ssl_ticket_key_t *key;
|
||||
const EVP_MD *digest;
|
||||
const EVP_CIPHER *cipher;
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
ssl_ctx = c->ssl->session_ctx;
|
||||
|
||||
if (ngx_ssl_rotate_ticket_keys(ssl_ctx, c->log) != NGX_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_NO_SHA256
|
||||
digest = EVP_sha1();
|
||||
#else
|
||||
digest = EVP_sha256();
|
||||
#endif
|
||||
|
||||
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
|
||||
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ticket_keys_index);
|
||||
if (keys == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -4369,7 +4549,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|||
/* encrypt session ticket */
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"ssl session ticket encrypt, key: \"%*xs\" (%s session)",
|
||||
"ssl ticket encrypt, key: \"%*xs\" (%s session)",
|
||||
(size_t) 16, key[0].name,
|
||||
SSL_session_reused(ssl_conn) ? "reused" : "new");
|
||||
|
||||
|
|
@ -4416,7 +4596,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"ssl session ticket decrypt, key: \"%*xs\" not found",
|
||||
"ssl ticket decrypt, key: \"%*xs\" not found",
|
||||
(size_t) 16, name);
|
||||
|
||||
return 0;
|
||||
|
|
@ -4424,7 +4604,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|||
found:
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"ssl session ticket decrypt, key: \"%*xs\"%s",
|
||||
"ssl ticket decrypt, key: \"%*xs\"%s",
|
||||
(size_t) 16, key[i].name, (i == 0) ? " (default)" : "");
|
||||
|
||||
if (key[i].size == 48) {
|
||||
|
|
@ -4461,7 +4641,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|||
|
||||
/* renew if non-default key */
|
||||
|
||||
if (i != 0) {
|
||||
if (i != 0 && key[i].expire) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
|
@ -4470,13 +4650,142 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_ssl_rotate_ticket_keys(SSL_CTX *ssl_ctx, ngx_log_t *log)
|
||||
{
|
||||
time_t now, expire;
|
||||
ngx_array_t *keys;
|
||||
ngx_shm_zone_t *shm_zone;
|
||||
ngx_slab_pool_t *shpool;
|
||||
ngx_ssl_ticket_key_t *key;
|
||||
ngx_ssl_session_cache_t *cache;
|
||||
u_char buf[80];
|
||||
|
||||
keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ticket_keys_index);
|
||||
if (keys == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
key = keys->elts;
|
||||
|
||||
if (!key[0].shared) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we don't need to update expiration of the current key
|
||||
* and the previous key is still needed, don't sync with shared
|
||||
* memory to save some work; in the worst case other worker process
|
||||
* will switch to the next key, but this process will still be able
|
||||
* to decrypt tickets encrypted with it
|
||||
*/
|
||||
|
||||
now = ngx_time();
|
||||
expire = now + SSL_CTX_get_timeout(ssl_ctx);
|
||||
|
||||
if (key[0].expire >= expire && key[1].expire >= now) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index);
|
||||
|
||||
cache = shm_zone->data;
|
||||
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||
|
||||
ngx_shmtx_lock(&shpool->mutex);
|
||||
|
||||
key = cache->ticket_keys;
|
||||
|
||||
if (key[0].expire == 0) {
|
||||
|
||||
/* initialize the current key */
|
||||
|
||||
if (RAND_bytes(buf, 80) != 1) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "RAND_bytes() failed");
|
||||
ngx_shmtx_unlock(&shpool->mutex);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
key[0].shared = 1;
|
||||
key[0].expire = expire;
|
||||
key[0].size = 80;
|
||||
ngx_memcpy(key[0].name, buf, 16);
|
||||
ngx_memcpy(key[0].hmac_key, buf + 16, 32);
|
||||
ngx_memcpy(key[0].aes_key, buf + 48, 32);
|
||||
|
||||
ngx_explicit_memzero(&buf, 80);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
|
||||
"ssl ticket key: \"%*xs\"",
|
||||
(size_t) 16, key[0].name);
|
||||
|
||||
/*
|
||||
* copy the current key to the next key, as initialization of
|
||||
* the previous key will replace the current key with the next
|
||||
* key
|
||||
*/
|
||||
|
||||
key[2] = key[0];
|
||||
}
|
||||
|
||||
if (key[1].expire < now) {
|
||||
|
||||
/*
|
||||
* if the previous key is no longer needed (or not initialized),
|
||||
* replace it with the current key, replace the current key with
|
||||
* the next key, and generate new next key
|
||||
*/
|
||||
|
||||
key[1] = key[0];
|
||||
key[0] = key[2];
|
||||
|
||||
if (RAND_bytes(buf, 80) != 1) {
|
||||
ngx_ssl_error(NGX_LOG_ALERT, log, 0, "RAND_bytes() failed");
|
||||
ngx_shmtx_unlock(&shpool->mutex);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
key[2].shared = 1;
|
||||
key[2].expire = 0;
|
||||
key[2].size = 80;
|
||||
ngx_memcpy(key[2].name, buf, 16);
|
||||
ngx_memcpy(key[2].hmac_key, buf + 16, 32);
|
||||
ngx_memcpy(key[2].aes_key, buf + 48, 32);
|
||||
|
||||
ngx_explicit_memzero(&buf, 80);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
|
||||
"ssl ticket key: \"%*xs\"",
|
||||
(size_t) 16, key[2].name);
|
||||
}
|
||||
|
||||
/*
|
||||
* update expiration of the current key: it is going to be needed
|
||||
* at least till the session being created expires
|
||||
*/
|
||||
|
||||
if (expire > key[0].expire) {
|
||||
key[0].expire = expire;
|
||||
}
|
||||
|
||||
/* sync keys to the worker process memory */
|
||||
|
||||
ngx_memcpy(keys->elts, cache->ticket_keys,
|
||||
2 * sizeof(ngx_ssl_ticket_key_t));
|
||||
|
||||
ngx_shmtx_unlock(&shpool->mutex);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_ssl_session_ticket_keys_cleanup(void *data)
|
||||
ngx_ssl_ticket_keys_cleanup(void *data)
|
||||
{
|
||||
ngx_array_t *keys = data;
|
||||
|
||||
ngx_explicit_memzero(keys->elts,
|
||||
keys->nelts * sizeof(ngx_ssl_session_ticket_key_t));
|
||||
keys->nelts * sizeof(ngx_ssl_ticket_key_t));
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ struct ngx_ssl_connection_s {
|
|||
unsigned no_send_shutdown:1;
|
||||
unsigned shutdown_without_free:1;
|
||||
unsigned handshake_buffer_set:1;
|
||||
unsigned session_timeout_set:1;
|
||||
unsigned try_early_data:1;
|
||||
unsigned in_early:1;
|
||||
unsigned in_ocsp:1;
|
||||
|
|
@ -134,37 +135,37 @@ typedef struct ngx_ssl_sess_id_s ngx_ssl_sess_id_t;
|
|||
|
||||
struct ngx_ssl_sess_id_s {
|
||||
ngx_rbtree_node_t node;
|
||||
u_char *id;
|
||||
size_t len;
|
||||
u_char *session;
|
||||
ngx_queue_t queue;
|
||||
time_t expire;
|
||||
u_char id[32];
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
void *stub;
|
||||
u_char sess_id[32];
|
||||
u_char *session;
|
||||
#else
|
||||
u_char session[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char name[16];
|
||||
u_char hmac_key[32];
|
||||
u_char aes_key[32];
|
||||
time_t expire;
|
||||
unsigned size:8;
|
||||
unsigned shared:1;
|
||||
} ngx_ssl_ticket_key_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_rbtree_t session_rbtree;
|
||||
ngx_rbtree_node_t sentinel;
|
||||
ngx_queue_t expire_queue;
|
||||
ngx_ssl_ticket_key_t ticket_keys[3];
|
||||
time_t fail_time;
|
||||
} ngx_ssl_session_cache_t;
|
||||
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
u_char name[16];
|
||||
u_char hmac_key[32];
|
||||
u_char aes_key[32];
|
||||
} ngx_ssl_session_ticket_key_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_SSL_SSLv2 0x0002
|
||||
#define NGX_SSL_SSLv3 0x0004
|
||||
#define NGX_SSL_TLSv1 0x0008
|
||||
|
|
@ -204,10 +205,12 @@ ngx_int_t ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
|
|||
ngx_uint_t depth, ngx_shm_zone_t *shm_zone);
|
||||
ngx_int_t ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
|
||||
|
||||
ngx_int_t ngx_ssl_ocsp_validate(ngx_connection_t *c);
|
||||
ngx_int_t ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s);
|
||||
void ngx_ssl_ocsp_cleanup(ngx_connection_t *c);
|
||||
ngx_int_t ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data);
|
||||
|
||||
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
|
||||
ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf,
|
||||
ngx_array_t *passwords);
|
||||
|
|
@ -314,7 +317,7 @@ void ngx_ssl_cleanup_ctx(void *data);
|
|||
extern int ngx_ssl_connection_index;
|
||||
extern int ngx_ssl_server_conf_index;
|
||||
extern int ngx_ssl_session_cache_index;
|
||||
extern int ngx_ssl_session_ticket_keys_index;
|
||||
extern int ngx_ssl_ticket_keys_index;
|
||||
extern int ngx_ssl_ocsp_index;
|
||||
extern int ngx_ssl_certificate_index;
|
||||
extern int ngx_ssl_next_certificate_index;
|
||||
|
|
|
|||
|
|
@ -46,18 +46,8 @@ ngx_event_recvmsg(ngx_event_t *ev)
|
|||
ngx_connection_t *c, *lc;
|
||||
static u_char buffer[65535];
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
#if (NGX_HAVE_IP_RECVDSTADDR)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))];
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))];
|
||||
#endif
|
||||
|
||||
if (ev->timedout) {
|
||||
|
|
@ -92,25 +82,13 @@ ngx_event_recvmsg(ngx_event_t *ev)
|
|||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
if (ls->wildcard) {
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
#if (NGX_HAVE_IP_RECVDSTADDR || NGX_HAVE_IP_PKTINFO)
|
||||
if (ls->sockaddr->sa_family == AF_INET) {
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
if (ls->sockaddr->sa_family == AF_INET6) {
|
||||
msg.msg_control = &msg_control6;
|
||||
msg.msg_controllen = sizeof(msg_control6);
|
||||
}
|
||||
#endif
|
||||
ngx_memzero(&msg_control, sizeof(msg_control));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
n = recvmsg(lc->fd, &msg, 0);
|
||||
|
|
@ -129,7 +107,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
|
|||
return;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
|
||||
"recvmsg() truncated data");
|
||||
|
|
@ -159,7 +137,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
|
|||
local_sockaddr = ls->sockaddr;
|
||||
local_socklen = ls->socklen;
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
|
||||
if (ls->wildcard) {
|
||||
struct cmsghdr *cmsg;
|
||||
|
|
@ -171,59 +149,9 @@ ngx_event_recvmsg(ngx_event_t *ev)
|
|||
cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg))
|
||||
{
|
||||
|
||||
#if (NGX_HAVE_IP_RECVDSTADDR)
|
||||
|
||||
if (cmsg->cmsg_level == IPPROTO_IP
|
||||
&& cmsg->cmsg_type == IP_RECVDSTADDR
|
||||
&& local_sockaddr->sa_family == AF_INET)
|
||||
{
|
||||
struct in_addr *addr;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
addr = (struct in_addr *) CMSG_DATA(cmsg);
|
||||
sin = (struct sockaddr_in *) local_sockaddr;
|
||||
sin->sin_addr = *addr;
|
||||
|
||||
if (ngx_get_srcaddr_cmsg(cmsg, local_sockaddr) == NGX_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
|
||||
if (cmsg->cmsg_level == IPPROTO_IP
|
||||
&& cmsg->cmsg_type == IP_PKTINFO
|
||||
&& local_sockaddr->sa_family == AF_INET)
|
||||
{
|
||||
struct in_pktinfo *pkt;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
sin = (struct sockaddr_in *) local_sockaddr;
|
||||
sin->sin_addr = pkt->ipi_addr;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
|
||||
if (cmsg->cmsg_level == IPPROTO_IPV6
|
||||
&& cmsg->cmsg_type == IPV6_PKTINFO
|
||||
&& local_sockaddr->sa_family == AF_INET6)
|
||||
{
|
||||
struct in6_pktinfo *pkt6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
|
||||
sin6 = (struct sockaddr_in6 *) local_sockaddr;
|
||||
sin6->sin6_addr = pkt6->ipi6_addr;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +246,8 @@ ngx_event_recvmsg(ngx_event_t *ev)
|
|||
c->send = ngx_udp_send;
|
||||
c->send_chain = ngx_udp_send_chain;
|
||||
|
||||
c->need_flush_buf = 1;
|
||||
|
||||
c->log = log;
|
||||
c->pool->log = log;
|
||||
c->listening = ls;
|
||||
|
|
|
|||
58
src/event/ngx_event_udp.h
Normal file
58
src/event/ngx_event_udp.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_EVENT_UDP_H_INCLUDED_
|
||||
#define _NGX_EVENT_UDP_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#if !(NGX_WIN32)
|
||||
|
||||
#if ((NGX_HAVE_MSGHDR_MSG_CONTROL) \
|
||||
&& (NGX_HAVE_IP_SENDSRCADDR || NGX_HAVE_IP_RECVDSTADDR \
|
||||
|| NGX_HAVE_IP_PKTINFO \
|
||||
|| (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)))
|
||||
#define NGX_HAVE_ADDRINFO_CMSG 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
|
||||
typedef union {
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR || NGX_HAVE_IP_RECVDSTADDR)
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_IP_PKTINFO)
|
||||
struct in_pktinfo pkt;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
struct in6_pktinfo pkt6;
|
||||
#endif
|
||||
} ngx_addrinfo_t;
|
||||
|
||||
size_t ngx_set_srcaddr_cmsg(struct cmsghdr *cmsg,
|
||||
struct sockaddr *local_sockaddr);
|
||||
ngx_int_t ngx_get_srcaddr_cmsg(struct cmsghdr *cmsg,
|
||||
struct sockaddr *local_sockaddr);
|
||||
|
||||
#endif
|
||||
|
||||
void ngx_event_recvmsg(ngx_event_t *ev);
|
||||
ssize_t ngx_sendmsg(ngx_connection_t *c, struct msghdr *msg, int flags);
|
||||
void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
||||
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
|
||||
#endif
|
||||
|
||||
void ngx_delete_udp_connection(void *data);
|
||||
|
||||
|
||||
#endif /* _NGX_EVENT_UDP_H_INCLUDED_ */
|
||||
|
|
@ -339,6 +339,7 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
|
|||
*p = '"';
|
||||
|
||||
r->headers_out.www_authenticate->hash = 1;
|
||||
r->headers_out.www_authenticate->next = NULL;
|
||||
ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate");
|
||||
r->headers_out.www_authenticate->value.data = basic;
|
||||
r->headers_out.www_authenticate->value.len = len;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ ngx_module_t ngx_http_auth_request_module = {
|
|||
static ngx_int_t
|
||||
ngx_http_auth_request_handler(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_table_elt_t *h, *ho;
|
||||
ngx_table_elt_t *h, *ho, **ph;
|
||||
ngx_http_request_t *sr;
|
||||
ngx_http_post_subrequest_t *ps;
|
||||
ngx_http_auth_request_ctx_t *ctx;
|
||||
|
|
@ -147,15 +147,21 @@ ngx_http_auth_request_handler(ngx_http_request_t *r)
|
|||
h = sr->upstream->headers_in.www_authenticate;
|
||||
}
|
||||
|
||||
if (h) {
|
||||
ph = &r->headers_out.www_authenticate;
|
||||
|
||||
while (h) {
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
if (ho == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
r->headers_out.www_authenticate = ho;
|
||||
*ph = ho;
|
||||
ph = &ho->next;
|
||||
|
||||
h = h->next;
|
||||
}
|
||||
|
||||
return ctx->status;
|
||||
|
|
|
|||
|
|
@ -1082,6 +1082,7 @@ ngx_http_dav_location(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->next = NULL;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
|
||||
|
|
|
|||
|
|
@ -835,14 +835,14 @@ static ngx_int_t
|
|||
ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
||||
{
|
||||
off_t file_pos;
|
||||
u_char ch, *pos, *lowcase_key;
|
||||
u_char ch, sep, *pos, *lowcase_key;
|
||||
size_t size, len, key_len, val_len, padding,
|
||||
allocated;
|
||||
ngx_uint_t i, n, next, hash, skip_empty, header_params;
|
||||
ngx_buf_t *b;
|
||||
ngx_chain_t *cl, *body;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *header, **ignored;
|
||||
ngx_table_elt_t *header, *hn, **ignored;
|
||||
ngx_http_upstream_t *u;
|
||||
ngx_http_script_code_pt code;
|
||||
ngx_http_script_engine_t e, le;
|
||||
|
|
@ -900,7 +900,11 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
|||
allocated = 0;
|
||||
lowcase_key = NULL;
|
||||
|
||||
if (params->number) {
|
||||
if (ngx_http_link_multi_headers(r) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (params->number || r->headers_in.multi) {
|
||||
n = 0;
|
||||
part = &r->headers_in.headers.part;
|
||||
|
||||
|
|
@ -930,6 +934,12 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
for (n = 0; n < header_params; n++) {
|
||||
if (&header[i] == ignored[n]) {
|
||||
goto next_length;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->number) {
|
||||
if (allocated < header[i].key.len) {
|
||||
allocated = header[i].key.len + 16;
|
||||
|
|
@ -959,15 +969,23 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
|||
ignored[header_params++] = &header[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
n += sizeof("HTTP_") - 1;
|
||||
|
||||
} else {
|
||||
n = sizeof("HTTP_") - 1 + header[i].key.len;
|
||||
}
|
||||
|
||||
len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)
|
||||
+ n + header[i].value.len;
|
||||
key_len = sizeof("HTTP_") - 1 + header[i].key.len;
|
||||
|
||||
val_len = header[i].value.len;
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
val_len += hn->value.len + 2;
|
||||
ignored[header_params++] = hn;
|
||||
}
|
||||
|
||||
len += ((key_len > 127) ? 4 : 1) + key_len
|
||||
+ ((val_len > 127) ? 4 : 1) + val_len;
|
||||
|
||||
next_length:
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1109,7 +1127,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
|||
|
||||
for (n = 0; n < header_params; n++) {
|
||||
if (&header[i] == ignored[n]) {
|
||||
goto next;
|
||||
goto next_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1125,6 +1143,11 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
val_len = header[i].value.len;
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
val_len += hn->value.len + 2;
|
||||
}
|
||||
|
||||
if (val_len > 127) {
|
||||
*b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
|
||||
*b->last++ = (u_char) ((val_len >> 16) & 0xff);
|
||||
|
|
@ -1150,13 +1173,34 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
|
|||
*b->last++ = ch;
|
||||
}
|
||||
|
||||
b->last = ngx_copy(b->last, header[i].value.data, val_len);
|
||||
b->last = ngx_copy(b->last, header[i].value.data,
|
||||
header[i].value.len);
|
||||
|
||||
if (header[i].next) {
|
||||
|
||||
if (header[i].key.len == sizeof("Cookie") - 1
|
||||
&& ngx_strncasecmp(header[i].key.data, (u_char *) "Cookie",
|
||||
sizeof("Cookie") - 1)
|
||||
== 0)
|
||||
{
|
||||
sep = ';';
|
||||
|
||||
} else {
|
||||
sep = ',';
|
||||
}
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
*b->last++ = sep;
|
||||
*b->last++ = ' ';
|
||||
b->last = ngx_copy(b->last, hn->value.data, hn->value.len);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"fastcgi param: \"%*s: %*s\"",
|
||||
key_len, b->last - (key_len + val_len),
|
||||
val_len, b->last - val_len);
|
||||
next:
|
||||
next_value:
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1963,8 +2007,12 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
|
|||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
if (hh) {
|
||||
rc = hh->handler(r, h, hh->offset);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
|
|
|||
|
|
@ -232,9 +232,10 @@ ngx_http_flv_handler(ngx_http_request_t *r)
|
|||
b->file_pos = start;
|
||||
b->file_last = of.size;
|
||||
|
||||
b->in_file = b->file_last ? 1: 0;
|
||||
b->in_file = b->file_last ? 1 : 0;
|
||||
b->last_buf = (r == r->main) ? 1 : 0;
|
||||
b->last_in_chain = 1;
|
||||
b->sync = (b->last_buf || b->in_file) ? 0 : 1;
|
||||
|
||||
b->file->fd = of.fd;
|
||||
b->file->name = path;
|
||||
|
|
|
|||
|
|
@ -327,15 +327,15 @@ static ngx_int_t
|
|||
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
|
||||
ngx_addr_t *addr)
|
||||
{
|
||||
ngx_array_t *xfwd;
|
||||
ngx_table_elt_t *xfwd;
|
||||
|
||||
if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
xfwd = &r->headers_in.x_forwarded_for;
|
||||
xfwd = r->headers_in.x_forwarded_for;
|
||||
|
||||
if (xfwd->nelts > 0 && ctx->proxies != NULL) {
|
||||
if (xfwd != NULL && ctx->proxies != NULL) {
|
||||
(void) ngx_http_get_forwarded_addr(r, addr, xfwd, NULL,
|
||||
ctx->proxies, ctx->proxy_recursive);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,16 +240,16 @@ static u_long
|
|||
ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
|
||||
{
|
||||
ngx_addr_t addr;
|
||||
ngx_array_t *xfwd;
|
||||
ngx_table_elt_t *xfwd;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
addr.sockaddr = r->connection->sockaddr;
|
||||
addr.socklen = r->connection->socklen;
|
||||
/* addr.name = r->connection->addr_text; */
|
||||
|
||||
xfwd = &r->headers_in.x_forwarded_for;
|
||||
xfwd = r->headers_in.x_forwarded_for;
|
||||
|
||||
if (xfwd->nelts > 0 && gcf->proxies != NULL) {
|
||||
if (xfwd != NULL && gcf->proxies != NULL) {
|
||||
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
|
||||
gcf->proxies, gcf->proxy_recursive);
|
||||
}
|
||||
|
|
@ -292,7 +292,7 @@ static geoipv6_t
|
|||
ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
|
||||
{
|
||||
ngx_addr_t addr;
|
||||
ngx_array_t *xfwd;
|
||||
ngx_table_elt_t *xfwd;
|
||||
in_addr_t addr4;
|
||||
struct in6_addr addr6;
|
||||
struct sockaddr_in *sin;
|
||||
|
|
@ -302,9 +302,9 @@ ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
|
|||
addr.socklen = r->connection->socklen;
|
||||
/* addr.name = r->connection->addr_text; */
|
||||
|
||||
xfwd = &r->headers_in.x_forwarded_for;
|
||||
xfwd = r->headers_in.x_forwarded_for;
|
||||
|
||||
if (xfwd->nelts > 0 && gcf->proxies != NULL) {
|
||||
if (xfwd != NULL && gcf->proxies != NULL) {
|
||||
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
|
||||
gcf->proxies, gcf->proxy_recursive);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,6 +209,8 @@ static char *ngx_http_grpc_ssl_password_file(ngx_conf_t *cf,
|
|||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post,
|
||||
void *data);
|
||||
static ngx_int_t ngx_http_grpc_merge_ssl(ngx_conf_t *cf,
|
||||
ngx_http_grpc_loc_conf_t *conf, ngx_http_grpc_loc_conf_t *prev);
|
||||
static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf,
|
||||
ngx_http_grpc_loc_conf_t *glcf);
|
||||
#endif
|
||||
|
|
@ -562,7 +564,7 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
|
|||
ctx->host = glcf->host;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
u->ssl = (glcf->upstream.ssl != NULL);
|
||||
u->ssl = glcf->ssl;
|
||||
|
||||
if (u->ssl) {
|
||||
ngx_str_set(&u->schema, "grpcs://");
|
||||
|
|
@ -1891,8 +1893,12 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
|
|||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
if (hh) {
|
||||
rc = hh->handler(r, h, hh->offset);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -4459,12 +4465,17 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
if (ngx_http_grpc_merge_ssl(cf, conf, prev) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
|
||||
prev->upstream.ssl_session_reuse, 1);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
|
||||
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
|
||||
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
|
||||
(NGX_CONF_BITMASK_SET
|
||||
|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
|
||||
|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
|
||||
"DEFAULT");
|
||||
|
|
@ -4520,7 +4531,7 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
conf->grpc_values = prev->grpc_values;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
conf->upstream.ssl = prev->upstream.ssl;
|
||||
conf->ssl = prev->ssl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4869,18 +4880,64 @@ ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_grpc_merge_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
|
||||
ngx_http_grpc_loc_conf_t *prev)
|
||||
{
|
||||
ngx_uint_t preserve;
|
||||
|
||||
if (conf->ssl_protocols == 0
|
||||
&& conf->ssl_ciphers.data == NULL
|
||||
&& conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_verify == NGX_CONF_UNSET
|
||||
&& conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
|
||||
&& conf->ssl_trusted_certificate.data == NULL
|
||||
&& conf->ssl_crl.data == NULL
|
||||
&& conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
|
||||
&& conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
|
||||
{
|
||||
if (prev->upstream.ssl) {
|
||||
conf->upstream.ssl = prev->upstream.ssl;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
preserve = 1;
|
||||
|
||||
} else {
|
||||
preserve = 0;
|
||||
}
|
||||
|
||||
conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
|
||||
if (conf->upstream.ssl == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
conf->upstream.ssl->log = cf->log;
|
||||
|
||||
/*
|
||||
* special handling to preserve conf->upstream.ssl
|
||||
* in the "http" section to inherit it to all servers
|
||||
*/
|
||||
|
||||
if (preserve) {
|
||||
prev->upstream.ssl = conf->upstream.ssl;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
|
||||
{
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
glcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
|
||||
if (glcf->upstream.ssl == NULL) {
|
||||
return NGX_ERROR;
|
||||
if (glcf->upstream.ssl->ctx) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
glcf->upstream.ssl->log = cf->log;
|
||||
|
||||
if (ngx_ssl_create(glcf->upstream.ssl, glcf->ssl_protocols, NULL)
|
||||
!= NGX_OK)
|
||||
{
|
||||
|
|
@ -4902,8 +4959,9 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (glcf->upstream.ssl_certificate) {
|
||||
|
||||
if (glcf->upstream.ssl_certificate
|
||||
&& glcf->upstream.ssl_certificate->value.len)
|
||||
{
|
||||
if (glcf->upstream.ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"grpc_ssl_certificate_key\" is defined "
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ typedef struct {
|
|||
unsigned nomem:1;
|
||||
unsigned buffering:1;
|
||||
unsigned zlib_ng:1;
|
||||
unsigned state_allocated:1;
|
||||
|
||||
size_t zin;
|
||||
size_t zout;
|
||||
|
|
@ -280,6 +281,7 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
h->hash = 1;
|
||||
h->next = NULL;
|
||||
ngx_str_set(&h->key, "Content-Encoding");
|
||||
ngx_str_set(&h->value, "gzip");
|
||||
r->headers_out.content_encoding = h;
|
||||
|
|
@ -513,9 +515,10 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
|
|||
} else {
|
||||
/*
|
||||
* Another zlib variant, https://github.com/zlib-ng/zlib-ng.
|
||||
* It forces window bits to 13 for fast compression level,
|
||||
* uses 16-byte padding in one of window-sized buffers, and
|
||||
* uses 128K hash.
|
||||
* It used to force window bits to 13 for fast compression level,
|
||||
* uses (64 + sizeof(void*)) additional space on all allocations
|
||||
* for alignment, 16-byte padding in one of window-sized buffers,
|
||||
* and 128K hash.
|
||||
*/
|
||||
|
||||
if (conf->level == 1) {
|
||||
|
|
@ -523,7 +526,8 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
|
|||
}
|
||||
|
||||
ctx->allocated = 8192 + 16 + (1 << (wbits + 2))
|
||||
+ 131072 + (1 << (memlevel + 8));
|
||||
+ 131072 + (1 << (memlevel + 8))
|
||||
+ 4 * (64 + sizeof(void*));
|
||||
ctx->zlib_ng = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -925,13 +929,16 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size)
|
|||
|
||||
alloc = items * size;
|
||||
|
||||
if (items == 1 && alloc % 512 != 0 && alloc < 8192) {
|
||||
|
||||
if (items == 1 && alloc % 512 != 0 && alloc < 8192
|
||||
&& !ctx->state_allocated)
|
||||
{
|
||||
/*
|
||||
* The zlib deflate_state allocation, it takes about 6K,
|
||||
* we allocate 8K. Other allocations are divisible by 512.
|
||||
*/
|
||||
|
||||
ctx->state_allocated = 1;
|
||||
|
||||
alloc = 8192;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,10 +242,13 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
h->hash = 1;
|
||||
h->next = NULL;
|
||||
ngx_str_set(&h->key, "Content-Encoding");
|
||||
ngx_str_set(&h->value, "gzip");
|
||||
r->headers_out.content_encoding = h;
|
||||
|
||||
r->allow_ranges = 1;
|
||||
|
||||
/* we need to allocate all before the header would be sent */
|
||||
|
||||
b = ngx_calloc_buf(r->pool);
|
||||
|
|
@ -270,6 +273,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
|
|||
b->in_file = b->file_last ? 1 : 0;
|
||||
b->last_buf = (r == r->main) ? 1 : 0;
|
||||
b->last_in_chain = 1;
|
||||
b->sync = (b->last_buf || b->in_file) ? 0 : 1;
|
||||
|
||||
b->file->fd = of.fd;
|
||||
b->file->name = path;
|
||||
|
|
|
|||
|
|
@ -329,8 +329,7 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
|
|||
time_t now, expires_time, max_age;
|
||||
ngx_str_t value;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *e, *cc, **ccp;
|
||||
ngx_table_elt_t *e, *cc;
|
||||
ngx_http_expires_t expires;
|
||||
|
||||
expires = conf->expires;
|
||||
|
|
@ -363,6 +362,7 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
|
|||
}
|
||||
|
||||
r->headers_out.expires = e;
|
||||
e->next = NULL;
|
||||
|
||||
e->hash = 1;
|
||||
ngx_str_set(&e->key, "Expires");
|
||||
|
|
@ -371,38 +371,29 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
|
|||
len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
|
||||
e->value.len = len - 1;
|
||||
|
||||
ccp = r->headers_out.cache_control.elts;
|
||||
cc = r->headers_out.cache_control;
|
||||
|
||||
if (ccp == NULL) {
|
||||
|
||||
if (ngx_array_init(&r->headers_out.cache_control, r->pool,
|
||||
1, sizeof(ngx_table_elt_t *))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
if (cc == NULL) {
|
||||
|
||||
cc = ngx_list_push(&r->headers_out.headers);
|
||||
if (cc == NULL) {
|
||||
e->hash = 0;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.cache_control = cc;
|
||||
cc->next = NULL;
|
||||
|
||||
cc->hash = 1;
|
||||
ngx_str_set(&cc->key, "Cache-Control");
|
||||
|
||||
ccp = ngx_array_push(&r->headers_out.cache_control);
|
||||
if (ccp == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ccp = cc;
|
||||
|
||||
} else {
|
||||
for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
|
||||
ccp[i]->hash = 0;
|
||||
for (cc = cc->next; cc; cc = cc->next) {
|
||||
cc->hash = 0;
|
||||
}
|
||||
|
||||
cc = ccp[0];
|
||||
cc = r->headers_out.cache_control;
|
||||
cc->next = NULL;
|
||||
}
|
||||
|
||||
if (expires == NGX_HTTP_EXPIRES_EPOCH) {
|
||||
|
|
@ -420,6 +411,8 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
|
|||
|
||||
e->value.data = ngx_pnalloc(r->pool, len);
|
||||
if (e->value.data == NULL) {
|
||||
e->hash = 0;
|
||||
cc->hash = 0;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -457,6 +450,7 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
|
|||
cc->value.data = ngx_pnalloc(r->pool,
|
||||
sizeof("max-age=") + NGX_TIME_T_LEN + 1);
|
||||
if (cc->value.data == NULL) {
|
||||
cc->hash = 0;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -564,22 +558,12 @@ static ngx_int_t
|
|||
ngx_http_add_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_http_header_val_t *hv, ngx_str_t *value)
|
||||
{
|
||||
ngx_array_t *pa;
|
||||
ngx_table_elt_t *h, **ph;
|
||||
|
||||
if (value->len == 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
pa = (ngx_array_t *) ((char *) &r->headers_out + hv->offset);
|
||||
|
||||
if (pa->elts == NULL) {
|
||||
if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
h = ngx_list_push(&r->headers_out.headers);
|
||||
if (h == NULL) {
|
||||
return NGX_ERROR;
|
||||
|
|
@ -589,12 +573,12 @@ ngx_http_add_multi_header_lines(ngx_http_request_t *r,
|
|||
h->key = hv->key;
|
||||
h->value = *value;
|
||||
|
||||
ph = ngx_array_push(pa);
|
||||
if (ph == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
|
||||
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -642,6 +626,7 @@ ngx_http_set_response_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
|
|||
}
|
||||
|
||||
*old = h;
|
||||
h->next = NULL;
|
||||
}
|
||||
|
||||
h->hash = 1;
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ found:
|
|||
}
|
||||
|
||||
h->hash = 1;
|
||||
h->next = NULL;
|
||||
ngx_str_set(&h->key, "Content-Encoding");
|
||||
ngx_str_set(&h->value, "gzip");
|
||||
r->headers_out.content_encoding = h;
|
||||
|
|
|
|||
|
|
@ -714,6 +714,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||
b->in_file = b->file_last ? 1 : 0;
|
||||
b->last_buf = (r == r->main) ? 1 : 0;
|
||||
b->last_in_chain = 1;
|
||||
b->sync = (b->last_buf || b->in_file) ? 0 : 1;
|
||||
|
||||
b->file->fd = of.fd;
|
||||
b->file->name = path;
|
||||
|
|
@ -2430,7 +2431,7 @@ ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
|||
}
|
||||
|
||||
start_sample += count;
|
||||
start_time -= count * duration;
|
||||
start_time -= (uint64_t) count * duration;
|
||||
entries--;
|
||||
entry++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,6 +236,8 @@ static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
|
|||
ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
static ngx_int_t ngx_http_proxy_merge_ssl(ngx_conf_t *cf,
|
||||
ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev);
|
||||
static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
|
||||
ngx_http_proxy_loc_conf_t *plcf);
|
||||
#endif
|
||||
|
|
@ -959,7 +961,7 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
|
|||
ctx->vars = plcf->vars;
|
||||
u->schema = plcf->vars.schema;
|
||||
#if (NGX_HTTP_SSL)
|
||||
u->ssl = (plcf->upstream.ssl != NULL);
|
||||
u->ssl = plcf->ssl;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
|
@ -1930,8 +1932,12 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
if (hh) {
|
||||
rc = hh->handler(r, h, hh->offset);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
|
@ -1965,6 +1971,7 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||
ngx_str_set(&h->key, "Server");
|
||||
ngx_str_null(&h->value);
|
||||
h->lowcase_key = (u_char *) "server";
|
||||
h->next = NULL;
|
||||
}
|
||||
|
||||
if (r->upstream->headers_in.date == NULL) {
|
||||
|
|
@ -1978,6 +1985,7 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||
ngx_str_set(&h->key, "Date");
|
||||
ngx_str_null(&h->value);
|
||||
h->lowcase_key = (u_char *) "date";
|
||||
h->next = NULL;
|
||||
}
|
||||
|
||||
/* clear content length if response is chunked */
|
||||
|
|
@ -2559,22 +2567,20 @@ static ngx_int_t
|
|||
ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
size_t len;
|
||||
u_char *p;
|
||||
ngx_uint_t i, n;
|
||||
ngx_table_elt_t **h;
|
||||
size_t len;
|
||||
u_char *p;
|
||||
ngx_table_elt_t *h, *xfwd;
|
||||
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
|
||||
n = r->headers_in.x_forwarded_for.nelts;
|
||||
h = r->headers_in.x_forwarded_for.elts;
|
||||
xfwd = r->headers_in.x_forwarded_for;
|
||||
|
||||
len = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
len += h[i]->value.len + sizeof(", ") - 1;
|
||||
for (h = xfwd; h; h = h->next) {
|
||||
len += h->value.len + sizeof(", ") - 1;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
|
|
@ -2593,8 +2599,8 @@ ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
|
|||
v->len = len;
|
||||
v->data = p;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
|
||||
for (h = xfwd; h; h = h->next) {
|
||||
p = ngx_copy(p, h->value.data, h->value.len);
|
||||
*p++ = ','; *p++ = ' ';
|
||||
}
|
||||
|
||||
|
|
@ -3720,12 +3726,17 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
if (ngx_http_proxy_merge_ssl(cf, conf, prev) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
|
||||
prev->upstream.ssl_session_reuse, 1);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
|
||||
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
|
||||
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
|
||||
(NGX_CONF_BITMASK_SET
|
||||
|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
|
||||
|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
|
||||
"DEFAULT");
|
||||
|
|
@ -3853,7 +3864,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
conf->proxy_values = prev->proxy_values;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
conf->upstream.ssl = prev->upstream.ssl;
|
||||
conf->ssl = prev->ssl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4918,18 +4929,64 @@ ngx_http_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_merge_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
|
||||
ngx_http_proxy_loc_conf_t *prev)
|
||||
{
|
||||
ngx_uint_t preserve;
|
||||
|
||||
if (conf->ssl_protocols == 0
|
||||
&& conf->ssl_ciphers.data == NULL
|
||||
&& conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_verify == NGX_CONF_UNSET
|
||||
&& conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
|
||||
&& conf->ssl_trusted_certificate.data == NULL
|
||||
&& conf->ssl_crl.data == NULL
|
||||
&& conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
|
||||
&& conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
|
||||
{
|
||||
if (prev->upstream.ssl) {
|
||||
conf->upstream.ssl = prev->upstream.ssl;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
preserve = 1;
|
||||
|
||||
} else {
|
||||
preserve = 0;
|
||||
}
|
||||
|
||||
conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
|
||||
if (conf->upstream.ssl == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
conf->upstream.ssl->log = cf->log;
|
||||
|
||||
/*
|
||||
* special handling to preserve conf->upstream.ssl
|
||||
* in the "http" section to inherit it to all servers
|
||||
*/
|
||||
|
||||
if (preserve) {
|
||||
prev->upstream.ssl = conf->upstream.ssl;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
|
||||
{
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
|
||||
if (plcf->upstream.ssl == NULL) {
|
||||
return NGX_ERROR;
|
||||
if (plcf->upstream.ssl->ctx) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
plcf->upstream.ssl->log = cf->log;
|
||||
|
||||
if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL)
|
||||
!= NGX_OK)
|
||||
{
|
||||
|
|
@ -4951,8 +5008,9 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (plcf->upstream.ssl_certificate) {
|
||||
|
||||
if (plcf->upstream.ssl_certificate
|
||||
&& plcf->upstream.ssl_certificate->value.len)
|
||||
{
|
||||
if (plcf->upstream.ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"proxy_ssl_certificate_key\" is defined "
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ next_filter:
|
|||
}
|
||||
|
||||
r->headers_out.accept_ranges->hash = 1;
|
||||
r->headers_out.accept_ranges->next = NULL;
|
||||
ngx_str_set(&r->headers_out.accept_ranges->key, "Accept-Ranges");
|
||||
ngx_str_set(&r->headers_out.accept_ranges->value, "bytes");
|
||||
|
||||
|
|
@ -424,9 +425,14 @@ ngx_http_range_singlepart_header(ngx_http_request_t *r,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_range) {
|
||||
r->headers_out.content_range->hash = 0;
|
||||
}
|
||||
|
||||
r->headers_out.content_range = content_range;
|
||||
|
||||
content_range->hash = 1;
|
||||
content_range->next = NULL;
|
||||
ngx_str_set(&content_range->key, "Content-Range");
|
||||
|
||||
content_range->value.data = ngx_pnalloc(r->pool,
|
||||
|
|
@ -580,6 +586,11 @@ ngx_http_range_multipart_header(ngx_http_request_t *r,
|
|||
r->headers_out.content_length = NULL;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_range) {
|
||||
r->headers_out.content_range->hash = 0;
|
||||
r->headers_out.content_range = NULL;
|
||||
}
|
||||
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
|
|
@ -596,9 +607,14 @@ ngx_http_range_not_satisfiable(ngx_http_request_t *r)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_range) {
|
||||
r->headers_out.content_range->hash = 0;
|
||||
}
|
||||
|
||||
r->headers_out.content_range = content_range;
|
||||
|
||||
content_range->hash = 1;
|
||||
content_range->next = NULL;
|
||||
ngx_str_set(&content_range->key, "Content-Range");
|
||||
|
||||
content_range->value.data = ngx_pnalloc(r->pool,
|
||||
|
|
|
|||
|
|
@ -134,9 +134,8 @@ ngx_http_realip_handler(ngx_http_request_t *r)
|
|||
ngx_str_t *value;
|
||||
ngx_uint_t i, hash;
|
||||
ngx_addr_t addr;
|
||||
ngx_array_t *xfwd;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *header;
|
||||
ngx_table_elt_t *header, *xfwd;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_realip_ctx_t *ctx;
|
||||
ngx_http_realip_loc_conf_t *rlcf;
|
||||
|
|
@ -168,9 +167,9 @@ ngx_http_realip_handler(ngx_http_request_t *r)
|
|||
|
||||
case NGX_HTTP_REALIP_XFWD:
|
||||
|
||||
xfwd = &r->headers_in.x_forwarded_for;
|
||||
xfwd = r->headers_in.x_forwarded_for;
|
||||
|
||||
if (xfwd->elts == NULL) {
|
||||
if (xfwd == NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -633,14 +633,14 @@ static ngx_int_t
|
|||
ngx_http_scgi_create_request(ngx_http_request_t *r)
|
||||
{
|
||||
off_t content_length_n;
|
||||
u_char ch, *key, *val, *lowcase_key;
|
||||
u_char ch, sep, *key, *val, *lowcase_key;
|
||||
size_t len, key_len, val_len, allocated;
|
||||
ngx_buf_t *b;
|
||||
ngx_str_t content_length;
|
||||
ngx_uint_t i, n, hash, skip_empty, header_params;
|
||||
ngx_chain_t *cl, *body;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *header, **ignored;
|
||||
ngx_table_elt_t *header, *hn, **ignored;
|
||||
ngx_http_scgi_params_t *params;
|
||||
ngx_http_script_code_pt code;
|
||||
ngx_http_script_engine_t e, le;
|
||||
|
|
@ -707,7 +707,11 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
|
|||
allocated = 0;
|
||||
lowcase_key = NULL;
|
||||
|
||||
if (params->number) {
|
||||
if (ngx_http_link_multi_headers(r) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (params->number || r->headers_in.multi) {
|
||||
n = 0;
|
||||
part = &r->headers_in.headers.part;
|
||||
|
||||
|
|
@ -737,6 +741,12 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
for (n = 0; n < header_params; n++) {
|
||||
if (&header[i] == ignored[n]) {
|
||||
goto next_length;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->number) {
|
||||
if (allocated < header[i].key.len) {
|
||||
allocated = header[i].key.len + 16;
|
||||
|
|
@ -770,6 +780,15 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
|
|||
|
||||
len += sizeof("HTTP_") - 1 + header[i].key.len + 1
|
||||
+ header[i].value.len + 1;
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
len += hn->value.len + 2;
|
||||
ignored[header_params++] = hn;
|
||||
}
|
||||
|
||||
next_length:
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -869,7 +888,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
|
|||
|
||||
for (n = 0; n < header_params; n++) {
|
||||
if (&header[i] == ignored[n]) {
|
||||
goto next;
|
||||
goto next_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -893,12 +912,33 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
|
|||
|
||||
val = b->last;
|
||||
b->last = ngx_copy(val, header[i].value.data, header[i].value.len);
|
||||
|
||||
if (header[i].next) {
|
||||
|
||||
if (header[i].key.len == sizeof("Cookie") - 1
|
||||
&& ngx_strncasecmp(header[i].key.data, (u_char *) "Cookie",
|
||||
sizeof("Cookie") - 1)
|
||||
== 0)
|
||||
{
|
||||
sep = ';';
|
||||
|
||||
} else {
|
||||
sep = ',';
|
||||
}
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
*b->last++ = sep;
|
||||
*b->last++ = ' ';
|
||||
b->last = ngx_copy(b->last, hn->value.data, hn->value.len);
|
||||
}
|
||||
}
|
||||
|
||||
*b->last++ = (u_char) 0;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"scgi param: \"%s: %s\"", key, val);
|
||||
|
||||
next:
|
||||
next_value:
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1074,8 +1114,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
|
|||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
if (hh) {
|
||||
rc = hh->handler(r, h, hh->offset);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ static ngx_http_variable_t ngx_http_ssi_vars[] = {
|
|||
static ngx_int_t
|
||||
ngx_http_ssi_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_http_ssi_ctx_t *ctx;
|
||||
ngx_http_ssi_ctx_t *ctx, *mctx;
|
||||
ngx_http_ssi_loc_conf_t *slcf;
|
||||
|
||||
slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
|
||||
|
|
@ -341,6 +341,8 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
|
|||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
|
||||
|
||||
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t));
|
||||
if (ctx == NULL) {
|
||||
return NGX_ERROR;
|
||||
|
|
@ -367,6 +369,26 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
|
|||
r->filter_need_in_memory = 1;
|
||||
|
||||
if (r == r->main) {
|
||||
|
||||
if (mctx) {
|
||||
|
||||
/*
|
||||
* if there was a shared context previously used as main,
|
||||
* copy variables and blocks
|
||||
*/
|
||||
|
||||
ctx->variables = mctx->variables;
|
||||
ctx->blocks = mctx->blocks;
|
||||
|
||||
#if (NGX_PCRE)
|
||||
ctx->ncaptures = mctx->ncaptures;
|
||||
ctx->captures = mctx->captures;
|
||||
ctx->captures_data = mctx->captures_data;
|
||||
#endif
|
||||
|
||||
mctx->shared = 0;
|
||||
}
|
||||
|
||||
ngx_http_clear_content_length(r);
|
||||
ngx_http_clear_accept_ranges(r);
|
||||
|
||||
|
|
@ -379,6 +401,10 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
|
|||
} else {
|
||||
ngx_http_weak_etag(r);
|
||||
}
|
||||
|
||||
} else if (mctx == NULL) {
|
||||
ngx_http_set_ctx(r->main, ctx, ngx_http_ssi_filter_module);
|
||||
ctx->shared = 1;
|
||||
}
|
||||
|
||||
return ngx_http_next_header_filter(r);
|
||||
|
|
@ -405,6 +431,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
|
||||
|
||||
if (ctx == NULL
|
||||
|| (ctx->shared && r == r->main)
|
||||
|| (in == NULL
|
||||
&& ctx->buf == NULL
|
||||
&& ctx->in == NULL
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ typedef struct {
|
|||
u_char *captures_data;
|
||||
#endif
|
||||
|
||||
unsigned shared:1;
|
||||
unsigned conditional:2;
|
||||
unsigned encoding:2;
|
||||
unsigned block:1;
|
||||
|
|
|
|||
|
|
@ -632,8 +632,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
||||
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
|
||||
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
|
||||
(NGX_CONF_BITMASK_SET
|
||||
|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
|
||||
|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
||||
|
||||
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
|
||||
NGX_SSL_BUFSIZE);
|
||||
|
|
@ -1093,7 +1094,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
len++;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
if (len == 0 || j == value[i].len) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
|
|
@ -1183,7 +1184,7 @@ ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
len++;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
if (len == 0 || j == value[1].len) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->next = NULL;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
r->headers_out.location->value.len = len;
|
||||
r->headers_out.location->value.data = location;
|
||||
|
|
@ -237,10 +238,6 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (r != r->main && of.size == 0) {
|
||||
return ngx_http_send_header(r);
|
||||
}
|
||||
|
||||
r->allow_ranges = 1;
|
||||
|
||||
/* we need to allocate all before the header would be sent */
|
||||
|
|
@ -264,9 +261,10 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||
b->file_pos = 0;
|
||||
b->file_last = of.size;
|
||||
|
||||
b->in_file = b->file_last ? 1: 0;
|
||||
b->last_buf = (r == r->main) ? 1: 0;
|
||||
b->in_file = b->file_last ? 1 : 0;
|
||||
b->last_buf = (r == r->main) ? 1 : 0;
|
||||
b->last_in_chain = 1;
|
||||
b->sync = (b->last_buf || b->in_file) ? 0 : 1;
|
||||
|
||||
b->file->fd = of.fd;
|
||||
b->file->name = path;
|
||||
|
|
|
|||
|
|
@ -319,10 +319,9 @@ ngx_http_userid_set_variable(ngx_http_request_t *r,
|
|||
static ngx_http_userid_ctx_t *
|
||||
ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf)
|
||||
{
|
||||
ngx_int_t n;
|
||||
ngx_str_t src, dst;
|
||||
ngx_table_elt_t **cookies;
|
||||
ngx_http_userid_ctx_t *ctx;
|
||||
ngx_str_t src, dst;
|
||||
ngx_table_elt_t *cookie;
|
||||
ngx_http_userid_ctx_t *ctx;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
|
||||
|
||||
|
|
@ -339,9 +338,9 @@ ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf)
|
|||
ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module);
|
||||
}
|
||||
|
||||
n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name,
|
||||
&ctx->cookie);
|
||||
if (n == NGX_DECLINED) {
|
||||
cookie = ngx_http_parse_multi_header_lines(r, r->headers_in.cookie,
|
||||
&conf->name, &ctx->cookie);
|
||||
if (cookie == NULL) {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
@ -349,10 +348,9 @@ ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf)
|
|||
"uid cookie: \"%V\"", &ctx->cookie);
|
||||
|
||||
if (ctx->cookie.len < 22) {
|
||||
cookies = r->headers_in.cookies.elts;
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent too short userid cookie \"%V\"",
|
||||
&cookies[n]->value);
|
||||
&cookie->value);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
@ -370,10 +368,9 @@ ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf)
|
|||
dst.data = (u_char *) ctx->uid_got;
|
||||
|
||||
if (ngx_decode_base64(&dst, &src) == NGX_ERROR) {
|
||||
cookies = r->headers_in.cookies.elts;
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent invalid userid cookie \"%V\"",
|
||||
&cookies[n]->value);
|
||||
&cookie->value);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf,
|
|||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post,
|
||||
void *data);
|
||||
static ngx_int_t ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf,
|
||||
ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev);
|
||||
static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
|
||||
ngx_http_uwsgi_loc_conf_t *uwcf);
|
||||
#endif
|
||||
|
|
@ -668,7 +670,7 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
|
|||
if (uwcf->uwsgi_lengths == NULL) {
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
u->ssl = (uwcf->upstream.ssl != NULL);
|
||||
u->ssl = uwcf->ssl;
|
||||
|
||||
if (u->ssl) {
|
||||
ngx_str_set(&u->schema, "suwsgi://");
|
||||
|
|
@ -845,13 +847,13 @@ ngx_http_uwsgi_create_key(ngx_http_request_t *r)
|
|||
static ngx_int_t
|
||||
ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
||||
{
|
||||
u_char ch, *lowcase_key;
|
||||
u_char ch, sep, *lowcase_key;
|
||||
size_t key_len, val_len, len, allocated;
|
||||
ngx_uint_t i, n, hash, skip_empty, header_params;
|
||||
ngx_buf_t *b;
|
||||
ngx_chain_t *cl, *body;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *header, **ignored;
|
||||
ngx_table_elt_t *header, *hn, **ignored;
|
||||
ngx_http_uwsgi_params_t *params;
|
||||
ngx_http_script_code_pt code;
|
||||
ngx_http_script_engine_t e, le;
|
||||
|
|
@ -905,7 +907,11 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
|||
allocated = 0;
|
||||
lowcase_key = NULL;
|
||||
|
||||
if (params->number) {
|
||||
if (ngx_http_link_multi_headers(r) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (params->number || r->headers_in.multi) {
|
||||
n = 0;
|
||||
part = &r->headers_in.headers.part;
|
||||
|
||||
|
|
@ -935,6 +941,12 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
for (n = 0; n < header_params; n++) {
|
||||
if (&header[i] == ignored[n]) {
|
||||
goto next_length;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->number) {
|
||||
if (allocated < header[i].key.len) {
|
||||
allocated = header[i].key.len + 16;
|
||||
|
|
@ -968,6 +980,15 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
|||
|
||||
len += 2 + sizeof("HTTP_") - 1 + header[i].key.len
|
||||
+ 2 + header[i].value.len;
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
len += hn->value.len + 2;
|
||||
ignored[header_params++] = hn;
|
||||
}
|
||||
|
||||
next_length:
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1086,7 +1107,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
|||
|
||||
for (n = 0; n < header_params; n++) {
|
||||
if (&header[i] == ignored[n]) {
|
||||
goto next;
|
||||
goto next_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1109,15 +1130,41 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
val_len = header[i].value.len;
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
val_len += hn->value.len + 2;
|
||||
}
|
||||
|
||||
*b->last++ = (u_char) (val_len & 0xff);
|
||||
*b->last++ = (u_char) ((val_len >> 8) & 0xff);
|
||||
b->last = ngx_copy(b->last, header[i].value.data, val_len);
|
||||
b->last = ngx_copy(b->last, header[i].value.data,
|
||||
header[i].value.len);
|
||||
|
||||
if (header[i].next) {
|
||||
|
||||
if (header[i].key.len == sizeof("Cookie") - 1
|
||||
&& ngx_strncasecmp(header[i].key.data, (u_char *) "Cookie",
|
||||
sizeof("Cookie") - 1)
|
||||
== 0)
|
||||
{
|
||||
sep = ';';
|
||||
|
||||
} else {
|
||||
sep = ',';
|
||||
}
|
||||
|
||||
for (hn = header[i].next; hn; hn = hn->next) {
|
||||
*b->last++ = sep;
|
||||
*b->last++ = ' ';
|
||||
b->last = ngx_copy(b->last, hn->value.data, hn->value.len);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"uwsgi param: \"%*s: %*s\"",
|
||||
key_len, b->last - (key_len + 2 + val_len),
|
||||
val_len, b->last - val_len);
|
||||
next:
|
||||
next_value:
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1295,8 +1342,12 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
|
|||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
if (hh) {
|
||||
rc = hh->handler(r, h, hh->offset);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
|
@ -1816,12 +1867,17 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
if (ngx_http_uwsgi_merge_ssl(cf, conf, prev) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
|
||||
prev->upstream.ssl_session_reuse, 1);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
|
||||
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
|
||||
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
|
||||
(NGX_CONF_BITMASK_SET
|
||||
|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
|
||||
|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
|
||||
"DEFAULT");
|
||||
|
|
@ -1878,7 +1934,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
conf->uwsgi_values = prev->uwsgi_values;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
conf->upstream.ssl = prev->upstream.ssl;
|
||||
conf->ssl = prev->ssl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -2405,18 +2461,64 @@ ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
|
||||
ngx_http_uwsgi_loc_conf_t *prev)
|
||||
{
|
||||
ngx_uint_t preserve;
|
||||
|
||||
if (conf->ssl_protocols == 0
|
||||
&& conf->ssl_ciphers.data == NULL
|
||||
&& conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
|
||||
&& conf->upstream.ssl_verify == NGX_CONF_UNSET
|
||||
&& conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
|
||||
&& conf->ssl_trusted_certificate.data == NULL
|
||||
&& conf->ssl_crl.data == NULL
|
||||
&& conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
|
||||
&& conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
|
||||
{
|
||||
if (prev->upstream.ssl) {
|
||||
conf->upstream.ssl = prev->upstream.ssl;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
preserve = 1;
|
||||
|
||||
} else {
|
||||
preserve = 0;
|
||||
}
|
||||
|
||||
conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
|
||||
if (conf->upstream.ssl == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
conf->upstream.ssl->log = cf->log;
|
||||
|
||||
/*
|
||||
* special handling to preserve conf->upstream.ssl
|
||||
* in the "http" section to inherit it to all servers
|
||||
*/
|
||||
|
||||
if (preserve) {
|
||||
prev->upstream.ssl = conf->upstream.ssl;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
|
||||
{
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
|
||||
if (uwcf->upstream.ssl == NULL) {
|
||||
return NGX_ERROR;
|
||||
if (uwcf->upstream.ssl->ctx) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
uwcf->upstream.ssl->log = cf->log;
|
||||
|
||||
if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
|
||||
!= NGX_OK)
|
||||
{
|
||||
|
|
@ -2438,8 +2540,9 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (uwcf->upstream.ssl_certificate) {
|
||||
|
||||
if (uwcf->upstream.ssl_certificate
|
||||
&& uwcf->upstream.ssl_certificate->value.len)
|
||||
{
|
||||
if (uwcf->upstream.ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"uwsgi_ssl_certificate_key\" is defined "
|
||||
|
|
|
|||
|
|
@ -269,10 +269,9 @@ header_in(r, key)
|
|||
u_char *p, *lowcase_key, *value, sep;
|
||||
STRLEN len;
|
||||
ssize_t size;
|
||||
ngx_uint_t i, n, hash;
|
||||
ngx_array_t *a;
|
||||
ngx_uint_t i, hash;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *h, **ph;
|
||||
ngx_table_elt_t *h, *header, **ph;
|
||||
ngx_http_header_t *hh;
|
||||
ngx_http_core_main_conf_t *cmcf;
|
||||
|
||||
|
|
@ -302,78 +301,23 @@ header_in(r, key)
|
|||
|
||||
if (hh) {
|
||||
|
||||
if (hh->offset == offsetof(ngx_http_headers_in_t, cookies)) {
|
||||
if (hh->offset == offsetof(ngx_http_headers_in_t, cookie)) {
|
||||
sep = ';';
|
||||
goto multi;
|
||||
}
|
||||
#if (NGX_HTTP_X_FORWARDED_FOR)
|
||||
if (hh->offset == offsetof(ngx_http_headers_in_t, x_forwarded_for)) {
|
||||
|
||||
} else {
|
||||
sep = ',';
|
||||
goto multi;
|
||||
}
|
||||
#endif
|
||||
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
|
||||
|
||||
if (*ph) {
|
||||
ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
|
||||
multi:
|
||||
|
||||
/* Cookie, X-Forwarded-For */
|
||||
|
||||
a = (ngx_array_t *) ((char *) &r->headers_in + hh->offset);
|
||||
|
||||
n = a->nelts;
|
||||
|
||||
if (n == 0) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
ph = a->elts;
|
||||
|
||||
if (n == 1) {
|
||||
ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
size = - (ssize_t) (sizeof("; ") - 1);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
size += ph[i]->value.len + sizeof("; ") - 1;
|
||||
}
|
||||
|
||||
value = ngx_pnalloc(r->pool, size);
|
||||
if (value == NULL) {
|
||||
ctx->error = 1;
|
||||
croak("ngx_pnalloc() failed");
|
||||
}
|
||||
|
||||
p = value;
|
||||
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
p = ngx_copy(p, ph[i]->value.data, ph[i]->value.len);
|
||||
|
||||
if (i == n - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
*p++ = sep; *p++ = ' ';
|
||||
}
|
||||
|
||||
ngx_http_perl_set_targ(value, size);
|
||||
|
||||
goto done;
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* iterate over all headers */
|
||||
|
||||
sep = ',';
|
||||
ph = &header;
|
||||
|
||||
part = &r->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
|
||||
|
|
@ -395,12 +339,49 @@ header_in(r, key)
|
|||
continue;
|
||||
}
|
||||
|
||||
ngx_http_perl_set_targ(h[i].value.data, h[i].value.len);
|
||||
*ph = &h[i];
|
||||
ph = &h[i].next;
|
||||
}
|
||||
|
||||
*ph = NULL;
|
||||
ph = &header;
|
||||
|
||||
found:
|
||||
|
||||
if (*ph == NULL) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
if ((*ph)->next == NULL) {
|
||||
ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
|
||||
goto done;
|
||||
}
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
size = - (ssize_t) (sizeof("; ") - 1);
|
||||
|
||||
for (h = *ph; h; h = h->next) {
|
||||
size += h->value.len + sizeof("; ") - 1;
|
||||
}
|
||||
|
||||
value = ngx_pnalloc(r->pool, size);
|
||||
if (value == NULL) {
|
||||
ctx->error = 1;
|
||||
croak("ngx_pnalloc() failed");
|
||||
}
|
||||
|
||||
p = value;
|
||||
|
||||
for (h = *ph; h; h = h->next) {
|
||||
p = ngx_copy(p, h->value.data, h->value.len);
|
||||
|
||||
if (h->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
*p++ = sep; *p++ = ' ';
|
||||
}
|
||||
|
||||
ngx_http_perl_set_targ(value, size);
|
||||
|
||||
done:
|
||||
|
||||
|
|
@ -591,6 +572,7 @@ header_out(r, key, value)
|
|||
}
|
||||
|
||||
header->hash = 1;
|
||||
header->next = NULL;
|
||||
|
||||
if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) {
|
||||
header->hash = 0;
|
||||
|
|
|
|||
|
|
@ -1130,7 +1130,7 @@ ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
|
|||
node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
|
||||
|| (lq->inclusive && lq->inclusive->auto_redirect));
|
||||
|
||||
node->len = (u_char) len;
|
||||
node->len = (u_short) len;
|
||||
ngx_memcpy(node->name, &lq->name->data[prefix], len);
|
||||
|
||||
ngx_queue_split(locations, q, &tail);
|
||||
|
|
@ -1228,7 +1228,8 @@ static ngx_int_t
|
|||
ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
||||
ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
|
||||
{
|
||||
ngx_uint_t i, default_server, proxy_protocol;
|
||||
ngx_uint_t i, default_server, proxy_protocol,
|
||||
protocols, protocols_prev;
|
||||
ngx_http_conf_addr_t *addr;
|
||||
#if (NGX_HTTP_SSL)
|
||||
ngx_uint_t ssl;
|
||||
|
|
@ -1264,12 +1265,18 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
default_server = addr[i].opt.default_server;
|
||||
|
||||
proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol;
|
||||
protocols = lsopt->proxy_protocol;
|
||||
protocols_prev = addr[i].opt.proxy_protocol;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
ssl = lsopt->ssl || addr[i].opt.ssl;
|
||||
protocols |= lsopt->ssl << 1;
|
||||
protocols_prev |= addr[i].opt.ssl << 1;
|
||||
#endif
|
||||
#if (NGX_HTTP_V2)
|
||||
http2 = lsopt->http2 || addr[i].opt.http2;
|
||||
protocols |= lsopt->http2 << 2;
|
||||
protocols_prev |= addr[i].opt.http2 << 2;
|
||||
#endif
|
||||
|
||||
if (lsopt->set) {
|
||||
|
|
@ -1299,6 +1306,57 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
addr[i].default_server = cscf;
|
||||
}
|
||||
|
||||
/* check for conflicting protocol options */
|
||||
|
||||
if ((protocols | protocols_prev) != protocols_prev) {
|
||||
|
||||
/* options added */
|
||||
|
||||
if ((addr[i].opt.set && !lsopt->set)
|
||||
|| addr[i].protocols_changed
|
||||
|| (protocols | protocols_prev) != protocols)
|
||||
{
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"protocol options redefined for %V",
|
||||
&addr[i].opt.addr_text);
|
||||
}
|
||||
|
||||
addr[i].protocols = protocols_prev;
|
||||
addr[i].protocols_set = 1;
|
||||
addr[i].protocols_changed = 1;
|
||||
|
||||
} else if ((protocols_prev | protocols) != protocols) {
|
||||
|
||||
/* options removed */
|
||||
|
||||
if (lsopt->set
|
||||
|| (addr[i].protocols_set && protocols != addr[i].protocols))
|
||||
{
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"protocol options redefined for %V",
|
||||
&addr[i].opt.addr_text);
|
||||
}
|
||||
|
||||
addr[i].protocols = protocols;
|
||||
addr[i].protocols_set = 1;
|
||||
addr[i].protocols_changed = 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* the same options */
|
||||
|
||||
if ((lsopt->set && addr[i].protocols_changed)
|
||||
|| (addr[i].protocols_set && protocols != addr[i].protocols))
|
||||
{
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"protocol options redefined for %V",
|
||||
&addr[i].opt.addr_text);
|
||||
}
|
||||
|
||||
addr[i].protocols = protocols;
|
||||
addr[i].protocols_set = 1;
|
||||
}
|
||||
|
||||
addr[i].opt.default_server = default_server;
|
||||
addr[i].opt.proxy_protocol = proxy_protocol;
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
|
@ -1355,6 +1413,9 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
}
|
||||
|
||||
addr->opt = *lsopt;
|
||||
addr->protocols = 0;
|
||||
addr->protocols_set = 0;
|
||||
addr->protocols_changed = 0;
|
||||
addr->hash.buckets = NULL;
|
||||
addr->hash.size = 0;
|
||||
addr->wc_head = NULL;
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
|
|||
ngx_str_t *args, ngx_uint_t *flags);
|
||||
ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
||||
ngx_uint_t allow_underscores);
|
||||
ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers,
|
||||
ngx_str_t *name, ngx_str_t *value);
|
||||
ngx_int_t ngx_http_parse_set_cookie_lines(ngx_array_t *headers,
|
||||
ngx_str_t *name, ngx_str_t *value);
|
||||
ngx_table_elt_t *ngx_http_parse_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *headers, ngx_str_t *name, ngx_str_t *value);
|
||||
ngx_table_elt_t *ngx_http_parse_set_cookie_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *headers, ngx_str_t *name, ngx_str_t *value);
|
||||
ngx_int_t ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len,
|
||||
ngx_str_t *value);
|
||||
void ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri,
|
||||
|
|
|
|||
|
|
@ -1007,6 +1007,7 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->next = NULL;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
|
||||
if (r->args.len == 0) {
|
||||
|
|
@ -1087,6 +1088,7 @@ ngx_int_t
|
|||
ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
if (r != r->main) {
|
||||
|
|
@ -1121,8 +1123,8 @@ ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
|
|||
if (rc == NGX_OK) {
|
||||
r->access_code = 0;
|
||||
|
||||
if (r->headers_out.www_authenticate) {
|
||||
r->headers_out.www_authenticate->hash = 0;
|
||||
for (h = r->headers_out.www_authenticate; h; h = h->next) {
|
||||
h->hash = 0;
|
||||
}
|
||||
|
||||
r->phase_handler = ph->next;
|
||||
|
|
@ -1687,6 +1689,7 @@ ngx_http_set_etag(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
etag->hash = 1;
|
||||
etag->next = NULL;
|
||||
ngx_str_set(&etag->key, "ETag");
|
||||
|
||||
etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
|
||||
|
|
@ -1781,6 +1784,7 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
|
|||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->next = NULL;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
r->headers_out.location->value = val;
|
||||
|
||||
|
|
@ -1799,10 +1803,6 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
|
|||
}
|
||||
}
|
||||
|
||||
if (r != r->main && val.len == 0) {
|
||||
return ngx_http_send_header(r);
|
||||
}
|
||||
|
||||
b = ngx_calloc_buf(r->pool);
|
||||
if (b == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
|
|
@ -1813,6 +1813,7 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
|
|||
b->memory = val.len ? 1 : 0;
|
||||
b->last_buf = (r == r->main) ? 1 : 0;
|
||||
b->last_in_chain = 1;
|
||||
b->sync = (b->last_buf || b->memory) ? 0 : 1;
|
||||
|
||||
out.buf = b;
|
||||
out.next = NULL;
|
||||
|
|
@ -2024,8 +2025,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
|
|||
{
|
||||
time_t date, expires;
|
||||
ngx_uint_t p;
|
||||
ngx_array_t *cc;
|
||||
ngx_table_elt_t *e, *d, *ae;
|
||||
ngx_table_elt_t *e, *d, *ae, *cc;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
r->gzip_tested = 1;
|
||||
|
|
@ -2118,30 +2118,30 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
|
|||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
cc = &r->headers_out.cache_control;
|
||||
cc = r->headers_out.cache_control;
|
||||
|
||||
if (cc->elts) {
|
||||
if (cc) {
|
||||
|
||||
if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
|
||||
&& ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
|
||||
&& ngx_http_parse_multi_header_lines(r, cc, &ngx_http_gzip_no_cache,
|
||||
NULL)
|
||||
>= 0)
|
||||
!= NULL)
|
||||
{
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
|
||||
&& ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
|
||||
&& ngx_http_parse_multi_header_lines(r, cc, &ngx_http_gzip_no_store,
|
||||
NULL)
|
||||
>= 0)
|
||||
!= NULL)
|
||||
{
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
|
||||
&& ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
|
||||
&& ngx_http_parse_multi_header_lines(r, cc, &ngx_http_gzip_private,
|
||||
NULL)
|
||||
>= 0)
|
||||
!= NULL)
|
||||
{
|
||||
goto ok;
|
||||
}
|
||||
|
|
@ -2712,12 +2712,12 @@ ngx_http_set_disable_symlinks(ngx_http_request_t *r,
|
|||
|
||||
ngx_int_t
|
||||
ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
|
||||
ngx_array_t *headers, ngx_str_t *value, ngx_array_t *proxies,
|
||||
ngx_table_elt_t *headers, ngx_str_t *value, ngx_array_t *proxies,
|
||||
int recursive)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t i, found;
|
||||
ngx_table_elt_t **h;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t found;
|
||||
ngx_table_elt_t *h, *next;
|
||||
|
||||
if (headers == NULL) {
|
||||
return ngx_http_get_forwarded_addr_internal(r, addr, value->data,
|
||||
|
|
@ -2725,16 +2725,23 @@ ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
|
|||
recursive);
|
||||
}
|
||||
|
||||
i = headers->nelts;
|
||||
h = headers->elts;
|
||||
/* revert headers order */
|
||||
|
||||
for (h = headers, headers = NULL; h; h = next) {
|
||||
next = h->next;
|
||||
h->next = headers;
|
||||
headers = h;
|
||||
}
|
||||
|
||||
/* iterate over all headers in reverse order */
|
||||
|
||||
rc = NGX_DECLINED;
|
||||
|
||||
found = 0;
|
||||
|
||||
while (i-- > 0) {
|
||||
rc = ngx_http_get_forwarded_addr_internal(r, addr, h[i]->value.data,
|
||||
h[i]->value.len, proxies,
|
||||
for (h = headers; h; h = h->next) {
|
||||
rc = ngx_http_get_forwarded_addr_internal(r, addr, h->value.data,
|
||||
h->value.len, proxies,
|
||||
recursive);
|
||||
|
||||
if (!recursive) {
|
||||
|
|
@ -2753,6 +2760,14 @@ ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
|
|||
found = 1;
|
||||
}
|
||||
|
||||
/* restore headers order */
|
||||
|
||||
for (h = headers, headers = NULL; h; h = next) {
|
||||
next = h->next;
|
||||
h->next = headers;
|
||||
headers = h;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -2802,6 +2817,80 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
|
|||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_link_multi_headers(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_uint_t i, j;
|
||||
ngx_list_part_t *part, *ppart;
|
||||
ngx_table_elt_t *header, *pheader, **ph;
|
||||
|
||||
if (r->headers_in.multi_linked) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
r->headers_in.multi_linked = 1;
|
||||
|
||||
part = &r->headers_in.headers.part;
|
||||
header = part->elts;
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
|
||||
if (i >= part->nelts) {
|
||||
if (part->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
part = part->next;
|
||||
header = part->elts;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
header[i].next = NULL;
|
||||
|
||||
/*
|
||||
* search for previous headers with the same name;
|
||||
* if there are any, link to them
|
||||
*/
|
||||
|
||||
ppart = &r->headers_in.headers.part;
|
||||
pheader = ppart->elts;
|
||||
|
||||
for (j = 0; /* void */; j++) {
|
||||
|
||||
if (j >= ppart->nelts) {
|
||||
if (ppart->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
ppart = ppart->next;
|
||||
pheader = ppart->elts;
|
||||
j = 0;
|
||||
}
|
||||
|
||||
if (part == ppart && i == j) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (header[i].key.len == pheader[j].key.len
|
||||
&& ngx_strncasecmp(header[i].key.data, pheader[j].key.data,
|
||||
header[i].key.len)
|
||||
== 0)
|
||||
{
|
||||
ph = &pheader[j].next;
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
*ph = &header[i];
|
||||
|
||||
r->headers_in.multi = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
|
||||
{
|
||||
|
|
@ -3871,7 +3960,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
ngx_str_t *value, size;
|
||||
ngx_url_t u;
|
||||
ngx_uint_t n;
|
||||
ngx_uint_t n, i;
|
||||
ngx_http_listen_opt_t lsopt;
|
||||
|
||||
cscf->listen = 1;
|
||||
|
|
@ -4197,6 +4286,16 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
}
|
||||
|
||||
for (n = 0; n < u.naddrs; n++) {
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
|
||||
u.addrs[i].sockaddr, u.addrs[i].socklen, 1)
|
||||
== NGX_OK)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
lsopt.sockaddr = u.addrs[n].sockaddr;
|
||||
lsopt.socklen = u.addrs[n].socklen;
|
||||
lsopt.addr_text = u.addrs[n].name;
|
||||
|
|
@ -4205,6 +4304,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
next:
|
||||
continue;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
|
|
|||
|
|
@ -274,6 +274,10 @@ typedef struct {
|
|||
typedef struct {
|
||||
ngx_http_listen_opt_t opt;
|
||||
|
||||
unsigned protocols:3;
|
||||
unsigned protocols_set:1;
|
||||
unsigned protocols_changed:1;
|
||||
|
||||
ngx_hash_t hash;
|
||||
ngx_hash_wildcard_t *wc_head;
|
||||
ngx_hash_wildcard_t *wc_tail;
|
||||
|
|
@ -463,8 +467,8 @@ struct ngx_http_location_tree_node_s {
|
|||
ngx_http_core_loc_conf_t *exact;
|
||||
ngx_http_core_loc_conf_t *inclusive;
|
||||
|
||||
u_short len;
|
||||
u_char auto_redirect;
|
||||
u_char len;
|
||||
u_char name[1];
|
||||
};
|
||||
|
||||
|
|
@ -529,9 +533,11 @@ ngx_int_t ngx_http_set_disable_symlinks(ngx_http_request_t *r,
|
|||
ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of);
|
||||
|
||||
ngx_int_t ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
|
||||
ngx_array_t *headers, ngx_str_t *value, ngx_array_t *proxies,
|
||||
ngx_table_elt_t *headers, ngx_str_t *value, ngx_array_t *proxies,
|
||||
int recursive);
|
||||
|
||||
ngx_int_t ngx_http_link_multi_headers(ngx_http_request_t *r);
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_core_module;
|
||||
|
||||
|
|
|
|||
|
|
@ -1575,10 +1575,6 @@ ngx_http_cache_send(ngx_http_request_t *r)
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http file cache send: %s", c->file.name.data);
|
||||
|
||||
if (r != r->main && c->length - c->body_start == 0) {
|
||||
return ngx_http_send_header(r);
|
||||
}
|
||||
|
||||
/* we need to allocate all before the header would be sent */
|
||||
|
||||
b = ngx_calloc_buf(r->pool);
|
||||
|
|
@ -1600,9 +1596,10 @@ ngx_http_cache_send(ngx_http_request_t *r)
|
|||
b->file_pos = c->body_start;
|
||||
b->file_last = c->length;
|
||||
|
||||
b->in_file = (c->length - c->body_start) ? 1: 0;
|
||||
b->last_buf = (r == r->main) ? 1: 0;
|
||||
b->in_file = (c->length - c->body_start) ? 1 : 0;
|
||||
b->last_buf = (r == r->main) ? 1 : 0;
|
||||
b->last_in_chain = 1;
|
||||
b->sync = (b->last_buf || b->in_file) ? 0 : 1;
|
||||
|
||||
b->file->fd = c->file.fd;
|
||||
b->file->name = c->file.name;
|
||||
|
|
@ -1756,6 +1753,11 @@ ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache)
|
|||
break;
|
||||
}
|
||||
|
||||
if (fcn->deleting) {
|
||||
wait = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
|
||||
sizeof(ngx_rbtree_key_t));
|
||||
len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
|
||||
|
|
|
|||
|
|
@ -1960,27 +1960,24 @@ unsafe:
|
|||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
|
||||
ngx_str_t *value)
|
||||
ngx_table_elt_t *
|
||||
ngx_http_parse_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *headers, ngx_str_t *name, ngx_str_t *value)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
u_char *start, *last, *end, ch;
|
||||
ngx_table_elt_t **h;
|
||||
u_char *start, *last, *end, ch;
|
||||
ngx_table_elt_t *h;
|
||||
|
||||
h = headers->elts;
|
||||
for (h = headers; h; h = h->next) {
|
||||
|
||||
for (i = 0; i < headers->nelts; i++) {
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"parse header: \"%V: %V\"", &h->key, &h->value);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, headers->pool->log, 0,
|
||||
"parse header: \"%V: %V\"", &h[i]->key, &h[i]->value);
|
||||
|
||||
if (name->len > h[i]->value.len) {
|
||||
if (name->len > h->value.len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
start = h[i]->value.data;
|
||||
end = h[i]->value.data + h[i]->value.len;
|
||||
start = h->value.data;
|
||||
end = h->value.data + h->value.len;
|
||||
|
||||
while (start < end) {
|
||||
|
||||
|
|
@ -1994,7 +1991,7 @@ ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
|
|||
|
||||
if (value == NULL) {
|
||||
if (start == end || *start == ',') {
|
||||
return i;
|
||||
return h;
|
||||
}
|
||||
|
||||
goto skip;
|
||||
|
|
@ -2014,7 +2011,7 @@ ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
|
|||
value->len = last - start;
|
||||
value->data = start;
|
||||
|
||||
return i;
|
||||
return h;
|
||||
|
||||
skip:
|
||||
|
||||
|
|
@ -2029,31 +2026,28 @@ ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
|
|||
}
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_parse_set_cookie_lines(ngx_array_t *headers, ngx_str_t *name,
|
||||
ngx_str_t *value)
|
||||
ngx_table_elt_t *
|
||||
ngx_http_parse_set_cookie_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *headers, ngx_str_t *name, ngx_str_t *value)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
u_char *start, *last, *end;
|
||||
ngx_table_elt_t **h;
|
||||
u_char *start, *last, *end;
|
||||
ngx_table_elt_t *h;
|
||||
|
||||
h = headers->elts;
|
||||
for (h = headers; h; h = h->next) {
|
||||
|
||||
for (i = 0; i < headers->nelts; i++) {
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"parse header: \"%V: %V\"", &h->key, &h->value);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, headers->pool->log, 0,
|
||||
"parse header: \"%V: %V\"", &h[i]->key, &h[i]->value);
|
||||
|
||||
if (name->len >= h[i]->value.len) {
|
||||
if (name->len >= h->value.len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
start = h[i]->value.data;
|
||||
end = h[i]->value.data + h[i]->value.len;
|
||||
start = h->value.data;
|
||||
end = h->value.data + h->value.len;
|
||||
|
||||
if (ngx_strncasecmp(start, name->data, name->len) != 0) {
|
||||
continue;
|
||||
|
|
@ -2077,10 +2071,10 @@ ngx_http_parse_set_cookie_lines(ngx_array_t *headers, ngx_str_t *name,
|
|||
value->len = last - start;
|
||||
value->data = start;
|
||||
|
||||
return i;
|
||||
return h;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
|
|||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
|
||||
|
|
@ -164,7 +162,7 @@ ngx_http_header_t ngx_http_headers_in[] = {
|
|||
#if (NGX_HTTP_X_FORWARDED_FOR)
|
||||
{ ngx_string("X-Forwarded-For"),
|
||||
offsetof(ngx_http_headers_in_t, x_forwarded_for),
|
||||
ngx_http_process_multi_header_lines },
|
||||
ngx_http_process_header_line },
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_REALIP)
|
||||
|
|
@ -196,8 +194,8 @@ ngx_http_header_t ngx_http_headers_in[] = {
|
|||
ngx_http_process_header_line },
|
||||
#endif
|
||||
|
||||
{ ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
|
||||
ngx_http_process_multi_header_lines },
|
||||
{ ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookie),
|
||||
ngx_http_process_header_line },
|
||||
|
||||
{ ngx_null_string, 0, NULL }
|
||||
};
|
||||
|
|
@ -1742,9 +1740,10 @@ ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
|
||||
|
||||
if (*ph == NULL) {
|
||||
*ph = h;
|
||||
}
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -1760,6 +1759,7 @@ ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
|
||||
if (*ph == NULL) {
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1792,6 +1792,7 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
r->headers_in.host = h;
|
||||
h->next = NULL;
|
||||
|
||||
host = h->value;
|
||||
|
||||
|
|
@ -1827,6 +1828,10 @@ static ngx_int_t
|
|||
ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
if (ngx_http_process_header_line(r, h, offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
|
||||
r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
|
||||
|
||||
|
|
@ -1844,12 +1849,10 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
{
|
||||
u_char *user_agent, *msie;
|
||||
|
||||
if (r->headers_in.user_agent) {
|
||||
return NGX_OK;
|
||||
if (ngx_http_process_header_line(r, h, offset) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_in.user_agent = h;
|
||||
|
||||
/* check some widespread browsers while the header is in CPU cache */
|
||||
|
||||
user_agent = h->value.data;
|
||||
|
|
@ -1911,35 +1914,6 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
ngx_array_t *headers;
|
||||
ngx_table_elt_t **ph;
|
||||
|
||||
headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
|
||||
|
||||
if (headers->elts == NULL) {
|
||||
if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ph = ngx_array_push(headers);
|
||||
if (ph == NULL) {
|
||||
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ph = h;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_process_request_header(ngx_http_request_t *r)
|
||||
{
|
||||
|
|
@ -2779,7 +2753,8 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
|
|||
|| (clcf->lingering_close == NGX_HTTP_LINGERING_ON
|
||||
&& (r->lingering_close
|
||||
|| r->header_in->pos < r->header_in->last
|
||||
|| r->connection->read->ready)))
|
||||
|| r->connection->read->ready
|
||||
|| r->connection->pipeline)))
|
||||
{
|
||||
ngx_http_set_lingering_close(r->connection);
|
||||
return;
|
||||
|
|
@ -3149,6 +3124,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
|
|||
|
||||
c->sent = 0;
|
||||
c->destroyed = 0;
|
||||
c->pipeline = 1;
|
||||
|
||||
if (rev->timer_set) {
|
||||
ngx_del_timer(rev);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ typedef struct {
|
|||
ngx_table_elt_t *keep_alive;
|
||||
|
||||
#if (NGX_HTTP_X_FORWARDED_FOR)
|
||||
ngx_array_t x_forwarded_for;
|
||||
ngx_table_elt_t *x_forwarded_for;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_REALIP)
|
||||
|
|
@ -231,17 +231,19 @@ typedef struct {
|
|||
ngx_table_elt_t *date;
|
||||
#endif
|
||||
|
||||
ngx_table_elt_t *cookie;
|
||||
|
||||
ngx_str_t user;
|
||||
ngx_str_t passwd;
|
||||
|
||||
ngx_array_t cookies;
|
||||
|
||||
ngx_str_t server;
|
||||
off_t content_length_n;
|
||||
time_t keep_alive_n;
|
||||
|
||||
unsigned connection_type:2;
|
||||
unsigned chunked:1;
|
||||
unsigned multi:1;
|
||||
unsigned multi_linked:1;
|
||||
unsigned msie:1;
|
||||
unsigned msie6:1;
|
||||
unsigned opera:1;
|
||||
|
|
@ -272,6 +274,9 @@ typedef struct {
|
|||
ngx_table_elt_t *expires;
|
||||
ngx_table_elt_t *etag;
|
||||
|
||||
ngx_table_elt_t *cache_control;
|
||||
ngx_table_elt_t *link;
|
||||
|
||||
ngx_str_t *override_charset;
|
||||
|
||||
size_t content_type_len;
|
||||
|
|
@ -280,9 +285,6 @@ typedef struct {
|
|||
u_char *content_type_lowcase;
|
||||
ngx_uint_t content_type_hash;
|
||||
|
||||
ngx_array_t cache_control;
|
||||
ngx_array_t link;
|
||||
|
||||
off_t content_length_n;
|
||||
off_t content_offset;
|
||||
time_t date_time;
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,7 @@ ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
|
|||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->next = NULL;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
r->headers_out.location->value = e->buf;
|
||||
|
||||
|
|
|
|||
|
|
@ -649,6 +649,7 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
|
|||
}
|
||||
|
||||
location->hash = 1;
|
||||
location->next = NULL;
|
||||
ngx_str_set(&location->key, "Location");
|
||||
location->value = uri;
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
|
|||
|
||||
static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
|
||||
|
|
@ -147,11 +150,6 @@ static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
|
|||
static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
#endif
|
||||
|
||||
static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
|
||||
static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
|
|
@ -231,7 +229,7 @@ static ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
|||
offsetof(ngx_http_headers_out_t, server), 0 },
|
||||
|
||||
{ ngx_string("WWW-Authenticate"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
ngx_http_upstream_process_multi_header_lines,
|
||||
offsetof(ngx_http_upstream_headers_in_t, www_authenticate),
|
||||
ngx_http_upstream_copy_header_line, 0, 0 },
|
||||
|
||||
|
|
@ -241,12 +239,13 @@ static ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
|||
ngx_http_upstream_rewrite_location, 0, 0 },
|
||||
|
||||
{ ngx_string("Refresh"),
|
||||
ngx_http_upstream_ignore_header_line, 0,
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, refresh),
|
||||
ngx_http_upstream_rewrite_refresh, 0, 0 },
|
||||
|
||||
{ ngx_string("Set-Cookie"),
|
||||
ngx_http_upstream_process_set_cookie,
|
||||
offsetof(ngx_http_upstream_headers_in_t, cookies),
|
||||
offsetof(ngx_http_upstream_headers_in_t, set_cookie),
|
||||
ngx_http_upstream_rewrite_set_cookie, 0, 1 },
|
||||
|
||||
{ ngx_string("Content-Disposition"),
|
||||
|
|
@ -264,8 +263,7 @@ static ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
|||
offsetof(ngx_http_headers_out_t, expires), 1 },
|
||||
|
||||
{ ngx_string("Accept-Ranges"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
|
||||
ngx_http_upstream_ignore_header_line, 0,
|
||||
ngx_http_upstream_copy_allow_ranges,
|
||||
offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
|
||||
|
||||
|
|
@ -316,12 +314,10 @@ static ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
|||
ngx_http_upstream_process_transfer_encoding, 0,
|
||||
ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
{ ngx_string("Content-Encoding"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, content_encoding),
|
||||
ngx_http_upstream_copy_content_encoding, 0, 0 },
|
||||
#endif
|
||||
ngx_http_upstream_ignore_header_line, 0,
|
||||
ngx_http_upstream_copy_header_line,
|
||||
offsetof(ngx_http_headers_out_t, content_encoding), 0 },
|
||||
|
||||
{ ngx_null_string, NULL, 0, NULL, 0, 0 }
|
||||
};
|
||||
|
|
@ -1694,8 +1690,10 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
|
|||
}
|
||||
}
|
||||
|
||||
if (u->conf->ssl_certificate && (u->conf->ssl_certificate->lengths
|
||||
|| u->conf->ssl_certificate_key->lengths))
|
||||
if (u->conf->ssl_certificate
|
||||
&& u->conf->ssl_certificate->value.len
|
||||
&& (u->conf->ssl_certificate->lengths
|
||||
|| u->conf->ssl_certificate_key->lengths))
|
||||
{
|
||||
if (ngx_http_upstream_ssl_certificate(r, u, c) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
|
|
@ -2651,7 +2649,7 @@ ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
|
|||
{
|
||||
ngx_int_t status;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_table_elt_t *h, *ho, **ph;
|
||||
ngx_http_err_page_t *err_page;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
|
|
@ -2680,23 +2678,36 @@ ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
|
|||
if (status == NGX_HTTP_UNAUTHORIZED
|
||||
&& u->headers_in.www_authenticate)
|
||||
{
|
||||
h = ngx_list_push(&r->headers_out.headers);
|
||||
h = u->headers_in.www_authenticate;
|
||||
ph = &r->headers_out.www_authenticate;
|
||||
|
||||
if (h == NULL) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
while (h) {
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
|
||||
if (ho == NULL) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return NGX_OK;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
*ph = ho;
|
||||
ph = &ho->next;
|
||||
|
||||
h = h->next;
|
||||
}
|
||||
|
||||
*h = *u->headers_in.www_authenticate;
|
||||
|
||||
r->headers_out.www_authenticate = h;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cache) {
|
||||
|
||||
if (u->headers_in.no_cache || u->headers_in.expired) {
|
||||
u->cacheable = 0;
|
||||
}
|
||||
|
||||
if (u->cacheable) {
|
||||
time_t valid;
|
||||
|
||||
|
|
@ -2791,6 +2802,10 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
|
||||
if (u->headers_in.no_cache || u->headers_in.expired) {
|
||||
u->cacheable = 0;
|
||||
}
|
||||
|
||||
if (u->headers_in.x_accel_redirect
|
||||
&& !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT))
|
||||
{
|
||||
|
|
@ -2811,6 +2826,10 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
if (h[i].hash == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
|
|
@ -2864,6 +2883,10 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
if (h[i].hash == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len))
|
||||
{
|
||||
|
|
@ -4615,10 +4638,36 @@ ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
|
||||
|
||||
if (*ph == NULL) {
|
||||
*ph = h;
|
||||
if (*ph) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\", ignored",
|
||||
&h->key, &h->value,
|
||||
&(*ph)->key, &(*ph)->value);
|
||||
h->hash = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_table_elt_t **ph;
|
||||
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
|
||||
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -4639,9 +4688,34 @@ ngx_http_upstream_process_content_length(ngx_http_request_t *r,
|
|||
|
||||
u = r->upstream;
|
||||
|
||||
if (u->headers_in.content_length) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\"",
|
||||
&h->key, &h->value,
|
||||
&u->headers_in.content_length->key,
|
||||
&u->headers_in.content_length->value);
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (u->headers_in.transfer_encoding) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent \"Content-Length\" and "
|
||||
"\"Transfer-Encoding\" headers at the same time");
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
h->next = NULL;
|
||||
u->headers_in.content_length = h;
|
||||
u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);
|
||||
|
||||
if (u->headers_in.content_length_n == NGX_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent invalid \"Content-Length\" header: "
|
||||
"\"%V: %V\"", &h->key, &h->value);
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -4654,6 +4728,18 @@ ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
|
|||
|
||||
u = r->upstream;
|
||||
|
||||
if (u->headers_in.last_modified) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\", ignored",
|
||||
&h->key, &h->value,
|
||||
&u->headers_in.last_modified->key,
|
||||
&u->headers_in.last_modified->value);
|
||||
h->hash = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
h->next = NULL;
|
||||
u->headers_in.last_modified = h;
|
||||
u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data,
|
||||
h->value.len);
|
||||
|
|
@ -4666,26 +4752,16 @@ static ngx_int_t
|
|||
ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
ngx_array_t *pa;
|
||||
ngx_table_elt_t **ph;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
pa = &u->headers_in.cookies;
|
||||
ph = &u->headers_in.set_cookie;
|
||||
|
||||
if (pa->elts == NULL) {
|
||||
if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ph = ngx_array_push(pa);
|
||||
if (ph == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
|
||||
|
|
@ -4701,26 +4777,16 @@ static ngx_int_t
|
|||
ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_array_t *pa;
|
||||
ngx_table_elt_t **ph;
|
||||
ngx_http_upstream_t *u;
|
||||
ngx_table_elt_t **ph;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
pa = &u->headers_in.cache_control;
|
||||
ph = &u->headers_in.cache_control;
|
||||
|
||||
if (pa->elts == NULL) {
|
||||
if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ph = ngx_array_push(pa);
|
||||
if (ph == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
{
|
||||
|
|
@ -4735,18 +4801,18 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
start = h->value.data;
|
||||
last = start + h->value.len;
|
||||
|
||||
if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) {
|
||||
goto extensions;
|
||||
}
|
||||
|
||||
if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL
|
||||
|| ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL
|
||||
|| ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL)
|
||||
{
|
||||
u->cacheable = 0;
|
||||
u->headers_in.no_cache = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -4776,13 +4842,16 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
if (n == 0) {
|
||||
u->cacheable = 0;
|
||||
u->headers_in.no_cache = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
r->cache->valid_sec = ngx_time() + n;
|
||||
u->headers_in.expired = 0;
|
||||
}
|
||||
|
||||
extensions:
|
||||
|
||||
p = ngx_strlcasestrn(start, last, (u_char *) "stale-while-revalidate=",
|
||||
23 - 1);
|
||||
|
||||
|
|
@ -4842,7 +4911,20 @@ ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
if (u->headers_in.expires) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\", ignored",
|
||||
&h->key, &h->value,
|
||||
&u->headers_in.expires->key,
|
||||
&u->headers_in.expires->value);
|
||||
h->hash = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
u->headers_in.expires = h;
|
||||
h->next = NULL;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
{
|
||||
|
|
@ -4863,7 +4945,7 @@ ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
expires = ngx_parse_http_time(h->value.data, h->value.len);
|
||||
|
||||
if (expires == NGX_ERROR || expires < ngx_time()) {
|
||||
u->cacheable = 0;
|
||||
u->headers_in.expired = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -4882,7 +4964,20 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
|
|||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
if (u->headers_in.x_accel_expires) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\", ignored",
|
||||
&h->key, &h->value,
|
||||
&u->headers_in.x_accel_expires->key,
|
||||
&u->headers_in.x_accel_expires->value);
|
||||
h->hash = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
u->headers_in.x_accel_expires = h;
|
||||
h->next = NULL;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
{
|
||||
|
|
@ -4914,6 +5009,8 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
|
|||
|
||||
default:
|
||||
r->cache->valid_sec = ngx_time() + n;
|
||||
u->headers_in.no_cache = 0;
|
||||
u->headers_in.expired = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -4925,6 +5022,8 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
|
|||
|
||||
if (n != NGX_ERROR) {
|
||||
r->cache->valid_sec = n;
|
||||
u->headers_in.no_cache = 0;
|
||||
u->headers_in.expired = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -4941,7 +5040,20 @@ ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
if (u->headers_in.x_accel_limit_rate) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\", ignored",
|
||||
&h->key, &h->value,
|
||||
&u->headers_in.x_accel_limit_rate->key,
|
||||
&u->headers_in.x_accel_limit_rate->value);
|
||||
h->hash = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
u->headers_in.x_accel_limit_rate = h;
|
||||
h->next = NULL;
|
||||
|
||||
if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) {
|
||||
return NGX_OK;
|
||||
|
|
@ -5000,7 +5112,11 @@ static ngx_int_t
|
|||
ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) {
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -5014,13 +5130,22 @@ static ngx_int_t
|
|||
ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
r->upstream->headers_in.connection = h;
|
||||
ngx_table_elt_t **ph;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
ph = &u->headers_in.connection;
|
||||
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
|
||||
(u_char *) "close", 5 - 1)
|
||||
!= NULL)
|
||||
{
|
||||
r->upstream->headers_in.connection_close = 1;
|
||||
u->headers_in.connection_close = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
|
@ -5031,13 +5156,40 @@ static ngx_int_t
|
|||
ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
r->upstream->headers_in.transfer_encoding = h;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
|
||||
(u_char *) "chunked", 7 - 1)
|
||||
!= NULL)
|
||||
u = r->upstream;
|
||||
|
||||
if (u->headers_in.transfer_encoding) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent duplicate header line: \"%V: %V\", "
|
||||
"previous value: \"%V: %V\"",
|
||||
&h->key, &h->value,
|
||||
&u->headers_in.transfer_encoding->key,
|
||||
&u->headers_in.transfer_encoding->value);
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (u->headers_in.content_length) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent \"Content-Length\" and "
|
||||
"\"Transfer-Encoding\" headers at the same time");
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
u->headers_in.transfer_encoding = h;
|
||||
h->next = NULL;
|
||||
|
||||
if (h->value.len == 7
|
||||
&& ngx_strncasecmp(h->value.data, (u_char *) "chunked", 7) == 0)
|
||||
{
|
||||
r->upstream->headers_in.chunked = 1;
|
||||
u->headers_in.chunked = 1;
|
||||
|
||||
} else {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent unknown \"Transfer-Encoding\": \"%V\"",
|
||||
&h->value);
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
|
@ -5048,29 +5200,74 @@ static ngx_int_t
|
|||
ngx_http_upstream_process_vary(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_http_upstream_t *u;
|
||||
ngx_table_elt_t **ph;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
u->headers_in.vary = h;
|
||||
ph = &u->headers_in.vary;
|
||||
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = h;
|
||||
h->next = NULL;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
ngx_str_t vary;
|
||||
|
||||
if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_VARY) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (r->cache == NULL) {
|
||||
if (r->cache == NULL || !u->cacheable) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (h->value.len > NGX_HTTP_CACHE_VARY_LEN
|
||||
|| (h->value.len == 1 && h->value.data[0] == '*'))
|
||||
{
|
||||
if (h->value.len == 1 && h->value.data[0] == '*') {
|
||||
u->cacheable = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (u->headers_in.vary->next) {
|
||||
|
||||
len = 0;
|
||||
|
||||
for (h = u->headers_in.vary; h; h = h->next) {
|
||||
len += h->value.len + 2;
|
||||
}
|
||||
|
||||
len -= 2;
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
vary.len = len;
|
||||
vary.data = p;
|
||||
|
||||
for (h = u->headers_in.vary; h; h = h->next) {
|
||||
p = ngx_copy(p, h->value.data, h->value.len);
|
||||
|
||||
if (h->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
*p++ = ','; *p++ = ' ';
|
||||
}
|
||||
|
||||
} else {
|
||||
vary = h->value;
|
||||
}
|
||||
|
||||
if (vary.len > NGX_HTTP_CACHE_VARY_LEN) {
|
||||
u->cacheable = 0;
|
||||
}
|
||||
|
||||
r->cache->vary = h->value;
|
||||
|
||||
r->cache->vary = vary;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
|
|
@ -5093,6 +5290,7 @@ ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
if (offset) {
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
|
||||
*ph = ho;
|
||||
ho->next = NULL;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
|
@ -5103,18 +5301,8 @@ static ngx_int_t
|
|||
ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_array_t *pa;
|
||||
ngx_table_elt_t *ho, **ph;
|
||||
|
||||
pa = (ngx_array_t *) ((char *) &r->headers_out + offset);
|
||||
|
||||
if (pa->elts == NULL) {
|
||||
if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
if (ho == NULL) {
|
||||
return NGX_ERROR;
|
||||
|
|
@ -5122,12 +5310,12 @@ ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
|
|||
|
||||
*ho = *h;
|
||||
|
||||
ph = ngx_array_push(pa);
|
||||
if (ph == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
|
||||
|
||||
while (*ph) { ph = &(*ph)->next; }
|
||||
|
||||
*ph = ho;
|
||||
ho->next = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -5197,6 +5385,7 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
r->headers_out.last_modified = ho;
|
||||
r->headers_out.last_modified_time =
|
||||
|
|
@ -5219,6 +5408,7 @@ ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
if (r->upstream->rewrite_redirect) {
|
||||
rc = r->upstream->rewrite_redirect(r, ho, 0);
|
||||
|
|
@ -5264,6 +5454,7 @@ ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
if (r->upstream->rewrite_redirect) {
|
||||
|
||||
|
|
@ -5309,6 +5500,7 @@ ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
if (r->upstream->rewrite_cookie) {
|
||||
rc = r->upstream->rewrite_cookie(r, ho);
|
||||
|
|
@ -5362,6 +5554,7 @@ ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
*ho = *h;
|
||||
ho->next = NULL;
|
||||
|
||||
r->headers_out.accept_ranges = ho;
|
||||
|
||||
|
|
@ -5369,29 +5562,6 @@ ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_table_elt_t *ho;
|
||||
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
if (ho == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ho = *h;
|
||||
|
||||
r->headers_out.content_encoding = ho;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_add_variables(ngx_conf_t *cf)
|
||||
{
|
||||
|
|
@ -5703,7 +5873,7 @@ ngx_http_upstream_header_variable(ngx_http_request_t *r,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
|
||||
return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
|
||||
&r->upstream->headers_in.headers.part,
|
||||
sizeof("upstream_http_") - 1);
|
||||
}
|
||||
|
|
@ -5718,7 +5888,7 @@ ngx_http_upstream_trailer_variable(ngx_http_request_t *r,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
|
||||
return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
|
||||
&r->upstream->headers_in.trailers.part,
|
||||
sizeof("upstream_trailer_") - 1);
|
||||
}
|
||||
|
|
@ -5740,9 +5910,9 @@ ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
|
|||
s.len = name->len - (sizeof("upstream_cookie_") - 1);
|
||||
s.data = name->data + sizeof("upstream_cookie_") - 1;
|
||||
|
||||
if (ngx_http_parse_set_cookie_lines(&r->upstream->headers_in.cookies,
|
||||
if (ngx_http_parse_set_cookie_lines(r, r->upstream->headers_in.set_cookie,
|
||||
&s, &cookie)
|
||||
== NGX_DECLINED)
|
||||
== NULL)
|
||||
{
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
|
|
|
|||
|
|
@ -280,23 +280,21 @@ typedef struct {
|
|||
|
||||
ngx_table_elt_t *last_modified;
|
||||
ngx_table_elt_t *location;
|
||||
ngx_table_elt_t *accept_ranges;
|
||||
ngx_table_elt_t *refresh;
|
||||
ngx_table_elt_t *www_authenticate;
|
||||
ngx_table_elt_t *transfer_encoding;
|
||||
ngx_table_elt_t *vary;
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
ngx_table_elt_t *content_encoding;
|
||||
#endif
|
||||
|
||||
ngx_array_t cache_control;
|
||||
ngx_array_t cookies;
|
||||
ngx_table_elt_t *cache_control;
|
||||
ngx_table_elt_t *set_cookie;
|
||||
|
||||
off_t content_length_n;
|
||||
time_t last_modified_time;
|
||||
|
||||
unsigned connection_close:1;
|
||||
unsigned chunked:1;
|
||||
unsigned no_cache:1;
|
||||
unsigned expired:1;
|
||||
} ngx_http_upstream_headers_in_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
|
|||
|
||||
static ngx_int_t ngx_http_variable_cookies(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data, u_char sep);
|
||||
|
||||
|
|
@ -63,6 +61,8 @@ static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
|
|||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
|
||||
|
|
@ -178,12 +178,12 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
|||
#endif
|
||||
|
||||
#if (NGX_HTTP_X_FORWARDED_FOR)
|
||||
{ ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
|
||||
{ ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header,
|
||||
offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
|
||||
#endif
|
||||
|
||||
{ ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
|
||||
offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
|
||||
offsetof(ngx_http_request_t, headers_in.cookie), 0, 0 },
|
||||
|
||||
{ ngx_string("content_length"), NULL, ngx_http_variable_content_length,
|
||||
0, 0, 0 },
|
||||
|
|
@ -216,6 +216,10 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
|||
ngx_http_variable_proxy_protocol_port,
|
||||
offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
|
||||
|
||||
{ ngx_string("proxy_protocol_tlv_"), NULL,
|
||||
ngx_http_variable_proxy_protocol_tlv,
|
||||
0, NGX_HTTP_VAR_PREFIX, 0 },
|
||||
|
||||
{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
|
||||
|
||||
{ ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
|
||||
|
|
@ -327,10 +331,10 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
|||
{ ngx_string("sent_http_transfer_encoding"), NULL,
|
||||
ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
|
||||
|
||||
{ ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
|
||||
{ ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_header,
|
||||
offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
|
||||
|
||||
{ ngx_string("sent_http_link"), NULL, ngx_http_variable_headers,
|
||||
{ ngx_string("sent_http_link"), NULL, ngx_http_variable_header,
|
||||
offsetof(ngx_http_request_t, headers_out.link), 0, 0 },
|
||||
|
||||
{ ngx_string("limit_rate"), ngx_http_variable_set_limit_rate,
|
||||
|
|
@ -807,22 +811,7 @@ static ngx_int_t
|
|||
ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||
uintptr_t data)
|
||||
{
|
||||
ngx_table_elt_t *h;
|
||||
|
||||
h = *(ngx_table_elt_t **) ((char *) r + data);
|
||||
|
||||
if (h) {
|
||||
v->len = h->value.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = h->value.data;
|
||||
|
||||
} else {
|
||||
v->not_found = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
return ngx_http_variable_headers_internal(r, v, data, ',');
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -834,38 +823,25 @@ ngx_http_variable_cookies(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_variable_headers(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
return ngx_http_variable_headers_internal(r, v, data, ',');
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_variable_headers_internal(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
|
||||
{
|
||||
size_t len;
|
||||
u_char *p, *end;
|
||||
ngx_uint_t i, n;
|
||||
ngx_array_t *a;
|
||||
ngx_table_elt_t **h;
|
||||
size_t len;
|
||||
u_char *p;
|
||||
ngx_table_elt_t *h, *th;
|
||||
|
||||
a = (ngx_array_t *) ((char *) r + data);
|
||||
|
||||
n = a->nelts;
|
||||
h = a->elts;
|
||||
h = *(ngx_table_elt_t **) ((char *) r + data);
|
||||
|
||||
len = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (th = h; th; th = th->next) {
|
||||
|
||||
if (h[i]->hash == 0) {
|
||||
if (th->hash == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
len += h[i]->value.len + 2;
|
||||
len += th->value.len + 2;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
|
|
@ -879,9 +855,9 @@ ngx_http_variable_headers_internal(ngx_http_request_t *r,
|
|||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
|
||||
if (n == 1) {
|
||||
v->len = (*h)->value.len;
|
||||
v->data = (*h)->value.data;
|
||||
if (h->next == NULL) {
|
||||
v->len = h->value.len;
|
||||
v->data = h->value.data;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -894,17 +870,15 @@ ngx_http_variable_headers_internal(ngx_http_request_t *r,
|
|||
v->len = len;
|
||||
v->data = p;
|
||||
|
||||
end = p + len;
|
||||
for (th = h; th; th = th->next) {
|
||||
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
|
||||
if (h[i]->hash == 0) {
|
||||
if (th->hash == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
|
||||
p = ngx_copy(p, th->value.data, th->value.len);
|
||||
|
||||
if (p == end) {
|
||||
if (th->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -919,7 +893,7 @@ static ngx_int_t
|
|||
ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
|
||||
return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
|
||||
&r->headers_in.headers.part,
|
||||
sizeof("http_") - 1);
|
||||
}
|
||||
|
|
@ -929,7 +903,7 @@ static ngx_int_t
|
|||
ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
|
||||
return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
|
||||
&r->headers_out.headers.part,
|
||||
sizeof("sent_http_") - 1);
|
||||
}
|
||||
|
|
@ -939,19 +913,26 @@ static ngx_int_t
|
|||
ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
|
||||
return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
|
||||
&r->headers_out.trailers.part,
|
||||
sizeof("sent_trailer_") - 1);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
|
||||
ngx_http_variable_unknown_header(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, ngx_str_t *var,
|
||||
ngx_list_part_t *part, size_t prefix)
|
||||
{
|
||||
u_char ch;
|
||||
u_char *p, ch;
|
||||
size_t len;
|
||||
ngx_uint_t i, n;
|
||||
ngx_table_elt_t *header;
|
||||
ngx_table_elt_t *header, *h, **ph;
|
||||
|
||||
ph = &h;
|
||||
#if (NGX_SUPPRESS_WARN)
|
||||
len = 0;
|
||||
#endif
|
||||
|
||||
header = part->elts;
|
||||
|
||||
|
|
@ -971,7 +952,11 @@ ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
|
|||
continue;
|
||||
}
|
||||
|
||||
for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
|
||||
if (header[i].key.len != var->len - prefix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (n = 0; n < var->len - prefix; n++) {
|
||||
ch = header[i].key.data[n];
|
||||
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
|
|
@ -986,18 +971,59 @@ ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
|
|||
}
|
||||
}
|
||||
|
||||
if (n + prefix == var->len && n == header[i].key.len) {
|
||||
v->len = header[i].value.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = header[i].value.data;
|
||||
|
||||
return NGX_OK;
|
||||
if (n != var->len - prefix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
len += header[i].value.len + 2;
|
||||
|
||||
*ph = &header[i];
|
||||
ph = &header[i].next;
|
||||
}
|
||||
|
||||
v->not_found = 1;
|
||||
*ph = NULL;
|
||||
|
||||
if (h == NULL) {
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
len -= 2;
|
||||
|
||||
if (h->next == NULL) {
|
||||
|
||||
v->len = h->value.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = h->value.data;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
v->len = len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = p;
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
p = ngx_copy(p, h->value.data, h->value.len);
|
||||
|
||||
if (h->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
*p++ = ','; *p++ = ' ';
|
||||
|
||||
h = h->next;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -1050,8 +1076,8 @@ ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||
s.len = name->len - (sizeof("cookie_") - 1);
|
||||
s.data = name->data + sizeof("cookie_") - 1;
|
||||
|
||||
if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie)
|
||||
== NGX_DECLINED)
|
||||
if (ngx_http_parse_multi_header_lines(r, r->headers_in.cookie, &s, &cookie)
|
||||
== NULL)
|
||||
{
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
|
|
@ -1366,6 +1392,39 @@ ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
ngx_str_t *name = (ngx_str_t *) data;
|
||||
|
||||
ngx_int_t rc;
|
||||
ngx_str_t tlv, value;
|
||||
|
||||
tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1);
|
||||
tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1;
|
||||
|
||||
rc = ngx_proxy_protocol_get_tlv(r->connection, &tlv, &value);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (rc == NGX_DECLINED) {
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
v->len = value.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = value.data;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_variable_server_addr(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
|
|
@ -1879,7 +1938,7 @@ ngx_http_variable_sent_location(ngx_http_request_t *r,
|
|||
|
||||
ngx_str_set(&name, "sent_http_location");
|
||||
|
||||
return ngx_http_variable_unknown_header(v, &name,
|
||||
return ngx_http_variable_unknown_header(r, v, &name,
|
||||
&r->headers_out.headers.part,
|
||||
sizeof("sent_http_") - 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,8 +57,9 @@ ngx_http_variable_value_t *ngx_http_get_flushed_variable(ngx_http_request_t *r,
|
|||
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
|
||||
ngx_str_t *name, ngx_uint_t key);
|
||||
|
||||
ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v,
|
||||
ngx_str_t *var, ngx_list_part_t *part, size_t prefix);
|
||||
ngx_int_t ngx_http_variable_unknown_header(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, ngx_str_t *var, ngx_list_part_t *part,
|
||||
size_t prefix);
|
||||
|
||||
|
||||
#if (NGX_PCRE)
|
||||
|
|
|
|||
|
|
@ -227,7 +227,8 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
|
||||
if (size == 0
|
||||
&& !(c->buffered & NGX_LOWLEVEL_BUFFERED)
|
||||
&& !(last && c->need_last_buf))
|
||||
&& !(last && c->need_last_buf)
|
||||
&& !(flush && c->need_flush_buf))
|
||||
{
|
||||
if (last || flush || sync) {
|
||||
for (cl = r->out; cl; /* void */) {
|
||||
|
|
|
|||
|
|
@ -1730,6 +1730,7 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
size_t len;
|
||||
ngx_int_t rc;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_connection_t *fc;
|
||||
ngx_http_header_t *hh;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_v2_header_t *header;
|
||||
|
|
@ -1789,17 +1790,11 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
}
|
||||
|
||||
r = h2c->state.stream->request;
|
||||
fc = r->connection;
|
||||
|
||||
/* TODO Optimization: validate headers while parsing. */
|
||||
if (ngx_http_v2_validate_header(r, header) != NGX_OK) {
|
||||
if (ngx_http_v2_terminate_stream(h2c, h2c->state.stream,
|
||||
NGX_HTTP_V2_PROTOCOL_ERROR)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
return ngx_http_v2_connection_error(h2c,
|
||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
@ -1886,6 +1881,8 @@ error:
|
|||
|
||||
h2c->state.stream = NULL;
|
||||
|
||||
ngx_http_run_posted_requests(fc);
|
||||
|
||||
return ngx_http_v2_state_header_complete(h2c, pos, end);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,12 +153,12 @@ struct ngx_http_v2_connection_s {
|
|||
ngx_queue_t dependencies;
|
||||
ngx_queue_t closed;
|
||||
|
||||
ngx_uint_t closed_nodes;
|
||||
ngx_uint_t last_sid;
|
||||
ngx_uint_t last_push;
|
||||
|
||||
time_t lingering_time;
|
||||
|
||||
unsigned closed_nodes:8;
|
||||
unsigned settings_ack:1;
|
||||
unsigned table_update:1;
|
||||
unsigned blocked:1;
|
||||
|
|
|
|||
|
|
@ -665,6 +665,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
|
|||
|
||||
fc->send_chain = ngx_http_v2_send_chain;
|
||||
fc->need_last_buf = 1;
|
||||
fc->need_flush_buf = 1;
|
||||
|
||||
return ngx_http_v2_filter_send(fc, stream);
|
||||
}
|
||||
|
|
@ -673,14 +674,14 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
|
|||
static ngx_int_t
|
||||
ngx_http_v2_push_resources(ngx_http_request_t *r)
|
||||
{
|
||||
u_char *start, *end, *last;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t path;
|
||||
ngx_uint_t i, push;
|
||||
ngx_table_elt_t **h;
|
||||
ngx_http_v2_loc_conf_t *h2lcf;
|
||||
ngx_http_complex_value_t *pushes;
|
||||
ngx_str_t binary[NGX_HTTP_V2_PUSH_HEADERS];
|
||||
u_char *start, *end, *last;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t path;
|
||||
ngx_uint_t i, push;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_v2_loc_conf_t *h2lcf;
|
||||
ngx_http_complex_value_t *pushes;
|
||||
ngx_str_t binary[NGX_HTTP_V2_PUSH_HEADERS];
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http2 push resources");
|
||||
|
|
@ -724,15 +725,13 @@ ngx_http_v2_push_resources(ngx_http_request_t *r)
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
h = r->headers_out.link.elts;
|
||||
|
||||
for (i = 0; i < r->headers_out.link.nelts; i++) {
|
||||
for (h = r->headers_out.link; h; h = h->next) {
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http2 parse link: \"%V\"", &h[i]->value);
|
||||
"http2 parse link: \"%V\"", &h->value);
|
||||
|
||||
start = h[i]->value.data;
|
||||
end = h[i]->value.data + h[i]->value.len;
|
||||
start = h->value.data;
|
||||
end = h->value.data + h->value.len;
|
||||
|
||||
next_link:
|
||||
|
||||
|
|
@ -1815,7 +1814,11 @@ ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c,
|
|||
static ngx_inline ngx_int_t
|
||||
ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream)
|
||||
{
|
||||
if (stream->queued == 0) {
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = stream->connection->connection;
|
||||
|
||||
if (stream->queued == 0 && !c->buffered) {
|
||||
fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
ngx_str_t *value, size;
|
||||
ngx_url_t u;
|
||||
ngx_uint_t i, n, m;
|
||||
ngx_mail_listen_t *ls, *als;
|
||||
ngx_mail_listen_t *ls, *als, *nls;
|
||||
ngx_mail_module_t *module;
|
||||
ngx_mail_core_main_conf_t *cmcf;
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
|
||||
|
||||
ls = ngx_array_push_n(&cmcf->listen, u.naddrs);
|
||||
ls = ngx_array_push(&cmcf->listen);
|
||||
if (ls == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
|
@ -568,20 +568,40 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
als = cmcf->listen.elts;
|
||||
|
||||
for (n = 0; n < u.naddrs; n++) {
|
||||
ls[n] = ls[0];
|
||||
|
||||
ls[n].sockaddr = u.addrs[n].sockaddr;
|
||||
ls[n].socklen = u.addrs[n].socklen;
|
||||
ls[n].addr_text = u.addrs[n].name;
|
||||
ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
|
||||
u.addrs[i].sockaddr, u.addrs[i].socklen, 1)
|
||||
== NGX_OK)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) {
|
||||
if (n != 0) {
|
||||
nls = ngx_array_push(&cmcf->listen);
|
||||
if (nls == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
*nls = *ls;
|
||||
|
||||
} else {
|
||||
nls = ls;
|
||||
}
|
||||
|
||||
nls->sockaddr = u.addrs[n].sockaddr;
|
||||
nls->socklen = u.addrs[n].socklen;
|
||||
nls->addr_text = u.addrs[n].name;
|
||||
nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
|
||||
|
||||
als = cmcf->listen.elts;
|
||||
|
||||
for (i = 0; i < cmcf->listen.nelts - 1; i++) {
|
||||
|
||||
if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
|
||||
ls[n].sockaddr, ls[n].socklen, 1)
|
||||
nls->sockaddr, nls->socklen, 1)
|
||||
!= NGX_OK)
|
||||
{
|
||||
continue;
|
||||
|
|
@ -589,9 +609,12 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate \"%V\" address and port pair",
|
||||
&ls[n].addr_text);
|
||||
&nls->addr_text);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
next:
|
||||
continue;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
|
|
|||
|
|
@ -327,7 +327,9 @@ ngx_mail_proxy_pop3_handler(ngx_event_t *rev)
|
|||
c->log->action = NULL;
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
|
||||
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
if (s->buffer->pos < s->buffer->last
|
||||
|| s->connection->read->ready)
|
||||
{
|
||||
ngx_post_event(c->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
|
|
@ -486,7 +488,9 @@ ngx_mail_proxy_imap_handler(ngx_event_t *rev)
|
|||
c->log->action = NULL;
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
|
||||
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
if (s->buffer->pos < s->buffer->last
|
||||
|| s->connection->read->ready)
|
||||
{
|
||||
ngx_post_event(c->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
|
|
@ -821,7 +825,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
|
|||
c->log->action = NULL;
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
|
||||
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
if (s->buffer->pos < s->buffer->last
|
||||
|| s->connection->read->ready)
|
||||
{
|
||||
ngx_post_event(c->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
|
|
@ -890,7 +896,7 @@ ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s)
|
|||
u_char *p;
|
||||
ssize_t n, size;
|
||||
ngx_connection_t *c;
|
||||
u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
|
||||
u_char buf[NGX_PROXY_PROTOCOL_V1_MAX_HEADER];
|
||||
|
||||
s->connection->log->action = "sending PROXY protocol header to upstream";
|
||||
|
||||
|
|
@ -898,7 +904,7 @@ ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s)
|
|||
"mail proxy send PROXY protocol header");
|
||||
|
||||
p = ngx_proxy_protocol_write(s->connection, buf,
|
||||
buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
|
||||
buf + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
|
||||
if (p == NULL) {
|
||||
ngx_mail_proxy_internal_server_error(s);
|
||||
return NGX_ERROR;
|
||||
|
|
|
|||
|
|
@ -360,8 +360,9 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
prev->prefer_server_ciphers, 0);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
||||
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
|
||||
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
|
||||
(NGX_CONF_BITMASK_SET
|
||||
|NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
|
||||
|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
||||
|
||||
ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
|
||||
ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
|
||||
|
|
@ -682,7 +683,7 @@ ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
len++;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
if (len == 0 || j == value[i].len) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,10 @@ typedef struct iocb ngx_aiocb_t;
|
|||
#include <linux/capability.h>
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_UDP_SEGMENT)
|
||||
#include <netinet/udp.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_LISTEN_BACKLOG 511
|
||||
|
||||
|
|
|
|||
|
|
@ -736,6 +736,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
|
|||
ngx_set_shutdown_timer(cycle);
|
||||
ngx_close_listening_sockets(cycle);
|
||||
ngx_close_idle_connections(cycle);
|
||||
ngx_event_process_posted(cycle, &ngx_posted_events);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -758,7 +759,6 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
|
|||
ngx_cpuset_t *cpu_affinity;
|
||||
struct rlimit rlmt;
|
||||
ngx_core_conf_t *ccf;
|
||||
ngx_listening_t *ls;
|
||||
|
||||
if (ngx_set_environment(cycle, NULL) == NULL) {
|
||||
/* fatal */
|
||||
|
|
@ -888,15 +888,6 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
|
|||
tp = ngx_timeofday();
|
||||
srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);
|
||||
|
||||
/*
|
||||
* disable deleting previous events for the listening sockets because
|
||||
* in the worker processes there are no events at all at this point
|
||||
*/
|
||||
ls = cycle->listening.elts;
|
||||
for (i = 0; i < cycle->listening.nelts; i++) {
|
||||
ls[i].previous = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; cycle->modules[i]; i++) {
|
||||
if (cycle->modules[i]->init_process) {
|
||||
if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
|
|||
return 0;
|
||||
|
||||
} else {
|
||||
rev->ready = 0;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
}
|
||||
|
|
@ -55,12 +56,15 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
|
|||
|
||||
#if (NGX_HAVE_EPOLLRDHUP)
|
||||
|
||||
if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
|
||||
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
||||
&& ngx_use_epoll_rdhup)
|
||||
{
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"readv: eof:%d, avail:%d",
|
||||
rev->pending_eof, rev->available);
|
||||
|
||||
if (rev->available == 0 && !rev->pending_eof) {
|
||||
rev->ready = 0;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,9 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||
|
||||
#if (NGX_HAVE_EPOLLRDHUP)
|
||||
|
||||
if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
|
||||
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
||||
&& ngx_use_epoll_rdhup)
|
||||
{
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"recv: eof:%d, avail:%d",
|
||||
rev->pending_eof, rev->available);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
static ngx_chain_t *ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec,
|
||||
ngx_chain_t *in, ngx_log_t *log);
|
||||
static ssize_t ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec);
|
||||
static ssize_t ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec);
|
||||
|
||||
|
||||
ngx_chain_t *
|
||||
|
|
@ -88,7 +88,7 @@ ngx_udp_unix_sendmsg_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
|
||||
send += vec.size;
|
||||
|
||||
n = ngx_sendmsg(c, &vec);
|
||||
n = ngx_sendmsg_vec(c, &vec);
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
|
|
@ -204,24 +204,13 @@ ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, ngx_log_t *log)
|
|||
|
||||
|
||||
static ssize_t
|
||||
ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec)
|
||||
ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_err_t err;
|
||||
struct msghdr msg;
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))];
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
#endif
|
||||
struct msghdr msg;
|
||||
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
struct cmsghdr *cmsg;
|
||||
u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))];
|
||||
#endif
|
||||
|
||||
ngx_memzero(&msg, sizeof(struct msghdr));
|
||||
|
|
@ -234,88 +223,180 @@ ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec)
|
|||
msg.msg_iov = vec->iovs;
|
||||
msg.msg_iovlen = vec->count;
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
if (c->listening && c->listening->wildcard && c->local_sockaddr) {
|
||||
|
||||
msg.msg_control = msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
ngx_memzero(msg_control, sizeof(msg_control));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
msg.msg_controllen = ngx_set_srcaddr_cmsg(cmsg, c->local_sockaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ngx_sendmsg(c, &msg, 0);
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HAVE_ADDRINFO_CMSG)
|
||||
|
||||
size_t
|
||||
ngx_set_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr)
|
||||
{
|
||||
size_t len;
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR)
|
||||
struct in_addr *addr;
|
||||
struct sockaddr_in *sin;
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
struct in_pktinfo *pkt;
|
||||
struct sockaddr_in *sin;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
struct in6_pktinfo *pkt6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
|
||||
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR) || (NGX_HAVE_IP_PKTINFO)
|
||||
|
||||
if (local_sockaddr->sa_family == AF_INET) {
|
||||
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR)
|
||||
|
||||
if (c->local_sockaddr->sa_family == AF_INET) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_addr *addr;
|
||||
struct sockaddr_in *sin;
|
||||
cmsg->cmsg_type = IP_SENDSRCADDR;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
|
||||
len = CMSG_SPACE(sizeof(struct in_addr));
|
||||
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
sin = (struct sockaddr_in *) local_sockaddr;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
cmsg->cmsg_type = IP_SENDSRCADDR;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
|
||||
|
||||
sin = (struct sockaddr_in *) c->local_sockaddr;
|
||||
|
||||
addr = (struct in_addr *) CMSG_DATA(cmsg);
|
||||
*addr = sin->sin_addr;
|
||||
}
|
||||
addr = (struct in_addr *) CMSG_DATA(cmsg);
|
||||
*addr = sin->sin_addr;
|
||||
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
|
||||
if (c->local_sockaddr->sa_family == AF_INET) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_pktinfo *pkt;
|
||||
struct sockaddr_in *sin;
|
||||
cmsg->cmsg_type = IP_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
len = CMSG_SPACE(sizeof(struct in_pktinfo));
|
||||
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
sin = (struct sockaddr_in *) local_sockaddr;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
cmsg->cmsg_type = IP_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
ngx_memzero(pkt, sizeof(struct in_pktinfo));
|
||||
pkt->ipi_spec_dst = sin->sin_addr;
|
||||
|
||||
sin = (struct sockaddr_in *) c->local_sockaddr;
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
ngx_memzero(pkt, sizeof(struct in_pktinfo));
|
||||
pkt->ipi_spec_dst = sin->sin_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
if (local_sockaddr->sa_family == AF_INET6) {
|
||||
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
len = CMSG_SPACE(sizeof(struct in6_pktinfo));
|
||||
|
||||
sin6 = (struct sockaddr_in6 *) local_sockaddr;
|
||||
|
||||
pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
|
||||
ngx_memzero(pkt6, sizeof(struct in6_pktinfo));
|
||||
pkt6->ipi6_addr = sin6->sin6_addr;
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_get_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr)
|
||||
{
|
||||
|
||||
#if (NGX_HAVE_IP_RECVDSTADDR)
|
||||
struct in_addr *addr;
|
||||
struct sockaddr_in *sin;
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
struct in_pktinfo *pkt;
|
||||
struct sockaddr_in *sin;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
struct in6_pktinfo *pkt6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
|
||||
|
||||
#if (NGX_HAVE_IP_RECVDSTADDR)
|
||||
|
||||
if (cmsg->cmsg_level == IPPROTO_IP
|
||||
&& cmsg->cmsg_type == IP_RECVDSTADDR
|
||||
&& local_sockaddr->sa_family == AF_INET)
|
||||
{
|
||||
addr = (struct in_addr *) CMSG_DATA(cmsg);
|
||||
sin = (struct sockaddr_in *) local_sockaddr;
|
||||
sin->sin_addr = *addr;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
|
||||
if (cmsg->cmsg_level == IPPROTO_IP
|
||||
&& cmsg->cmsg_type == IP_PKTINFO
|
||||
&& local_sockaddr->sa_family == AF_INET)
|
||||
{
|
||||
pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
sin = (struct sockaddr_in *) local_sockaddr;
|
||||
sin->sin_addr = pkt->ipi_addr;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
|
||||
if (c->local_sockaddr->sa_family == AF_INET6) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in6_pktinfo *pkt6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
if (cmsg->cmsg_level == IPPROTO_IPV6
|
||||
&& cmsg->cmsg_type == IPV6_PKTINFO
|
||||
&& local_sockaddr->sa_family == AF_INET6)
|
||||
{
|
||||
pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
|
||||
sin6 = (struct sockaddr_in6 *) local_sockaddr;
|
||||
sin6->sin6_addr = pkt6->ipi6_addr;
|
||||
|
||||
msg.msg_control = &msg_control6;
|
||||
msg.msg_controllen = sizeof(msg_control6);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
|
||||
sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
|
||||
|
||||
pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
|
||||
ngx_memzero(pkt6, sizeof(struct in6_pktinfo));
|
||||
pkt6->ipi6_addr = sin6->sin6_addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_sendmsg(ngx_connection_t *c, struct msghdr *msg, int flags)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_err_t err;
|
||||
#if (NGX_DEBUG)
|
||||
size_t size;
|
||||
ngx_uint_t i;
|
||||
#endif
|
||||
|
||||
eintr:
|
||||
|
||||
n = sendmsg(c->fd, &msg, 0);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"sendmsg: %z of %uz", n, vec->size);
|
||||
n = sendmsg(c->fd, msg, flags);
|
||||
|
||||
if (n == -1) {
|
||||
err = ngx_errno;
|
||||
|
|
@ -338,5 +419,14 @@ eintr:
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
for (i = 0, size = 0; i < (size_t) msg->msg_iovlen; i++) {
|
||||
size += msg->msg_iov[i].iov_len;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"sendmsg: %z of %uz", n, size);
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
|
|||
BIN
src/os/win32/nginx.ico
Normal file
BIN
src/os/win32/nginx.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
6
src/os/win32/nginx.rc
Normal file
6
src/os/win32/nginx.rc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
// Copyright (C) Igor Sysoev
|
||||
// Copyright (C) Nginx, Inc.
|
||||
|
||||
|
||||
nginx icon discardable "src\\os\\win32\\nginx.ico"
|
||||
24
src/os/win32/nginx_icon16.xpm
Normal file
24
src/os/win32/nginx_icon16.xpm
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* XPM */
|
||||
static char * nginx_xpm[] = {
|
||||
"16 16 2 2",
|
||||
/* colors */
|
||||
" c none",
|
||||
"GG c #009900",
|
||||
/* pixels */
|
||||
" ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGG ",
|
||||
" GGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" "
|
||||
};
|
||||
39
src/os/win32/nginx_icon32.xpm
Normal file
39
src/os/win32/nginx_icon32.xpm
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* XPM */
|
||||
static char * nginx_xpm[] = {
|
||||
"32 32 2 2",
|
||||
/* colors */
|
||||
" c none",
|
||||
"GG c #009900",
|
||||
/* pixels */
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG ",
|
||||
" GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "
|
||||
55
src/os/win32/nginx_icon48.xpm
Normal file
55
src/os/win32/nginx_icon48.xpm
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* XPM */
|
||||
static char * nginx_xpm[] = {
|
||||
"48 48 2 2",
|
||||
/* colors */
|
||||
" c none",
|
||||
"GG c #009900",
|
||||
/* pixels */
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
44
src/os/win32/ngx_alloc.c
Normal file
44
src/os/win32/ngx_alloc.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
ngx_uint_t ngx_pagesize;
|
||||
ngx_uint_t ngx_pagesize_shift;
|
||||
ngx_uint_t ngx_cacheline_size;
|
||||
|
||||
|
||||
void *ngx_alloc(size_t size, ngx_log_t *log)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(size);
|
||||
if (p == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"malloc(%uz) failed", size);
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void *ngx_calloc(size_t size, ngx_log_t *log)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = ngx_alloc(size, log);
|
||||
|
||||
if (p) {
|
||||
ngx_memzero(p, size);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
27
src/os/win32/ngx_alloc.h
Normal file
27
src/os/win32/ngx_alloc.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_ALLOC_H_INCLUDED_
|
||||
#define _NGX_ALLOC_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
void *ngx_alloc(size_t size, ngx_log_t *log);
|
||||
void *ngx_calloc(size_t size, ngx_log_t *log);
|
||||
|
||||
#define ngx_free free
|
||||
#define ngx_memalign(alignment, size, log) ngx_alloc(size, log)
|
||||
|
||||
extern ngx_uint_t ngx_pagesize;
|
||||
extern ngx_uint_t ngx_pagesize_shift;
|
||||
extern ngx_uint_t ngx_cacheline_size;
|
||||
|
||||
|
||||
#endif /* _NGX_ALLOC_H_INCLUDED_ */
|
||||
69
src/os/win32/ngx_atomic.h
Normal file
69
src/os/win32/ngx_atomic.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_ATOMIC_H_INCLUDED_
|
||||
#define _NGX_ATOMIC_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_HAVE_ATOMIC_OPS 1
|
||||
|
||||
typedef int32_t ngx_atomic_int_t;
|
||||
typedef uint32_t ngx_atomic_uint_t;
|
||||
typedef volatile ngx_atomic_uint_t ngx_atomic_t;
|
||||
#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1)
|
||||
|
||||
|
||||
#if defined( __WATCOMC__ ) || defined( __BORLANDC__ ) || defined(__GNUC__) \
|
||||
|| ( _MSC_VER >= 1300 )
|
||||
|
||||
/* the new SDK headers */
|
||||
|
||||
#define ngx_atomic_cmp_set(lock, old, set) \
|
||||
((ngx_atomic_uint_t) InterlockedCompareExchange((long *) lock, set, old) \
|
||||
== old)
|
||||
|
||||
#else
|
||||
|
||||
/* the old MS VC6.0SP2 SDK headers */
|
||||
|
||||
#define ngx_atomic_cmp_set(lock, old, set) \
|
||||
(InterlockedCompareExchange((void **) lock, (void *) set, (void *) old) \
|
||||
== (void *) old)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define ngx_atomic_fetch_add(p, add) InterlockedExchangeAdd((long *) p, add)
|
||||
|
||||
|
||||
#define ngx_memory_barrier()
|
||||
|
||||
|
||||
#if defined( __BORLANDC__ ) || ( __WATCOMC__ < 1230 )
|
||||
|
||||
/*
|
||||
* Borland C++ 5.5 (tasm32) and Open Watcom C prior to 1.3
|
||||
* do not understand the "pause" instruction
|
||||
*/
|
||||
|
||||
#define ngx_cpu_pause()
|
||||
#else
|
||||
#define ngx_cpu_pause() __asm { pause }
|
||||
#endif
|
||||
|
||||
|
||||
void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin);
|
||||
|
||||
#define ngx_trylock(lock) (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))
|
||||
#define ngx_unlock(lock) *(lock) = 0
|
||||
|
||||
|
||||
#endif /* _NGX_ATOMIC_H_INCLUDED_ */
|
||||
22
src/os/win32/ngx_dlopen.c
Normal file
22
src/os/win32/ngx_dlopen.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Maxim Dounin
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
char *
|
||||
ngx_dlerror(void)
|
||||
{
|
||||
u_char *p;
|
||||
static u_char errstr[NGX_MAX_ERROR_STR];
|
||||
|
||||
p = ngx_strerror(ngx_errno, errstr, NGX_MAX_ERROR_STR);
|
||||
*p = '\0';
|
||||
|
||||
return (char *) errstr;
|
||||
}
|
||||
32
src/os/win32/ngx_dlopen.h
Normal file
32
src/os/win32/ngx_dlopen.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Maxim Dounin
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_DLOPEN_H_INCLUDED_
|
||||
#define _NGX_DLOPEN_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_HAVE_DLOPEN 1
|
||||
|
||||
|
||||
#define ngx_dlopen(path) LoadLibrary((char *) path)
|
||||
#define ngx_dlopen_n "LoadLibrary()"
|
||||
|
||||
#define ngx_dlsym(handle, symbol) (void *) GetProcAddress(handle, symbol)
|
||||
#define ngx_dlsym_n "GetProcAddress()"
|
||||
|
||||
#define ngx_dlclose(handle) (FreeLibrary(handle) ? 0 : -1)
|
||||
#define ngx_dlclose_n "FreeLibrary()"
|
||||
|
||||
|
||||
char *ngx_dlerror(void);
|
||||
|
||||
|
||||
#endif /* _NGX_DLOPEN_H_INCLUDED_ */
|
||||
60
src/os/win32/ngx_errno.c
Normal file
60
src/os/win32/ngx_errno.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
u_char *
|
||||
ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
|
||||
{
|
||||
u_int len;
|
||||
static u_long lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
|
||||
|
||||
if (size == 0) {
|
||||
return errstr;
|
||||
}
|
||||
|
||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, lang, (char *) errstr, size, NULL);
|
||||
|
||||
if (len == 0 && lang) {
|
||||
|
||||
/*
|
||||
* Try to use English messages first and fallback to a language,
|
||||
* based on locale: non-English Windows have no English messages
|
||||
* at all. This way allows to use English messages at least on
|
||||
* Windows with MUI.
|
||||
*/
|
||||
|
||||
lang = 0;
|
||||
|
||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, lang, (char *) errstr, size, NULL);
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
return ngx_snprintf(errstr, size,
|
||||
"FormatMessage() error:(%d)", GetLastError());
|
||||
}
|
||||
|
||||
/* remove ".\r\n\0" */
|
||||
while (errstr[len] == '\0' || errstr[len] == CR
|
||||
|| errstr[len] == LF || errstr[len] == '.')
|
||||
{
|
||||
--len;
|
||||
}
|
||||
|
||||
return &errstr[++len];
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_strerror_init(void)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
71
src/os/win32/ngx_errno.h
Normal file
71
src/os/win32/ngx_errno.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_ERRNO_H_INCLUDED_
|
||||
#define _NGX_ERRNO_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef DWORD ngx_err_t;
|
||||
|
||||
#define ngx_errno GetLastError()
|
||||
#define ngx_set_errno(err) SetLastError(err)
|
||||
#define ngx_socket_errno WSAGetLastError()
|
||||
#define ngx_set_socket_errno(err) WSASetLastError(err)
|
||||
|
||||
#define NGX_EPERM ERROR_ACCESS_DENIED
|
||||
#define NGX_ENOENT ERROR_FILE_NOT_FOUND
|
||||
#define NGX_ENOPATH ERROR_PATH_NOT_FOUND
|
||||
#define NGX_ENOMEM ERROR_NOT_ENOUGH_MEMORY
|
||||
#define NGX_EACCES ERROR_ACCESS_DENIED
|
||||
/*
|
||||
* there are two EEXIST error codes:
|
||||
* ERROR_FILE_EXISTS used by CreateFile(CREATE_NEW),
|
||||
* and ERROR_ALREADY_EXISTS used by CreateDirectory();
|
||||
* MoveFile() uses both
|
||||
*/
|
||||
#define NGX_EEXIST ERROR_ALREADY_EXISTS
|
||||
#define NGX_EEXIST_FILE ERROR_FILE_EXISTS
|
||||
#define NGX_EXDEV ERROR_NOT_SAME_DEVICE
|
||||
#define NGX_ENOTDIR ERROR_PATH_NOT_FOUND
|
||||
#define NGX_EISDIR ERROR_CANNOT_MAKE
|
||||
#define NGX_ENOSPC ERROR_DISK_FULL
|
||||
#define NGX_EPIPE EPIPE
|
||||
#define NGX_EAGAIN WSAEWOULDBLOCK
|
||||
#define NGX_EINPROGRESS WSAEINPROGRESS
|
||||
#define NGX_ENOPROTOOPT WSAENOPROTOOPT
|
||||
#define NGX_EOPNOTSUPP WSAEOPNOTSUPP
|
||||
#define NGX_EADDRINUSE WSAEADDRINUSE
|
||||
#define NGX_ECONNABORTED WSAECONNABORTED
|
||||
#define NGX_ECONNRESET WSAECONNRESET
|
||||
#define NGX_ENOTCONN WSAENOTCONN
|
||||
#define NGX_ETIMEDOUT WSAETIMEDOUT
|
||||
#define NGX_ECONNREFUSED WSAECONNREFUSED
|
||||
#define NGX_ENAMETOOLONG ERROR_BAD_PATHNAME
|
||||
#define NGX_ENETDOWN WSAENETDOWN
|
||||
#define NGX_ENETUNREACH WSAENETUNREACH
|
||||
#define NGX_EHOSTDOWN WSAEHOSTDOWN
|
||||
#define NGX_EHOSTUNREACH WSAEHOSTUNREACH
|
||||
#define NGX_ENOMOREFILES ERROR_NO_MORE_FILES
|
||||
#define NGX_EILSEQ ERROR_NO_UNICODE_TRANSLATION
|
||||
#define NGX_ELOOP 0
|
||||
#define NGX_EBADF WSAEBADF
|
||||
|
||||
#define NGX_EALREADY WSAEALREADY
|
||||
#define NGX_EINVAL WSAEINVAL
|
||||
#define NGX_EMFILE WSAEMFILE
|
||||
#define NGX_ENFILE WSAEMFILE
|
||||
|
||||
|
||||
u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);
|
||||
ngx_int_t ngx_strerror_init(void);
|
||||
|
||||
|
||||
#endif /* _NGX_ERRNO_H_INCLUDED_ */
|
||||
99
src/os/win32/ngx_event_log.c
Normal file
99
src/os/win32/ngx_event_log.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_MAX_ERROR_STR 2048
|
||||
|
||||
|
||||
void ngx_cdecl
|
||||
ngx_event_log(ngx_err_t err, const char *fmt, ...)
|
||||
{
|
||||
u_char *p, *last;
|
||||
long types;
|
||||
HKEY key;
|
||||
HANDLE ev;
|
||||
va_list args;
|
||||
u_char text[NGX_MAX_ERROR_STR];
|
||||
const char *msgarg[9];
|
||||
static u_char netmsg[] = "%SystemRoot%\\System32\\netmsg.dll";
|
||||
|
||||
last = text + NGX_MAX_ERROR_STR;
|
||||
p = text + GetModuleFileName(NULL, (char *) text, NGX_MAX_ERROR_STR - 50);
|
||||
|
||||
*p++ = ':';
|
||||
ngx_linefeed(p);
|
||||
|
||||
va_start(args, fmt);
|
||||
p = ngx_vslprintf(p, last, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (err) {
|
||||
p = ngx_log_errno(p, last, err);
|
||||
}
|
||||
|
||||
if (p > last - NGX_LINEFEED_SIZE - 1) {
|
||||
p = last - NGX_LINEFEED_SIZE - 1;
|
||||
}
|
||||
|
||||
ngx_linefeed(p);
|
||||
|
||||
*p = '\0';
|
||||
|
||||
/*
|
||||
* we do not log errors here since we use
|
||||
* Event Log only to log our own logs open errors
|
||||
*/
|
||||
|
||||
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\nginx",
|
||||
0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, NULL)
|
||||
!= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (RegSetValueEx(key, "EventMessageFile", 0, REG_EXPAND_SZ,
|
||||
netmsg, sizeof(netmsg) - 1)
|
||||
!= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
types = EVENTLOG_ERROR_TYPE;
|
||||
|
||||
if (RegSetValueEx(key, "TypesSupported", 0, REG_DWORD,
|
||||
(u_char *) &types, sizeof(long))
|
||||
!= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
|
||||
ev = RegisterEventSource(NULL, "nginx");
|
||||
|
||||
msgarg[0] = (char *) text;
|
||||
msgarg[1] = NULL;
|
||||
msgarg[2] = NULL;
|
||||
msgarg[3] = NULL;
|
||||
msgarg[4] = NULL;
|
||||
msgarg[5] = NULL;
|
||||
msgarg[6] = NULL;
|
||||
msgarg[7] = NULL;
|
||||
msgarg[8] = NULL;
|
||||
|
||||
/*
|
||||
* the 3299 event id in netmsg.dll has the generic message format:
|
||||
* "%1 %2 %3 %4 %5 %6 %7 %8 %9"
|
||||
*/
|
||||
|
||||
ReportEvent(ev, EVENTLOG_ERROR_TYPE, 0, 3299, NULL, 9, 0, msgarg, NULL);
|
||||
|
||||
DeregisterEventSource(ev);
|
||||
}
|
||||
1459
src/os/win32/ngx_files.c
Normal file
1459
src/os/win32/ngx_files.c
Normal file
File diff suppressed because it is too large
Load diff
271
src/os/win32/ngx_files.h
Normal file
271
src/os/win32/ngx_files.h
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_FILES_H_INCLUDED_
|
||||
#define _NGX_FILES_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef HANDLE ngx_fd_t;
|
||||
typedef BY_HANDLE_FILE_INFORMATION ngx_file_info_t;
|
||||
typedef uint64_t ngx_file_uniq_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char *name;
|
||||
size_t size;
|
||||
void *addr;
|
||||
ngx_fd_t fd;
|
||||
HANDLE handle;
|
||||
ngx_log_t *log;
|
||||
} ngx_file_mapping_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATAW finddata;
|
||||
|
||||
u_char *name;
|
||||
size_t namelen;
|
||||
size_t allocated;
|
||||
|
||||
unsigned valid_info:1;
|
||||
unsigned type:1;
|
||||
unsigned ready:1;
|
||||
} ngx_dir_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATAW finddata;
|
||||
|
||||
unsigned ready:1;
|
||||
unsigned test:1;
|
||||
unsigned no_match:1;
|
||||
|
||||
u_char *pattern;
|
||||
ngx_str_t name;
|
||||
size_t last;
|
||||
ngx_log_t *log;
|
||||
} ngx_glob_t;
|
||||
|
||||
|
||||
|
||||
/* INVALID_FILE_ATTRIBUTES is specified but not defined at least in MSVC6SP2 */
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES 0xffffffff
|
||||
#endif
|
||||
|
||||
/* INVALID_SET_FILE_POINTER is not defined at least in MSVC6SP2 */
|
||||
#ifndef INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER 0xffffffff
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_INVALID_FILE INVALID_HANDLE_VALUE
|
||||
#define NGX_FILE_ERROR 0
|
||||
|
||||
|
||||
ngx_fd_t ngx_open_file(u_char *name, u_long mode, u_long create, u_long access);
|
||||
#define ngx_open_file_n "CreateFile()"
|
||||
|
||||
#define NGX_FILE_RDONLY GENERIC_READ
|
||||
#define NGX_FILE_WRONLY GENERIC_WRITE
|
||||
#define NGX_FILE_RDWR GENERIC_READ|GENERIC_WRITE
|
||||
#define NGX_FILE_APPEND FILE_APPEND_DATA|SYNCHRONIZE
|
||||
#define NGX_FILE_NONBLOCK 0
|
||||
|
||||
#define NGX_FILE_CREATE_OR_OPEN OPEN_ALWAYS
|
||||
#define NGX_FILE_OPEN OPEN_EXISTING
|
||||
#define NGX_FILE_TRUNCATE CREATE_ALWAYS
|
||||
|
||||
#define NGX_FILE_DEFAULT_ACCESS 0
|
||||
#define NGX_FILE_OWNER_ACCESS 0
|
||||
|
||||
|
||||
ngx_fd_t ngx_open_tempfile(u_char *name, ngx_uint_t persistent,
|
||||
ngx_uint_t access);
|
||||
#define ngx_open_tempfile_n "CreateFile()"
|
||||
|
||||
|
||||
#define ngx_close_file CloseHandle
|
||||
#define ngx_close_file_n "CloseHandle()"
|
||||
|
||||
|
||||
ssize_t ngx_read_fd(ngx_fd_t fd, void *buf, size_t size);
|
||||
#define ngx_read_fd_n "ReadFile()"
|
||||
|
||||
|
||||
ssize_t ngx_write_fd(ngx_fd_t fd, void *buf, size_t size);
|
||||
#define ngx_write_fd_n "WriteFile()"
|
||||
|
||||
|
||||
ssize_t ngx_write_console(ngx_fd_t fd, void *buf, size_t size);
|
||||
|
||||
|
||||
#define ngx_linefeed(p) *p++ = CR; *p++ = LF;
|
||||
#define NGX_LINEFEED_SIZE 2
|
||||
#define NGX_LINEFEED CRLF
|
||||
|
||||
|
||||
ngx_int_t ngx_delete_file(u_char *name);
|
||||
#define ngx_delete_file_n "DeleteFile()"
|
||||
|
||||
|
||||
ngx_int_t ngx_rename_file(u_char *from, u_char *to);
|
||||
#define ngx_rename_file_n "MoveFile()"
|
||||
ngx_err_t ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log);
|
||||
|
||||
|
||||
|
||||
ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
|
||||
#define ngx_set_file_time_n "SetFileTime()"
|
||||
|
||||
|
||||
ngx_int_t ngx_file_info(u_char *filename, ngx_file_info_t *fi);
|
||||
#define ngx_file_info_n "GetFileAttributesEx()"
|
||||
|
||||
|
||||
#define ngx_fd_info(fd, fi) GetFileInformationByHandle(fd, fi)
|
||||
#define ngx_fd_info_n "GetFileInformationByHandle()"
|
||||
|
||||
|
||||
#define ngx_link_info(name, fi) ngx_file_info(name, fi)
|
||||
#define ngx_link_info_n "GetFileAttributesEx()"
|
||||
|
||||
|
||||
#define ngx_is_dir(fi) \
|
||||
(((fi)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
#define ngx_is_file(fi) \
|
||||
(((fi)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
#define ngx_is_link(fi) 0
|
||||
#define ngx_is_exec(fi) 0
|
||||
|
||||
#define ngx_file_access(fi) 0
|
||||
|
||||
#define ngx_file_size(fi) \
|
||||
(((off_t) (fi)->nFileSizeHigh << 32) | (fi)->nFileSizeLow)
|
||||
#define ngx_file_fs_size(fi) ngx_file_size(fi)
|
||||
|
||||
#define ngx_file_uniq(fi) (*(ngx_file_uniq_t *) &(fi)->nFileIndexHigh)
|
||||
|
||||
|
||||
/* 116444736000000000 is commented in src/os/win32/ngx_time.c */
|
||||
|
||||
#define ngx_file_mtime(fi) \
|
||||
(time_t) (((((unsigned __int64) (fi)->ftLastWriteTime.dwHighDateTime << 32) \
|
||||
| (fi)->ftLastWriteTime.dwLowDateTime) \
|
||||
- 116444736000000000) / 10000000)
|
||||
|
||||
ngx_int_t ngx_create_file_mapping(ngx_file_mapping_t *fm);
|
||||
void ngx_close_file_mapping(ngx_file_mapping_t *fm);
|
||||
|
||||
|
||||
u_char *ngx_realpath(u_char *path, u_char *resolved);
|
||||
#define ngx_realpath_n ""
|
||||
|
||||
|
||||
size_t ngx_getcwd(u_char *buf, size_t size);
|
||||
#define ngx_getcwd_n "GetCurrentDirectory()"
|
||||
|
||||
|
||||
#define ngx_path_separator(c) ((c) == '/' || (c) == '\\')
|
||||
|
||||
#define NGX_HAVE_MAX_PATH 1
|
||||
#define NGX_MAX_PATH MAX_PATH
|
||||
|
||||
|
||||
ngx_int_t ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir);
|
||||
#define ngx_open_dir_n "FindFirstFile()"
|
||||
|
||||
|
||||
ngx_int_t ngx_read_dir(ngx_dir_t *dir);
|
||||
#define ngx_read_dir_n "FindNextFile()"
|
||||
|
||||
|
||||
ngx_int_t ngx_close_dir(ngx_dir_t *dir);
|
||||
#define ngx_close_dir_n "FindClose()"
|
||||
|
||||
|
||||
ngx_int_t ngx_create_dir(u_char *name, ngx_uint_t access);
|
||||
#define ngx_create_dir_n "CreateDirectory()"
|
||||
|
||||
|
||||
ngx_int_t ngx_delete_dir(u_char *name);
|
||||
#define ngx_delete_dir_n "RemoveDirectory()"
|
||||
|
||||
|
||||
#define ngx_dir_access(a) (a)
|
||||
|
||||
|
||||
#define ngx_de_name(dir) (dir)->name
|
||||
#define ngx_de_namelen(dir) (dir)->namelen
|
||||
|
||||
ngx_int_t ngx_de_info(u_char *name, ngx_dir_t *dir);
|
||||
#define ngx_de_info_n "dummy()"
|
||||
|
||||
ngx_int_t ngx_de_link_info(u_char *name, ngx_dir_t *dir);
|
||||
#define ngx_de_link_info_n "dummy()"
|
||||
|
||||
#define ngx_de_is_dir(dir) \
|
||||
(((dir)->finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
#define ngx_de_is_file(dir) \
|
||||
(((dir)->finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
#define ngx_de_is_link(dir) 0
|
||||
#define ngx_de_access(dir) 0
|
||||
#define ngx_de_size(dir) \
|
||||
(((off_t) (dir)->finddata.nFileSizeHigh << 32) | (dir)->finddata.nFileSizeLow)
|
||||
#define ngx_de_fs_size(dir) ngx_de_size(dir)
|
||||
|
||||
/* 116444736000000000 is commented in src/os/win32/ngx_time.c */
|
||||
|
||||
#define ngx_de_mtime(dir) \
|
||||
(time_t) (((((unsigned __int64) \
|
||||
(dir)->finddata.ftLastWriteTime.dwHighDateTime << 32) \
|
||||
| (dir)->finddata.ftLastWriteTime.dwLowDateTime) \
|
||||
- 116444736000000000) / 10000000)
|
||||
|
||||
|
||||
ngx_int_t ngx_open_glob(ngx_glob_t *gl);
|
||||
#define ngx_open_glob_n "FindFirstFile()"
|
||||
|
||||
ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name);
|
||||
void ngx_close_glob(ngx_glob_t *gl);
|
||||
|
||||
|
||||
ssize_t ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset);
|
||||
#define ngx_read_file_n "ReadFile()"
|
||||
|
||||
ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size,
|
||||
off_t offset);
|
||||
|
||||
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
off_t offset, ngx_pool_t *pool);
|
||||
|
||||
ngx_int_t ngx_read_ahead(ngx_fd_t fd, size_t n);
|
||||
#define ngx_read_ahead_n "ngx_read_ahead_n"
|
||||
|
||||
ngx_int_t ngx_directio_on(ngx_fd_t fd);
|
||||
#define ngx_directio_on_n "ngx_directio_on_n"
|
||||
|
||||
ngx_int_t ngx_directio_off(ngx_fd_t fd);
|
||||
#define ngx_directio_off_n "ngx_directio_off_n"
|
||||
|
||||
size_t ngx_fs_bsize(u_char *name);
|
||||
off_t ngx_fs_available(u_char *name);
|
||||
|
||||
|
||||
#define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
#define ngx_stderr GetStdHandle(STD_ERROR_HANDLE)
|
||||
#define ngx_set_stderr(fd) SetStdHandle(STD_ERROR_HANDLE, fd)
|
||||
#define ngx_set_stderr_n "SetStdHandle(STD_ERROR_HANDLE)"
|
||||
|
||||
|
||||
#endif /* _NGX_FILES_H_INCLUDED_ */
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue