New upstream version 1.22.0
This commit is contained in:
parent
5c35f1696f
commit
deedff451f
92 changed files with 3480 additions and 1301 deletions
160
CHANGES
160
CHANGES
|
|
@ -1,28 +1,144 @@
|
|||
|
||||
Changes with nginx 1.20.2 16 Nov 2021
|
||||
Changes with nginx 1.22.0 24 May 2022
|
||||
|
||||
*) 1.22.x stable branch.
|
||||
|
||||
|
||||
Changes with nginx 1.21.6 25 Jan 2022
|
||||
|
||||
*) Bugfix: when using EPOLLEXCLUSIVE on Linux client connections were
|
||||
unevenly distributed among worker processes.
|
||||
|
||||
*) Bugfix: nginx returned the "Connection: keep-alive" header line in
|
||||
responses during graceful shutdown of old worker processes.
|
||||
|
||||
*) Bugfix: in the "ssl_session_ticket_key" when using TLSv1.3.
|
||||
|
||||
|
||||
Changes with nginx 1.21.5 28 Dec 2021
|
||||
|
||||
*) Change: now nginx is built with the PCRE2 library by default.
|
||||
|
||||
*) Change: now nginx always uses sendfile(SF_NODISKIO) on FreeBSD.
|
||||
|
||||
*) Feature: support for sendfile(SF_NOCACHE) on FreeBSD.
|
||||
|
||||
*) Feature: the $ssl_curve variable.
|
||||
|
||||
*) Bugfix: connections might hang when using HTTP/2 without SSL with the
|
||||
"sendfile" and "aio" directives.
|
||||
|
||||
|
||||
Changes with nginx 1.21.4 02 Nov 2021
|
||||
|
||||
*) Change: support for NPN instead of ALPN to establish HTTP/2
|
||||
connections has been removed.
|
||||
|
||||
*) Change: now nginx rejects SSL connections if ALPN is used by the
|
||||
client, but no supported protocols can be negotiated.
|
||||
|
||||
*) Change: the default value of the "sendfile_max_chunk" directive was
|
||||
changed to 2 megabytes.
|
||||
|
||||
*) Feature: the "proxy_half_close" directive in the stream module.
|
||||
|
||||
*) Feature: the "ssl_alpn" directive in the stream module.
|
||||
|
||||
*) Feature: the $ssl_alpn_protocol variable.
|
||||
|
||||
*) Feature: support for SSL_sendfile() when using OpenSSL 3.0.
|
||||
|
||||
*) Feature: the "mp4_start_key_frame" directive in the
|
||||
ngx_http_mp4_module.
|
||||
Thanks to Tracey Jaquith.
|
||||
|
||||
*) Bugfix: in the $content_length variable when using chunked transfer
|
||||
encoding.
|
||||
|
||||
*) Bugfix: after receiving a response with incorrect length from a
|
||||
proxied backend nginx might nevertheless cache the connection.
|
||||
Thanks to Awdhesh Mathpal.
|
||||
|
||||
*) Bugfix: invalid headers from backends were logged at the "info" level
|
||||
instead of "error"; the bug had appeared in 1.21.1.
|
||||
|
||||
*) Bugfix: requests might hang when using HTTP/2 and the "aio_write"
|
||||
directive.
|
||||
|
||||
|
||||
Changes with nginx 1.21.3 07 Sep 2021
|
||||
|
||||
*) Change: optimization of client request body reading when using
|
||||
HTTP/2.
|
||||
|
||||
*) Bugfix: in request body filters internal API when using HTTP/2 and
|
||||
buffering of the data being processed.
|
||||
|
||||
|
||||
Changes with nginx 1.21.2 31 Aug 2021
|
||||
|
||||
*) Change: now nginx rejects HTTP/1.0 requests with the
|
||||
"Transfer-Encoding" header line.
|
||||
|
||||
*) Change: export ciphers are no longer supported.
|
||||
|
||||
*) Feature: OpenSSL 3.0 compatibility.
|
||||
|
||||
*) Feature: the "Auth-SSL-Protocol" and "Auth-SSL-Cipher" header lines
|
||||
are now passed to the mail proxy authentication server.
|
||||
Thanks to Rob Mueller.
|
||||
|
||||
*) Feature: request body filters API now permits buffering of the data
|
||||
being processed.
|
||||
|
||||
*) Bugfix: backend SSL connections in the stream module might hang after
|
||||
an SSL handshake.
|
||||
|
||||
*) Bugfix: the security level, which is available in OpenSSL 1.1.0 or
|
||||
newer, did not affect loading of the server certificates when set
|
||||
with "@SECLEVEL=N" in the "ssl_ciphers" directive.
|
||||
|
||||
*) Bugfix: SSL connections with gRPC backends might hang if select,
|
||||
poll, or /dev/poll methods were used.
|
||||
|
||||
*) Bugfix: when using HTTP/2 client request body was always written to
|
||||
disk if the "Content-Length" header line was not present in the
|
||||
request.
|
||||
|
||||
|
||||
Changes with nginx 1.21.1 06 Jul 2021
|
||||
|
||||
*) Change: now nginx always returns an error for the CONNECT method.
|
||||
|
||||
*) Change: now nginx always returns an error if both "Content-Length"
|
||||
and "Transfer-Encoding" header lines are present in the request.
|
||||
|
||||
*) Change: now nginx always returns an error if spaces or control
|
||||
characters are used in the request line.
|
||||
|
||||
*) Change: now nginx always returns an error if spaces or control
|
||||
characters are used in a header name.
|
||||
|
||||
*) Change: now nginx always returns an error if spaces or control
|
||||
characters are used in the "Host" request header line.
|
||||
|
||||
*) Change: optimization of configuration testing when using many
|
||||
listening sockets.
|
||||
|
||||
*) Bugfix: nginx did not escape """, "<", ">", "\", "^", "`", "{", "|",
|
||||
and "}" characters when proxying with changed URI.
|
||||
|
||||
*) Bugfix: SSL variables might be empty when used in logs; the bug had
|
||||
appeared in 1.19.5.
|
||||
|
||||
*) Bugfix: keepalive connections with gRPC backends might not be closed
|
||||
after receiving a GOAWAY frame.
|
||||
|
||||
*) Bugfix: backend SSL connections in the stream module might hang after
|
||||
an SSL handshake.
|
||||
|
||||
*) Bugfix: SSL connections with gRPC backends might hang if select,
|
||||
poll, or /dev/poll methods were used.
|
||||
|
||||
*) Bugfix: in the $content_length variable when using chunked transfer
|
||||
encoding.
|
||||
|
||||
*) Bugfix: requests might hang when using HTTP/2 and the "aio_write"
|
||||
directive.
|
||||
*) Bugfix: reduced memory consumption for long-lived requests when
|
||||
proxying with more than 64 buffers.
|
||||
|
||||
|
||||
Changes with nginx 1.20.1 25 May 2021
|
||||
Changes with nginx 1.21.0 25 May 2021
|
||||
|
||||
*) Security: 1-byte memory overwrite might occur during DNS server
|
||||
response processing if the "resolver" directive was used, allowing an
|
||||
|
|
@ -30,10 +146,24 @@ Changes with nginx 1.20.1 25 May 2021
|
|||
cause worker process crash or, potentially, arbitrary code execution
|
||||
(CVE-2021-23017).
|
||||
|
||||
*) Feature: variables support in the "proxy_ssl_certificate",
|
||||
"proxy_ssl_certificate_key" "grpc_ssl_certificate",
|
||||
"grpc_ssl_certificate_key", "uwsgi_ssl_certificate", and
|
||||
"uwsgi_ssl_certificate_key" directives.
|
||||
|
||||
Changes with nginx 1.20.0 20 Apr 2021
|
||||
*) Feature: the "max_errors" directive in the mail proxy module.
|
||||
|
||||
*) 1.20.x stable branch.
|
||||
*) Feature: the mail proxy module supports POP3 and IMAP pipelining.
|
||||
|
||||
*) Feature: the "fastopen" parameter of the "listen" directive in the
|
||||
stream module.
|
||||
Thanks to Anbang Wen.
|
||||
|
||||
*) Bugfix: special characters were not escaped during automatic redirect
|
||||
with appended trailing slash.
|
||||
|
||||
*) Bugfix: connections with clients in the mail proxy module might be
|
||||
closed unexpectedly when using SMTP pipelining.
|
||||
|
||||
|
||||
Changes with nginx 1.19.10 13 Apr 2021
|
||||
|
|
|
|||
164
CHANGES.ru
164
CHANGES.ru
|
|
@ -1,28 +1,148 @@
|
|||
|
||||
Изменения в nginx 1.20.2 16.11.2021
|
||||
Изменения в nginx 1.22.0 24.05.2022
|
||||
|
||||
*) Стабильная ветка 1.22.x.
|
||||
|
||||
|
||||
Изменения в nginx 1.21.6 25.01.2022
|
||||
|
||||
*) Исправление: при использование EPOLLEXCLUSIVE на Linux распределение
|
||||
клиентских соединений между рабочими процессами было неравномерным.
|
||||
|
||||
*) Исправление: во время плавного завершения старых рабочих процессов
|
||||
nginx возвращал в ответах строку заголовка "Connection: keep-alive".
|
||||
|
||||
*) Исправление: в директиве ssl_session_ticket_key при использовании
|
||||
TLSv1.3.
|
||||
|
||||
|
||||
Изменения в nginx 1.21.5 28.12.2021
|
||||
|
||||
*) Изменение: теперь nginx по умолчанию собирается с библиотекой PCRE2.
|
||||
|
||||
*) Изменение: теперь nginx всегда использует sendfile(SF_NODISKIO) на
|
||||
FreeBSD.
|
||||
|
||||
*) Добавление: поддержка sendfile(SF_NOCACHE) на FreeBSD.
|
||||
|
||||
*) Добавление: переменная $ssl_curve.
|
||||
|
||||
*) Исправление: при использовании HTTP/2 без SSL вместе с директивами
|
||||
sendfile и aio соединения могли зависать.
|
||||
|
||||
|
||||
Изменения в nginx 1.21.4 02.11.2021
|
||||
|
||||
*) Изменение: поддержка NPN вместо ALPN для установления
|
||||
HTTP/2-соединений упразднена.
|
||||
|
||||
*) Изменение: теперь nginx закрывает SSL соединение, если клиент
|
||||
использует ALPN, но nginx не поддерживает ни один из присланных
|
||||
клиентом протоколов.
|
||||
|
||||
*) Изменение: в директиве sendfile_max_chunk значение по умолчанию
|
||||
изменено на 2 мегабайта.
|
||||
|
||||
*) Добавление: директива proxy_half_close в модуле stream.
|
||||
|
||||
*) Добавление: директива ssl_alpn в модуле stream.
|
||||
|
||||
*) Добавление: переменная $ssl_alpn_protocol.
|
||||
|
||||
*) Добавление: поддержка SSL_sendfile() при использовании OpenSSL 3.0.
|
||||
|
||||
*) Добавление: директива mp4_start_key_frame в модуле
|
||||
ngx_http_mp4_module.
|
||||
Спасибо Tracey Jaquith.
|
||||
|
||||
*) Исправление: в переменной $content_length при использовании chunked
|
||||
transfer encoding.
|
||||
|
||||
*) Исправление: при получении ответа некорректной длины от проксируемого
|
||||
бэкенда nginx мог тем не менее закэшировать соединение.
|
||||
Спасибо Awdhesh Mathpal.
|
||||
|
||||
*) Исправление: некорректные заголовки от бэкендов логгировались на
|
||||
уровне info вместо error; ошибка появилась в 1.21.1.
|
||||
|
||||
*) Исправление: при использовании HTTP/2 и директивы aio_write запросы
|
||||
могли зависать.
|
||||
|
||||
|
||||
Изменения в nginx 1.21.3 07.09.2021
|
||||
|
||||
*) Изменение: оптимизация чтения тела запроса при использовании HTTP/2.
|
||||
|
||||
*) Исправление: во внутреннем API для обработки тела запроса при
|
||||
использовании HTTP/2 и буферизации обрабатываемых данных.
|
||||
|
||||
|
||||
Изменения в nginx 1.21.2 31.08.2021
|
||||
|
||||
*) Изменение: теперь nginx возвращает ошибку, если в запросе по
|
||||
протоколу HTTP/1.0 присутствует строка заголовка "Transfer-Encoding".
|
||||
|
||||
*) Изменение: экспортные шифры больше не поддерживаются.
|
||||
|
||||
*) Добавление: совместимость с OpenSSL 3.0.
|
||||
|
||||
*) Добавление: теперь серверу аутентификации почтового прокси-сервера
|
||||
передаются строки заголовка "Auth-SSL-Protocol" и "Auth-SSL-Cipher".
|
||||
Спасибо Rob Mueller.
|
||||
|
||||
*) Добавление: API для обработки тела запроса теперь позволяет
|
||||
буферизировать обрабатываемые данные.
|
||||
|
||||
*) Исправление: SSL-соединения к бэкендам в модуле stream могли зависать
|
||||
после SSL handshake.
|
||||
|
||||
*) Исправление: уровень безопасности, доступный в OpenSSL 1.1.0 и новее,
|
||||
не учитывался при загрузке сертификатов сервера, если был задан через
|
||||
"@SECLEVEL=N" в директиве ssl_ciphers.
|
||||
|
||||
*) Исправление: SSL-соединения с gRPC-бэкендами могли зависать, если
|
||||
использовались методы select, poll или /dev/poll.
|
||||
|
||||
*) Исправление: при использовании HTTP/2 тело запроса всегда
|
||||
записывалось на диск, если в запросе не было строки заголовка
|
||||
"Content-Length".
|
||||
|
||||
|
||||
Изменения в nginx 1.21.1 06.07.2021
|
||||
|
||||
*) Изменение: теперь nginx для метода CONNECT всегда возвращает ошибку.
|
||||
|
||||
*) Изменение: теперь nginx всегда возвращает ошибку, если в запросе
|
||||
одновременно присутствуют строки заголовка "Content-Length" и
|
||||
"Transfer-Encoding".
|
||||
|
||||
*) Изменение: теперь nginx всегда возвращает ошибку, если в строке
|
||||
запроса используются пробелы или управляющие символы.
|
||||
|
||||
*) Изменение: теперь nginx всегда возвращает ошибку, если в имени
|
||||
заголовка используются пробелы или управляющие символы.
|
||||
|
||||
*) Изменение: теперь nginx всегда возвращает ошибку, если в строке
|
||||
"Host" заголовка запроса используются пробелы или управляющие
|
||||
символы.
|
||||
|
||||
*) Изменение: оптимизация тестирования конфигурации при использовании
|
||||
большого количества listen-сокетов.
|
||||
|
||||
*) Исправление: nginx не экранировал символы """, "<", ">", "\", "^",
|
||||
"`", "{", "|", и "}" при проксировании с изменением URI запроса.
|
||||
|
||||
*) Исправление: SSL-переменные могли быть пустыми при записи в лог;
|
||||
ошибка появилась в 1.19.5.
|
||||
|
||||
*) Исправление: keepalive-соединения с gRPC-бэкендами могли не
|
||||
закрываться после получения GOAWAY-фрейма.
|
||||
|
||||
*) Исправление: SSL-соединения к бэкендам в модуле stream могли зависать
|
||||
после SSL handshake.
|
||||
|
||||
*) Исправление: SSL-соединения с gRPC-бэкендами могли зависать, если
|
||||
использовались методы select, poll или /dev/poll.
|
||||
|
||||
*) Исправление: в переменной $content_length при использовании chunked
|
||||
transfer encoding.
|
||||
|
||||
*) Исправление: при использовании HTTP/2 и директивы aio_write запросы
|
||||
могли зависать.
|
||||
*) Исправление: уменьшено потребление памяти для долгоживущих запросов
|
||||
при проксировании с использованием более 64 буферов.
|
||||
|
||||
|
||||
Изменения в nginx 1.20.1 25.05.2021
|
||||
Изменения в nginx 1.21.0 25.05.2021
|
||||
|
||||
*) Безопасность: при использовании директивы resolver во время обработки
|
||||
ответа DNS-сервера могла происходить перезапись одного байта памяти,
|
||||
|
|
@ -30,10 +150,24 @@
|
|||
от DNS-сервера, вызвать падение рабочего процесса или, потенциально,
|
||||
выполнение произвольного кода (CVE-2021-23017).
|
||||
|
||||
*) Добавление: директивы proxy_ssl_certificate,
|
||||
proxy_ssl_certificate_key, grpc_ssl_certificate,
|
||||
grpc_ssl_certificate_key, uwsgi_ssl_certificate и
|
||||
uwsgi_ssl_certificate_key поддерживают переменные.
|
||||
|
||||
Изменения в nginx 1.20.0 20.04.2021
|
||||
*) Добавление: директива max_errors в почтовом прокси-сервере.
|
||||
|
||||
*) Стабильная ветка 1.20.x.
|
||||
*) Добавление: почтовый прокси-сервер поддерживает POP3 и IMAP
|
||||
pipelining.
|
||||
|
||||
*) Добавление: параметр fastopen директивы listen в модуле stream.
|
||||
Спасибо Anbang Wen.
|
||||
|
||||
*) Исправление: специальные символы не экранировались при автоматическом
|
||||
перенаправлении с добавлением завершающего слэша.
|
||||
|
||||
*) Исправление: при использовании SMTP pipelining соединения с клиентами
|
||||
в почтовом прокси-сервере могли неожиданно закрываться.
|
||||
|
||||
|
||||
Изменения в nginx 1.19.10 13.04.2021
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2021 Igor Sysoev
|
||||
* Copyright (C) 2011-2021 Nginx, Inc.
|
||||
* Copyright (C) 2011-2022 Nginx, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -4,87 +4,62 @@
|
|||
|
||||
|
||||
if [ $PCRE != NONE ]; then
|
||||
CORE_INCS="$CORE_INCS $PCRE"
|
||||
|
||||
case "$NGX_CC_NAME" in
|
||||
if [ -f $PCRE/src/pcre2.h.generic ]; then
|
||||
|
||||
msvc | owc | bcc)
|
||||
have=NGX_PCRE . auto/have
|
||||
PCRE_LIBRARY=PCRE2
|
||||
|
||||
have=NGX_PCRE . auto/have
|
||||
have=NGX_PCRE2 . auto/have
|
||||
|
||||
if [ "$NGX_PLATFORM" = win32 ]; then
|
||||
have=PCRE2_STATIC . auto/have
|
||||
fi
|
||||
|
||||
CORE_INCS="$CORE_INCS $PCRE/src/"
|
||||
CORE_DEPS="$CORE_DEPS $PCRE/src/pcre2.h"
|
||||
|
||||
case "$NGX_CC_NAME" in
|
||||
|
||||
msvc)
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/src/pcre2-8.lib"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/src/pcre2-8.lib"
|
||||
;;
|
||||
|
||||
*)
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre2-8.a"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre2-8.a"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
else
|
||||
|
||||
PCRE_LIBRARY=PCRE
|
||||
|
||||
have=NGX_PCRE . auto/have
|
||||
|
||||
if [ "$NGX_PLATFORM" = win32 ]; then
|
||||
have=PCRE_STATIC . auto/have
|
||||
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/pcre.lib"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib"
|
||||
;;
|
||||
fi
|
||||
|
||||
icc)
|
||||
have=NGX_PCRE . auto/have
|
||||
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
|
||||
CORE_INCS="$CORE_INCS $PCRE"
|
||||
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
|
||||
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
|
||||
case "$NGX_CC_NAME" in
|
||||
|
||||
echo $ngx_n "checking for PCRE library ...$ngx_c"
|
||||
msvc | owc | bcc)
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/pcre.lib"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib"
|
||||
;;
|
||||
|
||||
if [ -f $PCRE/pcre.h ]; then
|
||||
ngx_pcre_ver=`grep PCRE_MAJOR $PCRE/pcre.h \
|
||||
| sed -e 's/^.*PCRE_MAJOR.* \(.*\)$/\1/'`
|
||||
|
||||
else if [ -f $PCRE/configure.in ]; then
|
||||
ngx_pcre_ver=`grep PCRE_MAJOR= $PCRE/configure.in \
|
||||
| sed -e 's/^.*=\(.*\)$/\1/'`
|
||||
|
||||
else
|
||||
ngx_pcre_ver=`grep pcre_major, $PCRE/configure.ac \
|
||||
| sed -e 's/^.*pcre_major,.*\[\(.*\)\].*$/\1/'`
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " $ngx_pcre_ver major version found"
|
||||
|
||||
# to allow -ipo optimization we link with the *.o but not library
|
||||
|
||||
case "$ngx_pcre_ver" in
|
||||
4|5)
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre.o"
|
||||
;;
|
||||
|
||||
6)
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_chartables.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_compile.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_exec.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_fullinfo.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_globals.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_tables.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_try_flipped.o"
|
||||
;;
|
||||
|
||||
*)
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_chartables.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_compile.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_exec.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_fullinfo.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_globals.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_tables.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_try_flipped.o"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/pcre_newline.o"
|
||||
;;
|
||||
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
have=NGX_PCRE . auto/have
|
||||
|
||||
if [ "$NGX_PLATFORM" = win32 ]; then
|
||||
have=PCRE_STATIC . auto/have
|
||||
fi
|
||||
|
||||
CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a"
|
||||
;;
|
||||
|
||||
esac
|
||||
*)
|
||||
LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
|
||||
CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a"
|
||||
;;
|
||||
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ $PCRE_JIT = YES ]; then
|
||||
have=NGX_HAVE_PCRE_JIT . auto/have
|
||||
|
|
@ -94,8 +69,48 @@ if [ $PCRE != NONE ]; then
|
|||
else
|
||||
|
||||
if [ "$NGX_PLATFORM" != win32 ]; then
|
||||
|
||||
PCRE=NO
|
||||
fi
|
||||
|
||||
if [ $PCRE = NO -a $PCRE2 != DISABLED ]; then
|
||||
|
||||
ngx_feature="PCRE2 library"
|
||||
ngx_feature_name="NGX_PCRE2"
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include <pcre2.h>"
|
||||
ngx_feature_path=
|
||||
ngx_feature_libs="-lpcre2-8"
|
||||
ngx_feature_test="pcre2_code *re;
|
||||
re = pcre2_compile(NULL, 0, 0, NULL, NULL, NULL);
|
||||
if (re == NULL) return 1"
|
||||
. auto/feature
|
||||
|
||||
if [ $ngx_found = no ]; then
|
||||
|
||||
# pcre2-config
|
||||
|
||||
ngx_pcre2_prefix=`pcre2-config --prefix 2>/dev/null`
|
||||
|
||||
if [ -n "$ngx_pcre2_prefix" ]; then
|
||||
ngx_feature="PCRE2 library in $ngx_pcre2_prefix"
|
||||
ngx_feature_path=`pcre2-config --cflags \
|
||||
| sed -n -e 's/.*-I *\([^ ][^ ]*\).*/\1/p'`
|
||||
ngx_feature_libs=`pcre2-config --libs8`
|
||||
. auto/feature
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $ngx_found = yes ]; then
|
||||
have=NGX_PCRE . auto/have
|
||||
CORE_INCS="$CORE_INCS $ngx_feature_path"
|
||||
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
|
||||
PCRE=YES
|
||||
PCRE_LIBRARY=PCRE2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $PCRE = NO ]; then
|
||||
|
||||
ngx_feature="PCRE library"
|
||||
ngx_feature_name="NGX_PCRE"
|
||||
|
|
@ -171,6 +186,7 @@ else
|
|||
CORE_INCS="$CORE_INCS $ngx_feature_path"
|
||||
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
|
||||
PCRE=YES
|
||||
PCRE_LIBRARY=PCRE
|
||||
fi
|
||||
|
||||
if [ $PCRE = YES ]; then
|
||||
|
|
|
|||
|
|
@ -3,36 +3,138 @@
|
|||
# Copyright (C) Nginx, Inc.
|
||||
|
||||
|
||||
case "$NGX_CC_NAME" in
|
||||
if [ $PCRE_LIBRARY = PCRE2 ]; then
|
||||
|
||||
msvc)
|
||||
ngx_makefile=makefile.msvc
|
||||
ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
|
||||
ngx_pcre="PCRE=\"$PCRE\""
|
||||
;;
|
||||
# PCRE2
|
||||
|
||||
owc)
|
||||
ngx_makefile=makefile.owc
|
||||
ngx_opt="CPU_OPT=\"$CPU_OPT\""
|
||||
ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
;;
|
||||
if [ $NGX_CC_NAME = msvc ]; then
|
||||
|
||||
bcc)
|
||||
ngx_makefile=makefile.bcc
|
||||
ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
|
||||
ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
;;
|
||||
# With PCRE2, it is not possible to compile all sources.
|
||||
# Since list of source files changes between versions, we
|
||||
# test files which might not be present.
|
||||
|
||||
*)
|
||||
ngx_makefile=
|
||||
;;
|
||||
ngx_pcre_srcs="pcre2_auto_possess.c \
|
||||
pcre2_chartables.c \
|
||||
pcre2_compile.c \
|
||||
pcre2_config.c \
|
||||
pcre2_context.c \
|
||||
pcre2_dfa_match.c \
|
||||
pcre2_error.c \
|
||||
pcre2_jit_compile.c \
|
||||
pcre2_maketables.c \
|
||||
pcre2_match.c \
|
||||
pcre2_match_data.c \
|
||||
pcre2_newline.c \
|
||||
pcre2_ord2utf.c \
|
||||
pcre2_pattern_info.c \
|
||||
pcre2_string_utils.c \
|
||||
pcre2_study.c \
|
||||
pcre2_substitute.c \
|
||||
pcre2_substring.c \
|
||||
pcre2_tables.c \
|
||||
pcre2_ucd.c \
|
||||
pcre2_valid_utf.c \
|
||||
pcre2_xclass.c"
|
||||
|
||||
esac
|
||||
ngx_pcre_test="pcre2_convert.c \
|
||||
pcre2_extuni.c \
|
||||
pcre2_find_bracket.c \
|
||||
pcre2_script_run.c \
|
||||
pcre2_serialize.c"
|
||||
|
||||
for ngx_src in $ngx_pcre_test
|
||||
do
|
||||
if [ -f $PCRE/src/$ngx_src ]; then
|
||||
ngx_pcre_srcs="$ngx_pcre_srcs $ngx_src"
|
||||
fi
|
||||
done
|
||||
|
||||
ngx_pcre_objs=`echo $ngx_pcre_srcs \
|
||||
| sed -e "s#\([^ ]*\.\)c#\1$ngx_objext#g"`
|
||||
|
||||
ngx_pcre_srcs=`echo $ngx_pcre_srcs \
|
||||
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g"`
|
||||
ngx_pcre_objs=`echo $ngx_pcre_objs \
|
||||
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g"`
|
||||
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
|
||||
PCRE_CFLAGS = -O2 -Ob1 -Oi -Gs $LIBC $CPU_OPT
|
||||
PCRE_FLAGS = -DHAVE_CONFIG_H -DPCRE2_STATIC -DPCRE2_CODE_UNIT_WIDTH=8 \\
|
||||
-DHAVE_MEMMOVE
|
||||
|
||||
PCRE_SRCS = $ngx_pcre_srcs
|
||||
PCRE_OBJS = $ngx_pcre_objs
|
||||
|
||||
$PCRE/src/pcre2.h:
|
||||
cd $PCRE/src \\
|
||||
&& copy /y config.h.generic config.h \\
|
||||
&& copy /y pcre2.h.generic pcre2.h \\
|
||||
&& copy /y pcre2_chartables.c.dist pcre2_chartables.c
|
||||
|
||||
$PCRE/src/pcre2-8.lib: $PCRE/src/pcre2.h $NGX_MAKEFILE
|
||||
cd $PCRE/src \\
|
||||
&& cl -nologo -c \$(PCRE_CFLAGS) -I . \$(PCRE_FLAGS) \$(PCRE_SRCS) \\
|
||||
&& link -lib -out:pcre2-8.lib -verbose:lib \$(PCRE_OBJS)
|
||||
|
||||
END
|
||||
|
||||
else
|
||||
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
|
||||
$PCRE/src/pcre2.h: $PCRE/Makefile
|
||||
|
||||
$PCRE/Makefile: $NGX_MAKEFILE
|
||||
cd $PCRE \\
|
||||
&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
|
||||
&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
|
||||
./configure --disable-shared $PCRE_CONF_OPT
|
||||
|
||||
$PCRE/.libs/libpcre2-8.a: $PCRE/Makefile
|
||||
cd $PCRE \\
|
||||
&& \$(MAKE) libpcre2-8.la
|
||||
|
||||
END
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if [ -n "$ngx_makefile" ]; then
|
||||
else
|
||||
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
# PCRE
|
||||
|
||||
case "$NGX_CC_NAME" in
|
||||
|
||||
msvc)
|
||||
ngx_makefile=makefile.msvc
|
||||
ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
|
||||
ngx_pcre="PCRE=\"$PCRE\""
|
||||
;;
|
||||
|
||||
owc)
|
||||
ngx_makefile=makefile.owc
|
||||
ngx_opt="CPU_OPT=\"$CPU_OPT\""
|
||||
ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
;;
|
||||
|
||||
bcc)
|
||||
ngx_makefile=makefile.bcc
|
||||
ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
|
||||
ngx_pcre=`echo \-DPCRE=\"$PCRE\" \
|
||||
| sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
;;
|
||||
|
||||
*)
|
||||
ngx_makefile=
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
|
||||
if [ -n "$ngx_makefile" ]; then
|
||||
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
|
||||
`echo "$PCRE/pcre.lib: $PCRE/pcre.h $NGX_MAKEFILE" \
|
||||
| sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
|
|
@ -43,9 +145,9 @@ if [ -n "$ngx_makefile" ]; then
|
|||
|
||||
END
|
||||
|
||||
else
|
||||
else
|
||||
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
cat << END >> $NGX_MAKEFILE
|
||||
|
||||
$PCRE/pcre.h: $PCRE/Makefile
|
||||
|
||||
|
|
@ -61,4 +163,6 @@ $PCRE/.libs/libpcre.a: $PCRE/Makefile
|
|||
|
||||
END
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ if [ $HTTP = YES ]; then
|
|||
fi
|
||||
|
||||
|
||||
if [ $HTTP_V2 = YES ]; then
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_HUFF_SRCS"
|
||||
fi
|
||||
|
||||
|
||||
# the module order is important
|
||||
# ngx_http_static_module
|
||||
# ngx_http_gzip_static_module
|
||||
|
|
@ -414,8 +419,6 @@ if [ $HTTP = YES ]; then
|
|||
ngx_module_srcs="src/http/v2/ngx_http_v2.c \
|
||||
src/http/v2/ngx_http_v2_table.c \
|
||||
src/http/v2/ngx_http_v2_encode.c \
|
||||
src/http/v2/ngx_http_v2_huff_decode.c \
|
||||
src/http/v2/ngx_http_v2_huff_encode.c \
|
||||
src/http/v2/ngx_http_v2_module.c"
|
||||
ngx_module_libs=
|
||||
ngx_module_link=$HTTP_V2
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ PCRE=NONE
|
|||
PCRE_OPT=
|
||||
PCRE_CONF_OPT=
|
||||
PCRE_JIT=NO
|
||||
PCRE2=YES
|
||||
|
||||
USE_OPENSSL=NO
|
||||
OPENSSL=NONE
|
||||
|
|
@ -357,6 +358,7 @@ use the \"--with-mail_ssl_module\" option instead"
|
|||
--with-pcre=*) PCRE="$value" ;;
|
||||
--with-pcre-opt=*) PCRE_OPT="$value" ;;
|
||||
--with-pcre-jit) PCRE_JIT=YES ;;
|
||||
--without-pcre2) PCRE2=DISABLED ;;
|
||||
|
||||
--with-openssl=*) OPENSSL="$value" ;;
|
||||
--with-openssl-opt=*) OPENSSL_OPT="$value" ;;
|
||||
|
|
@ -573,6 +575,7 @@ cat << END
|
|||
--with-pcre=DIR set path to PCRE library sources
|
||||
--with-pcre-opt=OPTIONS set additional build options for PCRE
|
||||
--with-pcre-jit build PCRE with JIT compilation support
|
||||
--without-pcre2 do not use PCRE2 library
|
||||
|
||||
--with-zlib=DIR set path to zlib library sources
|
||||
--with-zlib-opt=OPTIONS set additional build options for zlib
|
||||
|
|
|
|||
|
|
@ -44,12 +44,10 @@ if [ $osreldate -gt 300007 ]; then
|
|||
CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
|
||||
fi
|
||||
|
||||
if [ $NGX_FILE_AIO = YES ]; then
|
||||
if [ $osreldate -gt 502103 ]; then
|
||||
echo " + sendfile()'s SF_NODISKIO found"
|
||||
if [ $osreldate -gt 1100093 ]; then
|
||||
echo " + sendfile()'s SF_NODISKIO found"
|
||||
|
||||
have=NGX_HAVE_AIO_SENDFILE . auto/have
|
||||
fi
|
||||
have=NGX_HAVE_SENDFILE_NODISKIO . auto/have
|
||||
fi
|
||||
|
||||
# POSIX semaphores
|
||||
|
|
|
|||
|
|
@ -255,3 +255,6 @@ NGX_WIN32_RC="src/os/win32/nginx.rc"
|
|||
|
||||
|
||||
HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
|
||||
|
||||
HTTP_HUFF_SRCS="src/http/ngx_http_huff_decode.c
|
||||
src/http/ngx_http_huff_encode.c"
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ if [ $USE_PCRE = DISABLED ]; then
|
|||
|
||||
else
|
||||
case $PCRE in
|
||||
YES) echo " + using system PCRE library" ;;
|
||||
YES) echo " + using system $PCRE_LIBRARY library" ;;
|
||||
NONE) echo " + PCRE library is not used" ;;
|
||||
*) echo " + using PCRE library: $PCRE" ;;
|
||||
*) echo " + using $PCRE_LIBRARY library: $PCRE" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ types {
|
|||
text/vnd.wap.wml wml;
|
||||
text/x-component htc;
|
||||
|
||||
image/avif avif;
|
||||
image/png png;
|
||||
image/svg+xml svg svgz;
|
||||
image/tiff tif tiff;
|
||||
|
|
@ -51,6 +52,7 @@ types {
|
|||
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
docx;
|
||||
application/vnd.wap.wmlc wmlc;
|
||||
application/wasm wasm;
|
||||
application/x-7z-compressed 7z;
|
||||
application/x-cocoa cco;
|
||||
application/x-java-archive-diff jardiff;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ if exists("b:current_syntax")
|
|||
finish
|
||||
end
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" general syntax
|
||||
|
||||
if has("patch-7.4.1142")
|
||||
|
|
@ -152,6 +155,8 @@ syn keyword ngxDirective contained auth_jwt_header_set
|
|||
syn keyword ngxDirective contained auth_jwt_key_file
|
||||
syn keyword ngxDirective contained auth_jwt_key_request
|
||||
syn keyword ngxDirective contained auth_jwt_leeway
|
||||
syn keyword ngxDirective contained auth_jwt_require
|
||||
syn keyword ngxDirective contained auth_jwt_type
|
||||
syn keyword ngxDirective contained auth_request
|
||||
syn keyword ngxDirective contained auth_request_set
|
||||
syn keyword ngxDirective contained autoindex
|
||||
|
|
@ -332,16 +337,24 @@ syn keyword ngxDirective contained index
|
|||
syn keyword ngxDirective contained iocp_threads
|
||||
syn keyword ngxDirective contained ip_hash
|
||||
syn keyword ngxDirective contained js_access
|
||||
syn keyword ngxDirective contained js_body_filter
|
||||
syn keyword ngxDirective contained js_content
|
||||
syn keyword ngxDirective contained js_fetch_ciphers
|
||||
syn keyword ngxDirective contained js_fetch_protocols
|
||||
syn keyword ngxDirective contained js_fetch_trusted_certificate
|
||||
syn keyword ngxDirective contained js_fetch_verify_depth
|
||||
syn keyword ngxDirective contained js_filter
|
||||
syn keyword ngxDirective contained js_header_filter
|
||||
syn keyword ngxDirective contained js_import
|
||||
syn keyword ngxDirective contained js_include
|
||||
syn keyword ngxDirective contained js_path
|
||||
syn keyword ngxDirective contained js_preread
|
||||
syn keyword ngxDirective contained js_set
|
||||
syn keyword ngxDirective contained js_var
|
||||
syn keyword ngxDirective contained keepalive
|
||||
syn keyword ngxDirective contained keepalive_disable
|
||||
syn keyword ngxDirective contained keepalive_requests
|
||||
syn keyword ngxDirective contained keepalive_time
|
||||
syn keyword ngxDirective contained keepalive_timeout
|
||||
syn keyword ngxDirective contained keyval
|
||||
syn keyword ngxDirective contained keyval_zone
|
||||
|
|
@ -373,6 +386,7 @@ syn keyword ngxDirective contained log_subrequest
|
|||
syn keyword ngxDirective contained map_hash_bucket_size
|
||||
syn keyword ngxDirective contained map_hash_max_size
|
||||
syn keyword ngxDirective contained master_process
|
||||
syn keyword ngxDirective contained max_errors
|
||||
syn keyword ngxDirective contained max_ranges
|
||||
syn keyword ngxDirective contained memcached_bind
|
||||
syn keyword ngxDirective contained memcached_buffer_size
|
||||
|
|
@ -396,6 +410,7 @@ syn keyword ngxDirective contained mp4_buffer_size
|
|||
syn keyword ngxDirective contained mp4_limit_rate
|
||||
syn keyword ngxDirective contained mp4_limit_rate_after
|
||||
syn keyword ngxDirective contained mp4_max_buffer_size
|
||||
syn keyword ngxDirective contained mp4_start_key_frame
|
||||
syn keyword ngxDirective contained msie_padding
|
||||
syn keyword ngxDirective contained msie_refresh
|
||||
syn keyword ngxDirective contained multi_accept
|
||||
|
|
@ -452,6 +467,7 @@ syn keyword ngxDirective contained proxy_cookie_flags
|
|||
syn keyword ngxDirective contained proxy_cookie_path
|
||||
syn keyword ngxDirective contained proxy_download_rate
|
||||
syn keyword ngxDirective contained proxy_force_ranges
|
||||
syn keyword ngxDirective contained proxy_half_close
|
||||
syn keyword ngxDirective contained proxy_headers_hash_bucket_size
|
||||
syn keyword ngxDirective contained proxy_headers_hash_max_size
|
||||
syn keyword ngxDirective contained proxy_hide_header
|
||||
|
|
@ -591,6 +607,7 @@ syn keyword ngxDirective contained ssi_min_file_chunk
|
|||
syn keyword ngxDirective contained ssi_silent_errors
|
||||
syn keyword ngxDirective contained ssi_types
|
||||
syn keyword ngxDirective contained ssi_value_length
|
||||
syn keyword ngxDirective contained ssl_alpn
|
||||
syn keyword ngxDirective contained ssl_buffer_size
|
||||
syn keyword ngxDirective contained ssl_certificate
|
||||
syn keyword ngxDirective contained ssl_certificate_key
|
||||
|
|
@ -782,11 +799,15 @@ syn keyword ngxDirectiveThirdParty contained auth_digest_user_file
|
|||
syn keyword ngxDirectiveThirdParty contained auth_gss
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_allow_basic_fallback
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_authorized_principal
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_authorized_principal_regex
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_constrained_delegation
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_delegate_credentials
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_force_realm
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_format_full
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_keytab
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_map_to_local
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_realm
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_service_ccache
|
||||
syn keyword ngxDirectiveThirdParty contained auth_gss_service_name
|
||||
|
||||
" LDAP Authentication
|
||||
|
|
@ -963,7 +984,6 @@ syn keyword ngxDirectiveThirdParty contained fancyindex_hide_parent_dir
|
|||
syn keyword ngxDirectiveThirdParty contained fancyindex_hide_symlinks
|
||||
syn keyword ngxDirectiveThirdParty contained fancyindex_ignore
|
||||
syn keyword ngxDirectiveThirdParty contained fancyindex_localtime
|
||||
syn keyword ngxDirectiveThirdParty contained fancyindex_name_length
|
||||
syn keyword ngxDirectiveThirdParty contained fancyindex_show_dotfiles
|
||||
syn keyword ngxDirectiveThirdParty contained fancyindex_show_path
|
||||
syn keyword ngxDirectiveThirdParty contained fancyindex_time_format
|
||||
|
|
@ -1053,7 +1073,9 @@ syn keyword ngxDirectiveThirdParty contained nchan_publisher_upstream_request
|
|||
syn keyword ngxDirectiveThirdParty contained nchan_pubsub
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_pubsub_channel_id
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_pubsub_location
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_cluster_check_interval
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_connect_timeout
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_discovered_ip_range_blacklist
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_fakesub_timer_interval
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_idle_channel_cache_timeout
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_namespace
|
||||
|
|
@ -1061,12 +1083,29 @@ syn keyword ngxDirectiveThirdParty contained nchan_redis_nostore_fastpublish
|
|||
syn keyword ngxDirectiveThirdParty contained nchan_redis_optimize_target
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_pass
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_pass_inheritable
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_password
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ping_interval
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_publish_msgpacked_max_size
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_server
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_ciphers
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_client_certificate
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_client_certificate_key
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_server_name
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_trusted_certificate
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_trusted_certificate_path
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_ssl_verify_certificate
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_storage_mode
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_subscribe_weights
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls_ciphers
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls_client_certificate
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls_server_name
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls_trusted_certificate
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls_trusted_certificate_path
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_tls_verify_certificate
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_url
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_username
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_redis_wait_after_connecting
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_shared_memory_size
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_storage_engine
|
||||
|
|
@ -1080,6 +1119,8 @@ syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_mess
|
|||
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_info
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_info_string
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_location
|
||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_message_id_custom_etag_header
|
||||
|
|
@ -1377,6 +1418,7 @@ syn keyword ngxDirectiveThirdParty contained lua_socket_read_timeout
|
|||
syn keyword ngxDirectiveThirdParty contained lua_socket_send_lowat
|
||||
syn keyword ngxDirectiveThirdParty contained lua_socket_send_timeout
|
||||
syn keyword ngxDirectiveThirdParty contained lua_ssl_ciphers
|
||||
syn keyword ngxDirectiveThirdParty contained lua_ssl_conf_command
|
||||
syn keyword ngxDirectiveThirdParty contained lua_ssl_crl
|
||||
syn keyword ngxDirectiveThirdParty contained lua_ssl_protocols
|
||||
syn keyword ngxDirectiveThirdParty contained lua_ssl_trusted_certificate
|
||||
|
|
@ -1384,6 +1426,7 @@ syn keyword ngxDirectiveThirdParty contained lua_ssl_verify_depth
|
|||
syn keyword ngxDirectiveThirdParty contained lua_thread_cache_max_entries
|
||||
syn keyword ngxDirectiveThirdParty contained lua_transform_underscores_in_response_headers
|
||||
syn keyword ngxDirectiveThirdParty contained lua_use_default_type
|
||||
syn keyword ngxDirectiveThirdParty contained lua_worker_thread_vm_pool_size
|
||||
syn keyword ngxDirectiveThirdParty contained rewrite_by_lua
|
||||
syn keyword ngxDirectiveThirdParty contained rewrite_by_lua_block
|
||||
syn keyword ngxDirectiveThirdParty contained rewrite_by_lua_file
|
||||
|
|
@ -1393,6 +1436,8 @@ syn keyword ngxDirectiveThirdParty contained set_by_lua_block
|
|||
syn keyword ngxDirectiveThirdParty contained set_by_lua_file
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_certificate_by_lua_block
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_certificate_by_lua_file
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_client_hello_by_lua_block
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_client_hello_by_lua_file
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_session_fetch_by_lua_block
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_session_fetch_by_lua_file
|
||||
syn keyword ngxDirectiveThirdParty contained ssl_session_store_by_lua_block
|
||||
|
|
@ -1711,15 +1756,18 @@ syn keyword ngxDirectiveThirdParty contained set_base32_alphabet
|
|||
syn keyword ngxDirectiveThirdParty contained set_base32_padding
|
||||
syn keyword ngxDirectiveThirdParty contained set_decode_base32
|
||||
syn keyword ngxDirectiveThirdParty contained set_decode_base64
|
||||
syn keyword ngxDirectiveThirdParty contained set_decode_base64url
|
||||
syn keyword ngxDirectiveThirdParty contained set_decode_hex
|
||||
syn keyword ngxDirectiveThirdParty contained set_encode_base32
|
||||
syn keyword ngxDirectiveThirdParty contained set_encode_base64
|
||||
syn keyword ngxDirectiveThirdParty contained set_encode_base64url
|
||||
syn keyword ngxDirectiveThirdParty contained set_encode_hex
|
||||
syn keyword ngxDirectiveThirdParty contained set_escape_uri
|
||||
syn keyword ngxDirectiveThirdParty contained set_formatted_gmt_time
|
||||
syn keyword ngxDirectiveThirdParty contained set_formatted_local_time
|
||||
syn keyword ngxDirectiveThirdParty contained set_hashed_upstream
|
||||
syn keyword ngxDirectiveThirdParty contained set_hmac_sha1
|
||||
syn keyword ngxDirectiveThirdParty contained set_hmac_sha256
|
||||
syn keyword ngxDirectiveThirdParty contained set_if_empty
|
||||
syn keyword ngxDirectiveThirdParty contained set_local_today
|
||||
syn keyword ngxDirectiveThirdParty contained set_misc_base32_padding
|
||||
|
|
@ -1841,6 +1889,7 @@ syn keyword ngxDirectiveThirdParty contained vod_notification_uri
|
|||
syn keyword ngxDirectiveThirdParty contained vod_open_file_thread_pool
|
||||
syn keyword ngxDirectiveThirdParty contained vod_output_buffer_pool
|
||||
syn keyword ngxDirectiveThirdParty contained vod_parse_hdlr_name
|
||||
syn keyword ngxDirectiveThirdParty contained vod_parse_udta_name
|
||||
syn keyword ngxDirectiveThirdParty contained vod_path_response_postfix
|
||||
syn keyword ngxDirectiveThirdParty contained vod_path_response_prefix
|
||||
syn keyword ngxDirectiveThirdParty contained vod_performance_counters
|
||||
|
|
@ -2368,9 +2417,9 @@ syn keyword ngxDirectiveThirdParty contained websockify_send_timeout
|
|||
|
||||
" IP2Location Nginx
|
||||
" https://github.com/ip2location/ip2location-nginx
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_proxy
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_addresstype
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_areacode
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_category
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_city
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_country_long
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_country_short
|
||||
|
|
@ -2384,6 +2433,8 @@ syn keyword ngxDirectiveThirdParty contained ip2location_mcc
|
|||
syn keyword ngxDirectiveThirdParty contained ip2location_mnc
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_mobilebrand
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_netspeed
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_proxy
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_region
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_timezone
|
||||
syn keyword ngxDirectiveThirdParty contained ip2location_usagetype
|
||||
|
|
@ -2403,6 +2454,7 @@ syn keyword ngxDirectiveThirdParty contained ip2proxy_domain
|
|||
syn keyword ngxDirectiveThirdParty contained ip2proxy_isp
|
||||
syn keyword ngxDirectiveThirdParty contained ip2proxy_is_proxy
|
||||
syn keyword ngxDirectiveThirdParty contained ip2proxy_last_seen
|
||||
syn keyword ngxDirectiveThirdParty contained ip2proxy_provider
|
||||
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy
|
||||
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_recursive
|
||||
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_type
|
||||
|
|
@ -2436,4 +2488,7 @@ hi def link ngxDirectiveThirdPartyDeprecated Error
|
|||
hi def link ngxListenOptions Keyword
|
||||
hi def link ngxListenOptionsDeprecated Error
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
let b:current_syntax = "nginx"
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@
|
|||
<head>
|
||||
<title>Error</title>
|
||||
<style>
|
||||
body {
|
||||
width: 35em;
|
||||
margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif;
|
||||
}
|
||||
html { color-scheme: light dark; }
|
||||
body { width: 35em; margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@
|
|||
<head>
|
||||
<title>Welcome to nginx!</title>
|
||||
<style>
|
||||
body {
|
||||
width: 35em;
|
||||
margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif;
|
||||
}
|
||||
html { color-scheme: light dark; }
|
||||
body { width: 35em; margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
#define _NGINX_H_INCLUDED_
|
||||
|
||||
|
||||
#define nginx_version 1020002
|
||||
#define NGINX_VERSION "1.20.2"
|
||||
#define nginx_version 1022000
|
||||
#define NGINX_VERSION "1.22.0"
|
||||
#define NGINX_VER "nginx/" NGINX_VERSION
|
||||
|
||||
#ifdef NGX_BUILD
|
||||
|
|
|
|||
|
|
@ -90,9 +90,6 @@ struct ngx_output_chain_ctx_s {
|
|||
|
||||
#if (NGX_HAVE_FILE_AIO || NGX_COMPAT)
|
||||
ngx_output_chain_aio_pt aio_handler;
|
||||
#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
|
||||
ssize_t (*aio_preload)(ngx_buf_t *file);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (NGX_THREADS || NGX_COMPAT)
|
||||
|
|
|
|||
|
|
@ -495,21 +495,24 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *) &reuseaddr, sizeof(int))
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||
"setsockopt(SO_REUSEADDR) %V failed",
|
||||
&ls[i].addr_text);
|
||||
if (ls[i].type != SOCK_DGRAM || !ngx_test_config) {
|
||||
|
||||
if (ngx_close_socket(s) == -1) {
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *) &reuseaddr, sizeof(int))
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||
ngx_close_socket_n " %V failed",
|
||||
"setsockopt(SO_REUSEADDR) %V failed",
|
||||
&ls[i].addr_text);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
if (ngx_close_socket(s) == -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||
ngx_close_socket_n " %V failed",
|
||||
&ls[i].addr_text);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ struct ngx_connection_s {
|
|||
|
||||
unsigned need_last_buf:1;
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT)
|
||||
unsigned busy_count:2;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -274,6 +274,10 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
|
|||
}
|
||||
|
||||
for (n = 0; n < nelts; n++) {
|
||||
if (names[n].key.data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
|
||||
{
|
||||
ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#define NGX_MODULE_SIGNATURE_3 "0"
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT)
|
||||
#define NGX_MODULE_SIGNATURE_4 "1"
|
||||
#else
|
||||
#define NGX_MODULE_SIGNATURE_4 "0"
|
||||
|
|
|
|||
|
|
@ -29,10 +29,6 @@
|
|||
|
||||
static ngx_inline ngx_int_t
|
||||
ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf);
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
static ngx_int_t ngx_output_chain_aio_setup(ngx_output_chain_ctx_t *ctx,
|
||||
ngx_file_t *file);
|
||||
#endif
|
||||
static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool,
|
||||
ngx_chain_t **chain, ngx_chain_t *in);
|
||||
static ngx_int_t ngx_output_chain_align_file_buf(ngx_output_chain_ctx_t *ctx,
|
||||
|
|
@ -260,10 +256,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (buf->in_file && buf->file->directio) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sendfile = ctx->sendfile;
|
||||
|
||||
#if (NGX_SENDFILE_LIMIT)
|
||||
|
|
@ -272,6 +264,19 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
|
|||
sendfile = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(NGX_HAVE_SENDFILE_NODISKIO)
|
||||
|
||||
/*
|
||||
* With DIRECTIO, disable sendfile() unless sendfile(SF_NOCACHE)
|
||||
* is available.
|
||||
*/
|
||||
|
||||
if (buf->in_file && buf->file->directio) {
|
||||
sendfile = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!sendfile) {
|
||||
|
|
@ -283,12 +288,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
|
|||
buf->in_file = 0;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
if (ctx->aio_preload && buf->in_file) {
|
||||
(void) ngx_output_chain_aio_setup(ctx, buf->file);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctx->need_in_memory && !ngx_buf_in_memory(buf)) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -301,28 +300,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
|
|||
}
|
||||
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_output_chain_aio_setup(ngx_output_chain_ctx_t *ctx, ngx_file_t *file)
|
||||
{
|
||||
ngx_event_aio_t *aio;
|
||||
|
||||
if (file->aio == NULL && ngx_file_aio_init(file, ctx->pool) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
aio = file->aio;
|
||||
|
||||
aio->data = ctx->filter_ctx;
|
||||
aio->preload_handler = ctx->aio_preload;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_output_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain,
|
||||
ngx_chain_t *in)
|
||||
|
|
@ -803,6 +780,10 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (chain && c->write->ready) {
|
||||
ngx_post_event(c->write, &ngx_posted_next_events);
|
||||
}
|
||||
|
||||
for (cl = ctx->out; cl && cl != chain; /* void */) {
|
||||
ln = cl;
|
||||
cl = cl->next;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ struct ngx_rbtree_s {
|
|||
(tree)->sentinel = s; \
|
||||
(tree)->insert = i
|
||||
|
||||
#define ngx_rbtree_data(node, type, link) \
|
||||
(type *) ((u_char *) (node) - offsetof(type, link))
|
||||
|
||||
|
||||
void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
|
||||
void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
|
||||
|
|
|
|||
|
|
@ -10,15 +10,22 @@
|
|||
|
||||
|
||||
typedef struct {
|
||||
ngx_flag_t pcre_jit;
|
||||
ngx_flag_t pcre_jit;
|
||||
ngx_list_t *studies;
|
||||
} ngx_regex_conf_t;
|
||||
|
||||
|
||||
static ngx_inline void ngx_regex_malloc_init(ngx_pool_t *pool);
|
||||
static ngx_inline void ngx_regex_malloc_done(void);
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
static void * ngx_libc_cdecl ngx_regex_malloc(size_t size, void *data);
|
||||
static void ngx_libc_cdecl ngx_regex_free(void *p, void *data);
|
||||
#else
|
||||
static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
|
||||
static void ngx_libc_cdecl ngx_regex_free(void *p);
|
||||
#if (NGX_HAVE_PCRE_JIT)
|
||||
static void ngx_pcre_free_studies(void *data);
|
||||
#endif
|
||||
static void ngx_regex_cleanup(void *data);
|
||||
|
||||
static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
|
||||
|
||||
|
|
@ -65,32 +72,197 @@ ngx_module_t ngx_regex_module = {
|
|||
};
|
||||
|
||||
|
||||
static ngx_pool_t *ngx_pcre_pool;
|
||||
static ngx_list_t *ngx_pcre_studies;
|
||||
static ngx_pool_t *ngx_regex_pool;
|
||||
static ngx_list_t *ngx_regex_studies;
|
||||
static ngx_uint_t ngx_regex_direct_alloc;
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
static pcre2_compile_context *ngx_regex_compile_context;
|
||||
static pcre2_match_data *ngx_regex_match_data;
|
||||
static ngx_uint_t ngx_regex_match_data_size;
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
ngx_regex_init(void)
|
||||
{
|
||||
#if !(NGX_PCRE2)
|
||||
pcre_malloc = ngx_regex_malloc;
|
||||
pcre_free = ngx_regex_free;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ngx_inline void
|
||||
ngx_regex_malloc_init(ngx_pool_t *pool)
|
||||
{
|
||||
ngx_pcre_pool = pool;
|
||||
ngx_regex_pool = pool;
|
||||
ngx_regex_direct_alloc = (pool == NULL) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static ngx_inline void
|
||||
ngx_regex_malloc_done(void)
|
||||
{
|
||||
ngx_pcre_pool = NULL;
|
||||
ngx_regex_pool = NULL;
|
||||
ngx_regex_direct_alloc = 0;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
|
||||
ngx_int_t
|
||||
ngx_regex_compile(ngx_regex_compile_t *rc)
|
||||
{
|
||||
int n, errcode;
|
||||
char *p;
|
||||
u_char errstr[128];
|
||||
size_t erroff;
|
||||
uint32_t options;
|
||||
pcre2_code *re;
|
||||
ngx_regex_elt_t *elt;
|
||||
pcre2_general_context *gctx;
|
||||
pcre2_compile_context *cctx;
|
||||
|
||||
if (ngx_regex_compile_context == NULL) {
|
||||
/*
|
||||
* Allocate a compile context if not yet allocated. This uses
|
||||
* direct allocations from heap, so the result can be cached
|
||||
* even at runtime.
|
||||
*/
|
||||
|
||||
ngx_regex_malloc_init(NULL);
|
||||
|
||||
gctx = pcre2_general_context_create(ngx_regex_malloc, ngx_regex_free,
|
||||
NULL);
|
||||
if (gctx == NULL) {
|
||||
ngx_regex_malloc_done();
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
cctx = pcre2_compile_context_create(gctx);
|
||||
if (cctx == NULL) {
|
||||
pcre2_general_context_free(gctx);
|
||||
ngx_regex_malloc_done();
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
ngx_regex_compile_context = cctx;
|
||||
|
||||
pcre2_general_context_free(gctx);
|
||||
ngx_regex_malloc_done();
|
||||
}
|
||||
|
||||
options = 0;
|
||||
|
||||
if (rc->options & NGX_REGEX_CASELESS) {
|
||||
options |= PCRE2_CASELESS;
|
||||
}
|
||||
|
||||
if (rc->options & NGX_REGEX_MULTILINE) {
|
||||
options |= PCRE2_MULTILINE;
|
||||
}
|
||||
|
||||
if (rc->options & ~(NGX_REGEX_CASELESS|NGX_REGEX_MULTILINE)) {
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"regex \"%V\" compilation failed: invalid options",
|
||||
&rc->pattern)
|
||||
- rc->err.data;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_regex_malloc_init(rc->pool);
|
||||
|
||||
re = pcre2_compile(rc->pattern.data, rc->pattern.len, options,
|
||||
&errcode, &erroff, ngx_regex_compile_context);
|
||||
|
||||
/* ensure that there is no current pool */
|
||||
ngx_regex_malloc_done();
|
||||
|
||||
if (re == NULL) {
|
||||
pcre2_get_error_message(errcode, errstr, 128);
|
||||
|
||||
if ((size_t) erroff == rc->pattern.len) {
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"pcre2_compile() failed: %s in \"%V\"",
|
||||
errstr, &rc->pattern)
|
||||
- rc->err.data;
|
||||
|
||||
} else {
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"pcre2_compile() failed: %s in \"%V\" at \"%s\"",
|
||||
errstr, &rc->pattern, rc->pattern.data + erroff)
|
||||
- rc->err.data;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc->regex = re;
|
||||
|
||||
/* do not study at runtime */
|
||||
|
||||
if (ngx_regex_studies != NULL) {
|
||||
elt = ngx_list_push(ngx_regex_studies);
|
||||
if (elt == NULL) {
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
elt->regex = rc->regex;
|
||||
elt->name = rc->pattern.data;
|
||||
}
|
||||
|
||||
n = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &rc->captures);
|
||||
if (n < 0) {
|
||||
p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_CAPTURECOUNT) failed: %d";
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (rc->captures == 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
n = pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &rc->named_captures);
|
||||
if (n < 0) {
|
||||
p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMECOUNT) failed: %d";
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (rc->named_captures == 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
n = pcre2_pattern_info(re, PCRE2_INFO_NAMEENTRYSIZE, &rc->name_size);
|
||||
if (n < 0) {
|
||||
p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMEENTRYSIZE) failed: %d";
|
||||
goto failed;
|
||||
}
|
||||
|
||||
n = pcre2_pattern_info(re, PCRE2_INFO_NAMETABLE, &rc->names);
|
||||
if (n < 0) {
|
||||
p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMETABLE) failed: %d";
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
failed:
|
||||
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
|
||||
- rc->err.data;
|
||||
return NGX_ERROR;
|
||||
|
||||
nomem:
|
||||
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"regex \"%V\" compilation failed: no memory",
|
||||
&rc->pattern)
|
||||
- rc->err.data;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
ngx_int_t
|
||||
ngx_regex_compile(ngx_regex_compile_t *rc)
|
||||
{
|
||||
|
|
@ -98,11 +270,30 @@ ngx_regex_compile(ngx_regex_compile_t *rc)
|
|||
char *p;
|
||||
pcre *re;
|
||||
const char *errstr;
|
||||
ngx_uint_t options;
|
||||
ngx_regex_elt_t *elt;
|
||||
|
||||
options = 0;
|
||||
|
||||
if (rc->options & NGX_REGEX_CASELESS) {
|
||||
options |= PCRE_CASELESS;
|
||||
}
|
||||
|
||||
if (rc->options & NGX_REGEX_MULTILINE) {
|
||||
options |= PCRE_MULTILINE;
|
||||
}
|
||||
|
||||
if (rc->options & ~(NGX_REGEX_CASELESS|NGX_REGEX_MULTILINE)) {
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"regex \"%V\" compilation failed: invalid options",
|
||||
&rc->pattern)
|
||||
- rc->err.data;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_regex_malloc_init(rc->pool);
|
||||
|
||||
re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
|
||||
re = pcre_compile((const char *) rc->pattern.data, (int) options,
|
||||
&errstr, &erroff, NULL);
|
||||
|
||||
/* ensure that there is no current pool */
|
||||
|
|
@ -113,13 +304,13 @@ ngx_regex_compile(ngx_regex_compile_t *rc)
|
|||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"pcre_compile() failed: %s in \"%V\"",
|
||||
errstr, &rc->pattern)
|
||||
- rc->err.data;
|
||||
- rc->err.data;
|
||||
|
||||
} else {
|
||||
rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
|
||||
"pcre_compile() failed: %s in \"%V\" at \"%s\"",
|
||||
errstr, &rc->pattern, rc->pattern.data + erroff)
|
||||
- rc->err.data;
|
||||
- rc->err.data;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
|
|
@ -134,8 +325,8 @@ ngx_regex_compile(ngx_regex_compile_t *rc)
|
|||
|
||||
/* do not study at runtime */
|
||||
|
||||
if (ngx_pcre_studies != NULL) {
|
||||
elt = ngx_list_push(ngx_pcre_studies);
|
||||
if (ngx_regex_studies != NULL) {
|
||||
elt = ngx_list_push(ngx_regex_studies);
|
||||
if (elt == NULL) {
|
||||
goto nomem;
|
||||
}
|
||||
|
|
@ -193,6 +384,83 @@ nomem:
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
|
||||
ngx_int_t
|
||||
ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size)
|
||||
{
|
||||
size_t *ov;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t n, i;
|
||||
|
||||
/*
|
||||
* The pcre2_match() function might allocate memory for backtracking
|
||||
* frames, typical allocations are from 40k and above. So the allocator
|
||||
* is configured to do direct allocations from heap during matching.
|
||||
*/
|
||||
|
||||
ngx_regex_malloc_init(NULL);
|
||||
|
||||
if (ngx_regex_match_data == NULL
|
||||
|| size > ngx_regex_match_data_size)
|
||||
{
|
||||
/*
|
||||
* Allocate a match data if not yet allocated or smaller than
|
||||
* needed.
|
||||
*/
|
||||
|
||||
if (ngx_regex_match_data) {
|
||||
pcre2_match_data_free(ngx_regex_match_data);
|
||||
}
|
||||
|
||||
ngx_regex_match_data_size = size;
|
||||
ngx_regex_match_data = pcre2_match_data_create(size / 3, NULL);
|
||||
|
||||
if (ngx_regex_match_data == NULL) {
|
||||
rc = PCRE2_ERROR_NOMEMORY;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
rc = pcre2_match(re, s->data, s->len, 0, 0, ngx_regex_match_data, NULL);
|
||||
|
||||
if (rc < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
n = pcre2_get_ovector_count(ngx_regex_match_data);
|
||||
ov = pcre2_get_ovector_pointer(ngx_regex_match_data);
|
||||
|
||||
if (n > size / 3) {
|
||||
n = size / 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
captures[i * 2] = ov[i * 2];
|
||||
captures[i * 2 + 1] = ov[i * 2 + 1];
|
||||
}
|
||||
|
||||
failed:
|
||||
|
||||
ngx_regex_malloc_done();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
ngx_int_t
|
||||
ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size)
|
||||
{
|
||||
return pcre_exec(re->code, re->extra, (const char *) s->data, s->len,
|
||||
0, 0, captures, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
|
||||
|
|
@ -227,14 +495,40 @@ ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
|
|||
}
|
||||
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
|
||||
static void * ngx_libc_cdecl
|
||||
ngx_regex_malloc(size_t size, void *data)
|
||||
{
|
||||
if (ngx_regex_pool) {
|
||||
return ngx_palloc(ngx_regex_pool, size);
|
||||
}
|
||||
|
||||
if (ngx_regex_direct_alloc) {
|
||||
return ngx_alloc(size, ngx_cycle->log);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void ngx_libc_cdecl
|
||||
ngx_regex_free(void *p, void *data)
|
||||
{
|
||||
if (ngx_regex_direct_alloc) {
|
||||
ngx_free(p);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void * ngx_libc_cdecl
|
||||
ngx_regex_malloc(size_t size)
|
||||
{
|
||||
ngx_pool_t *pool;
|
||||
pool = ngx_pcre_pool;
|
||||
|
||||
if (pool) {
|
||||
return ngx_palloc(pool, size);
|
||||
if (ngx_regex_pool) {
|
||||
return ngx_palloc(ngx_regex_pool, size);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -247,19 +541,20 @@ ngx_regex_free(void *p)
|
|||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_PCRE_JIT)
|
||||
|
||||
static void
|
||||
ngx_pcre_free_studies(void *data)
|
||||
ngx_regex_cleanup(void *data)
|
||||
{
|
||||
ngx_list_t *studies = data;
|
||||
#if (NGX_PCRE2 || NGX_HAVE_PCRE_JIT)
|
||||
ngx_regex_conf_t *rcf = data;
|
||||
|
||||
ngx_uint_t i;
|
||||
ngx_list_part_t *part;
|
||||
ngx_regex_elt_t *elts;
|
||||
|
||||
part = &studies->part;
|
||||
part = &rcf->studies->part;
|
||||
elts = part->elts;
|
||||
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
|
|
@ -274,56 +569,83 @@ ngx_pcre_free_studies(void *data)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The PCRE JIT compiler uses mmap for its executable codes, so we
|
||||
* have to explicitly call the pcre_free_study() function to free
|
||||
* this memory. In PCRE2, we call the pcre2_code_free() function
|
||||
* for the same reason.
|
||||
*/
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
pcre2_code_free(elts[i].regex);
|
||||
#else
|
||||
if (elts[i].regex->extra != NULL) {
|
||||
pcre_free_study(elts[i].regex->extra);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On configuration parsing errors ngx_regex_module_init() will not
|
||||
* be called. Make sure ngx_regex_studies is properly cleared anyway.
|
||||
*/
|
||||
|
||||
ngx_regex_studies = NULL;
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
|
||||
/*
|
||||
* Free compile context and match data. If needed at runtime by
|
||||
* the new cycle, these will be re-allocated.
|
||||
*/
|
||||
|
||||
if (ngx_regex_compile_context) {
|
||||
pcre2_compile_context_free(ngx_regex_compile_context);
|
||||
ngx_regex_compile_context = NULL;
|
||||
}
|
||||
|
||||
if (ngx_regex_match_data) {
|
||||
pcre2_match_data_free(ngx_regex_match_data);
|
||||
ngx_regex_match_data = NULL;
|
||||
ngx_regex_match_data_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_regex_module_init(ngx_cycle_t *cycle)
|
||||
{
|
||||
int opt;
|
||||
const char *errstr;
|
||||
ngx_uint_t i;
|
||||
ngx_list_part_t *part;
|
||||
ngx_regex_elt_t *elts;
|
||||
int opt;
|
||||
#if !(NGX_PCRE2)
|
||||
const char *errstr;
|
||||
#endif
|
||||
ngx_uint_t i;
|
||||
ngx_list_part_t *part;
|
||||
ngx_regex_elt_t *elts;
|
||||
ngx_regex_conf_t *rcf;
|
||||
|
||||
opt = 0;
|
||||
|
||||
#if (NGX_HAVE_PCRE_JIT)
|
||||
{
|
||||
ngx_regex_conf_t *rcf;
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
|
||||
|
||||
#if (NGX_PCRE2 || NGX_HAVE_PCRE_JIT)
|
||||
|
||||
if (rcf->pcre_jit) {
|
||||
#if (NGX_PCRE2)
|
||||
opt = 1;
|
||||
#else
|
||||
opt = PCRE_STUDY_JIT_COMPILE;
|
||||
|
||||
/*
|
||||
* The PCRE JIT compiler uses mmap for its executable codes, so we
|
||||
* have to explicitly call the pcre_free_study() function to free
|
||||
* this memory.
|
||||
*/
|
||||
|
||||
cln = ngx_pool_cleanup_add(cycle->pool, 0);
|
||||
if (cln == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cln->handler = ngx_pcre_free_studies;
|
||||
cln->data = ngx_pcre_studies;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ngx_regex_malloc_init(cycle->pool);
|
||||
|
||||
part = &ngx_pcre_studies->part;
|
||||
part = &rcf->studies->part;
|
||||
elts = part->elts;
|
||||
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
|
|
@ -338,6 +660,23 @@ ngx_regex_module_init(ngx_cycle_t *cycle)
|
|||
i = 0;
|
||||
}
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
|
||||
if (opt) {
|
||||
int n;
|
||||
|
||||
n = pcre2_jit_compile(elts[i].regex, PCRE2_JIT_COMPLETE);
|
||||
|
||||
if (n != 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
|
||||
"pcre2_jit_compile() failed: %d in \"%s\", "
|
||||
"ignored",
|
||||
n, elts[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);
|
||||
|
||||
if (errstr != NULL) {
|
||||
|
|
@ -360,12 +699,16 @@ ngx_regex_module_init(ngx_cycle_t *cycle)
|
|||
elts[i].name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
ngx_regex_malloc_done();
|
||||
|
||||
ngx_pcre_studies = NULL;
|
||||
ngx_regex_studies = NULL;
|
||||
#if (NGX_PCRE2)
|
||||
ngx_regex_compile_context = NULL;
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -374,7 +717,8 @@ ngx_regex_module_init(ngx_cycle_t *cycle)
|
|||
static void *
|
||||
ngx_regex_create_conf(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_regex_conf_t *rcf;
|
||||
ngx_regex_conf_t *rcf;
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
|
||||
if (rcf == NULL) {
|
||||
|
|
@ -383,11 +727,21 @@ ngx_regex_create_conf(ngx_cycle_t *cycle)
|
|||
|
||||
rcf->pcre_jit = NGX_CONF_UNSET;
|
||||
|
||||
ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
|
||||
if (ngx_pcre_studies == NULL) {
|
||||
cln = ngx_pool_cleanup_add(cycle->pool, 0);
|
||||
if (cln == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cln->handler = ngx_regex_cleanup;
|
||||
cln->data = rcf;
|
||||
|
||||
rcf->studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
|
||||
if (rcf->studies == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ngx_regex_studies = rcf->studies;
|
||||
|
||||
return rcf;
|
||||
}
|
||||
|
||||
|
|
@ -412,7 +766,21 @@ ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
|
|||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_PCRE_JIT)
|
||||
#if (NGX_PCRE2)
|
||||
{
|
||||
int r;
|
||||
uint32_t jit;
|
||||
|
||||
jit = 0;
|
||||
r = pcre2_config(PCRE2_CONFIG_JIT, &jit);
|
||||
|
||||
if (r != 0 || jit != 1) {
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"PCRE2 library does not support JIT");
|
||||
*fp = 0;
|
||||
}
|
||||
}
|
||||
#elif (NGX_HAVE_PCRE_JIT)
|
||||
{
|
||||
int jit, r;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,24 +12,38 @@
|
|||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include <pcre2.h>
|
||||
|
||||
#define NGX_REGEX_NO_MATCHED PCRE2_ERROR_NOMATCH /* -1 */
|
||||
|
||||
typedef pcre2_code ngx_regex_t;
|
||||
|
||||
#else
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
|
||||
#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */
|
||||
|
||||
#define NGX_REGEX_CASELESS PCRE_CASELESS
|
||||
|
||||
#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */
|
||||
|
||||
typedef struct {
|
||||
pcre *code;
|
||||
pcre_extra *extra;
|
||||
} ngx_regex_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_REGEX_CASELESS 0x00000001
|
||||
#define NGX_REGEX_MULTILINE 0x00000002
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t pattern;
|
||||
ngx_pool_t *pool;
|
||||
ngx_int_t options;
|
||||
ngx_uint_t options;
|
||||
|
||||
ngx_regex_t *regex;
|
||||
int captures;
|
||||
|
|
@ -49,10 +63,14 @@ typedef struct {
|
|||
void ngx_regex_init(void);
|
||||
ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
|
||||
|
||||
#define ngx_regex_exec(re, s, captures, size) \
|
||||
pcre_exec(re->code, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
|
||||
captures, size)
|
||||
#define ngx_regex_exec_n "pcre_exec()"
|
||||
ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
|
||||
ngx_uint_t size);
|
||||
|
||||
#if (NGX_PCRE2)
|
||||
#define ngx_regex_exec_n "pcre2_match()"
|
||||
#else
|
||||
#define ngx_regex_exec_n "pcre_exec()"
|
||||
#endif
|
||||
|
||||
ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,7 @@ typedef struct {
|
|||
} ngx_resolver_an_t;
|
||||
|
||||
|
||||
#define ngx_resolver_node(n) \
|
||||
(ngx_resolver_node_t *) \
|
||||
((u_char *) (n) - offsetof(ngx_resolver_node_t, node))
|
||||
#define ngx_resolver_node(n) ngx_rbtree_data(n, ngx_resolver_node_t, node)
|
||||
|
||||
|
||||
static ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec);
|
||||
|
|
|
|||
|
|
@ -89,22 +89,10 @@ ngx_rwlock_rlock(ngx_atomic_t *lock)
|
|||
void
|
||||
ngx_rwlock_unlock(ngx_atomic_t *lock)
|
||||
{
|
||||
ngx_atomic_uint_t readers;
|
||||
|
||||
readers = *lock;
|
||||
|
||||
if (readers == NGX_RWLOCK_WLOCK) {
|
||||
if (*lock == NGX_RWLOCK_WLOCK) {
|
||||
(void) ngx_atomic_cmp_set(lock, NGX_RWLOCK_WLOCK, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
if (ngx_atomic_cmp_set(lock, readers, readers - 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
readers = *lock;
|
||||
} else {
|
||||
(void) ngx_atomic_fetch_add(lock, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1493,19 +1493,32 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
|
|||
uint32_t *escape;
|
||||
static u_char hex[] = "0123456789ABCDEF";
|
||||
|
||||
/* " ", "#", "%", "?", %00-%1F, %7F-%FF */
|
||||
/*
|
||||
* Per RFC 3986 only the following chars are allowed in URIs unescaped:
|
||||
*
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*
|
||||
* And "%" can appear as a part of escaping itself. The following
|
||||
* characters are not allowed and need to be escaped: %00-%1F, %7F-%FF,
|
||||
* " ", """, "<", ">", "\", "^", "`", "{", "|", "}".
|
||||
*/
|
||||
|
||||
/* " ", "#", "%", "?", not allowed */
|
||||
|
||||
static uint32_t uri[] = {
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
||||
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
|
||||
0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */
|
||||
0xd000002d, /* 1101 0000 0000 0000 0000 0000 0010 1101 */
|
||||
|
||||
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
|
||||
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
|
||||
|
||||
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
|
||||
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
|
||||
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
|
@ -1513,19 +1526,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
|
|||
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
};
|
||||
|
||||
/* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */
|
||||
/* " ", "#", "%", "&", "+", ";", "?", not allowed */
|
||||
|
||||
static uint32_t args[] = {
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
||||
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
|
||||
0x88000869, /* 1000 1000 0000 0000 0000 1000 0110 1001 */
|
||||
0xd800086d, /* 1101 1000 0000 0000 0000 1000 0110 1101 */
|
||||
|
||||
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
|
||||
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
|
||||
|
||||
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
|
||||
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
|
||||
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
|
@ -1553,19 +1566,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
|
|||
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
};
|
||||
|
||||
/* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */
|
||||
/* " ", "#", """, "%", "'", not allowed */
|
||||
|
||||
static uint32_t html[] = {
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
||||
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
|
||||
0x000000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */
|
||||
0x500000ad, /* 0101 0000 0000 0000 0000 0000 1010 1101 */
|
||||
|
||||
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
|
||||
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
|
||||
|
||||
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
|
||||
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
|
||||
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
|
@ -1573,19 +1586,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
|
|||
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
};
|
||||
|
||||
/* " ", """, "%", "'", %00-%1F, %7F-%FF */
|
||||
/* " ", """, "'", not allowed */
|
||||
|
||||
static uint32_t refresh[] = {
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
||||
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
|
||||
0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */
|
||||
0x50000085, /* 0101 0000 0000 0000 0000 0000 1000 0101 */
|
||||
|
||||
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
|
||||
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */
|
||||
|
||||
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
|
||||
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
0xd8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */
|
||||
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
|
|
|||
|
|
@ -200,10 +200,6 @@ ngx_monotonic_time(time_t sec, ngx_uint_t msec)
|
|||
|
||||
#if defined(CLOCK_MONOTONIC_FAST)
|
||||
clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
|
||||
|
||||
#elif defined(CLOCK_MONOTONIC_COARSE)
|
||||
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ ngx_uint_t ngx_accept_events;
|
|||
ngx_uint_t ngx_accept_mutex_held;
|
||||
ngx_msec_t ngx_accept_mutex_delay;
|
||||
ngx_int_t ngx_accept_disabled;
|
||||
ngx_uint_t ngx_use_exclusive_accept;
|
||||
|
||||
|
||||
#if (NGX_STAT_STUB)
|
||||
|
|
@ -441,20 +442,23 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
|
|||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
|
||||
ls = cycle->listening.elts;
|
||||
for (i = 0; i < cycle->listening.nelts; i++) {
|
||||
|
||||
if (!ls[i].reuseport || ls[i].worker != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
/* cloning may change cycle->listening.elts */
|
||||
if (!ngx_test_config) {
|
||||
|
||||
ls = cycle->listening.elts;
|
||||
for (i = 0; i < cycle->listening.nelts; i++) {
|
||||
|
||||
if (!ls[i].reuseport || ls[i].worker != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
/* cloning may change cycle->listening.elts */
|
||||
|
||||
ls = cycle->listening.elts;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -641,6 +645,8 @@ ngx_event_process_init(ngx_cycle_t *cycle)
|
|||
|
||||
#endif
|
||||
|
||||
ngx_use_exclusive_accept = 0;
|
||||
|
||||
ngx_queue_init(&ngx_posted_accept_events);
|
||||
ngx_queue_init(&ngx_posted_next_events);
|
||||
ngx_queue_init(&ngx_posted_events);
|
||||
|
|
@ -886,6 +892,8 @@ ngx_event_process_init(ngx_cycle_t *cycle)
|
|||
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
||||
&& ccf->worker_processes > 1)
|
||||
{
|
||||
ngx_use_exclusive_accept = 1;
|
||||
|
||||
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -147,10 +147,6 @@ struct ngx_event_aio_s {
|
|||
|
||||
ngx_fd_t fd;
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
|
||||
ssize_t (*preload_handler)(ngx_buf_t *file);
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_EVENTFD)
|
||||
int64_t res;
|
||||
#endif
|
||||
|
|
@ -466,6 +462,7 @@ extern ngx_uint_t ngx_accept_events;
|
|||
extern ngx_uint_t ngx_accept_mutex_held;
|
||||
extern ngx_msec_t ngx_accept_mutex_delay;
|
||||
extern ngx_int_t ngx_accept_disabled;
|
||||
extern ngx_uint_t ngx_use_exclusive_accept;
|
||||
|
||||
|
||||
#if (NGX_STAT_STUB)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
|
||||
static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all);
|
||||
#if (NGX_HAVE_EPOLLEXCLUSIVE)
|
||||
static void ngx_reorder_accept_events(ngx_listening_t *ls);
|
||||
#endif
|
||||
static void ngx_close_accepted_connection(ngx_connection_t *c);
|
||||
|
||||
|
||||
|
|
@ -314,6 +317,10 @@ ngx_event_accept(ngx_event_t *ev)
|
|||
}
|
||||
|
||||
} while (ev->available);
|
||||
|
||||
#if (NGX_HAVE_EPOLLEXCLUSIVE)
|
||||
ngx_reorder_accept_events(ls);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -420,6 +427,57 @@ ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all)
|
|||
}
|
||||
|
||||
|
||||
#if (NGX_HAVE_EPOLLEXCLUSIVE)
|
||||
|
||||
static void
|
||||
ngx_reorder_accept_events(ngx_listening_t *ls)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
|
||||
/*
|
||||
* Linux with EPOLLEXCLUSIVE usually notifies only the process which
|
||||
* was first to add the listening socket to the epoll instance. As
|
||||
* a result most of the connections are handled by the first worker
|
||||
* process. To fix this, we re-add the socket periodically, so other
|
||||
* workers will get a chance to accept connections.
|
||||
*/
|
||||
|
||||
if (!ngx_use_exclusive_accept) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
|
||||
if (ls->reuseport) {
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
c = ls->connection;
|
||||
|
||||
if (c->requests++ % 16 != 0
|
||||
&& ngx_accept_disabled <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ngx_close_accepted_connection(ngx_connection_t *c)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ static void ngx_ssl_write_handler(ngx_event_t *wev);
|
|||
static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data,
|
||||
size_t size);
|
||||
#endif
|
||||
static ssize_t ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file,
|
||||
size_t size);
|
||||
static void ngx_ssl_read_handler(ngx_event_t *rev);
|
||||
static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
|
||||
static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
|
||||
|
|
@ -299,11 +301,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
|
|||
SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
|
||||
#endif
|
||||
|
||||
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
|
||||
/* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
|
||||
SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
|
||||
#endif
|
||||
|
||||
#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
|
||||
SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
|
||||
#endif
|
||||
|
|
@ -863,11 +860,6 @@ ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
|
|||
SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
}
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
|
||||
/* a temporary 512-bit RSA key is required for export versions of MSIE */
|
||||
SSL_CTX_set_tmp_rsa_callback(ssl->ctx, ngx_ssl_rsa512_key_callback);
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1120,32 +1112,6 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
|
|||
}
|
||||
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
|
||||
|
||||
RSA *
|
||||
ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
|
||||
int key_length)
|
||||
{
|
||||
static RSA *key;
|
||||
|
||||
if (key_length != 512) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
|
||||
if (key == NULL) {
|
||||
key = RSA_generate_key(512, RSA_F4, NULL, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ngx_array_t *
|
||||
ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
|
||||
{
|
||||
|
|
@ -1417,6 +1383,9 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
|
|||
if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) {
|
||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||
"SSL_CTX_set0_tmp_dh_pkey(\%s\") failed", file->data);
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x3000001fL)
|
||||
EVP_PKEY_free(dh);
|
||||
#endif
|
||||
BIO_free(bio);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
|
@ -1798,6 +1767,16 @@ ngx_ssl_handshake(ngx_connection_t *c)
|
|||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BIO_get_ktls_send
|
||||
|
||||
if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"BIO_get_ktls_send(): 1");
|
||||
c->ssl->sendfile = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
rc = ngx_ssl_ocsp_validate(c);
|
||||
|
|
@ -1935,6 +1914,16 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
|
|||
c->read->ready = 1;
|
||||
c->write->ready = 1;
|
||||
|
||||
#ifdef BIO_get_ktls_send
|
||||
|
||||
if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"BIO_get_ktls_send(): 1");
|
||||
c->ssl->sendfile = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
rc = ngx_ssl_ocsp_validate(c);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
|
|
@ -2538,10 +2527,11 @@ ngx_ssl_write_handler(ngx_event_t *wev)
|
|||
ngx_chain_t *
|
||||
ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
{
|
||||
int n;
|
||||
ngx_uint_t flush;
|
||||
ssize_t send, size;
|
||||
ngx_buf_t *buf;
|
||||
int n;
|
||||
ngx_uint_t flush;
|
||||
ssize_t send, size, file_size;
|
||||
ngx_buf_t *buf;
|
||||
ngx_chain_t *cl;
|
||||
|
||||
if (!c->ssl->buffer) {
|
||||
|
||||
|
|
@ -2615,6 +2605,11 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (in->buf->in_file && c->ssl->sendfile) {
|
||||
flush = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
size = in->buf->last - in->buf->pos;
|
||||
|
||||
if (size > buf->end - buf->last) {
|
||||
|
|
@ -2646,8 +2641,35 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
size = buf->last - buf->pos;
|
||||
|
||||
if (size == 0) {
|
||||
|
||||
if (in && in->buf->in_file && send < limit) {
|
||||
|
||||
/* coalesce the neighbouring file bufs */
|
||||
|
||||
cl = in;
|
||||
file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send);
|
||||
|
||||
n = ngx_ssl_sendfile(c, in->buf, file_size);
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
break;
|
||||
}
|
||||
|
||||
in = ngx_chain_update_sent(in, n);
|
||||
|
||||
send += n;
|
||||
flush = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
buf->flush = 0;
|
||||
c->buffered &= ~NGX_SSL_BUFFERED;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
|
|
@ -2672,7 +2694,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
buf->pos = buf->start;
|
||||
buf->last = buf->start;
|
||||
|
||||
if (in == NULL || send == limit) {
|
||||
if (in == NULL || send >= limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2803,7 +2825,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
|
|||
|
||||
#ifdef SSL_READ_EARLY_DATA_SUCCESS
|
||||
|
||||
ssize_t
|
||||
static ssize_t
|
||||
ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
|
||||
{
|
||||
int n, sslerr;
|
||||
|
|
@ -2918,6 +2940,183 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
|
|||
#endif
|
||||
|
||||
|
||||
static ssize_t
|
||||
ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
|
||||
{
|
||||
#ifdef BIO_get_ktls_send
|
||||
|
||||
int sslerr, flags;
|
||||
ssize_t n;
|
||||
ngx_err_t err;
|
||||
|
||||
ngx_ssl_clear_error(c->log);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"SSL to sendfile: @%O %uz",
|
||||
file->file_pos, size);
|
||||
|
||||
ngx_set_errno(0);
|
||||
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
|
||||
flags = (c->busy_count <= 2) ? SF_NODISKIO : 0;
|
||||
|
||||
if (file->file->directio) {
|
||||
flags |= SF_NOCACHE;
|
||||
}
|
||||
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
if (n > 0) {
|
||||
|
||||
if (c->ssl->saved_read_handler) {
|
||||
|
||||
c->read->handler = c->ssl->saved_read_handler;
|
||||
c->ssl->saved_read_handler = NULL;
|
||||
c->read->ready = 1;
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_post_event(c->read, &ngx_posted_events);
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
c->busy_count = 0;
|
||||
#endif
|
||||
|
||||
c->sent += n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
|
||||
/*
|
||||
* if sendfile returns zero, then someone has truncated the file,
|
||||
* so the offset became beyond the end of the file
|
||||
*/
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"SSL_sendfile() reported that \"%s\" was truncated at %O",
|
||||
file->file->name.data, file->file_pos);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
sslerr = SSL_get_error(c->ssl->connection, n);
|
||||
|
||||
if (sslerr == SSL_ERROR_ZERO_RETURN) {
|
||||
|
||||
/*
|
||||
* OpenSSL fails to return SSL_ERROR_SYSCALL if an error
|
||||
* happens during writing after close_notify alert from the
|
||||
* peer, and returns SSL_ERROR_ZERO_RETURN instead
|
||||
*/
|
||||
|
||||
sslerr = SSL_ERROR_SYSCALL;
|
||||
}
|
||||
|
||||
if (sslerr == SSL_ERROR_SSL
|
||||
&& ERR_GET_REASON(ERR_peek_error()) == SSL_R_UNINITIALIZED
|
||||
&& ngx_errno != 0)
|
||||
{
|
||||
/*
|
||||
* OpenSSL fails to return SSL_ERROR_SYSCALL if an error
|
||||
* happens in sendfile(), and returns SSL_ERROR_SSL with
|
||||
* SSL_R_UNINITIALIZED reason instead
|
||||
*/
|
||||
|
||||
sslerr = SSL_ERROR_SYSCALL;
|
||||
}
|
||||
|
||||
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
|
||||
|
||||
if (sslerr == SSL_ERROR_WANT_WRITE) {
|
||||
|
||||
if (c->ssl->saved_read_handler) {
|
||||
|
||||
c->read->handler = c->ssl->saved_read_handler;
|
||||
c->ssl->saved_read_handler = NULL;
|
||||
c->read->ready = 1;
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_post_event(c->read, &ngx_posted_events);
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
|
||||
if (ngx_errno == EBUSY) {
|
||||
c->busy_count++;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"SSL_sendfile() busy, count:%d", c->busy_count);
|
||||
|
||||
if (c->write->posted) {
|
||||
ngx_delete_posted_event(c->write);
|
||||
}
|
||||
|
||||
ngx_post_event(c->write, &ngx_posted_next_events);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
c->write->ready = 0;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (sslerr == SSL_ERROR_WANT_READ) {
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"SSL_sendfile: want read");
|
||||
|
||||
c->read->ready = 0;
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* we do not set the timer because there is already
|
||||
* the write event timer
|
||||
*/
|
||||
|
||||
if (c->ssl->saved_read_handler == NULL) {
|
||||
c->ssl->saved_read_handler = c->read->handler;
|
||||
c->read->handler = ngx_ssl_read_handler;
|
||||
}
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
c->ssl->no_wait_shutdown = 1;
|
||||
c->ssl->no_send_shutdown = 1;
|
||||
c->write->error = 1;
|
||||
|
||||
ngx_ssl_connection_error(c, sslerr, err, "SSL_sendfile() failed");
|
||||
|
||||
#else
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"SSL_sendfile() not available");
|
||||
#endif
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_ssl_read_handler(ngx_event_t *rev)
|
||||
{
|
||||
|
|
@ -3169,6 +3368,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|
|||
#endif
|
||||
#ifdef SSL_R_CALLBACK_FAILED
|
||||
|| n == SSL_R_CALLBACK_FAILED /* 234 */
|
||||
#endif
|
||||
#ifdef SSL_R_NO_APPLICATION_PROTOCOL
|
||||
|| n == SSL_R_NO_APPLICATION_PROTOCOL /* 235 */
|
||||
#endif
|
||||
|| n == SSL_R_UNEXPECTED_MESSAGE /* 244 */
|
||||
|| n == SSL_R_UNEXPECTED_RECORD /* 245 */
|
||||
|
|
@ -4249,7 +4451,21 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
|
|||
return -1;
|
||||
}
|
||||
|
||||
return (i == 0) ? 1 : 2 /* renew */;
|
||||
/* renew if TLSv1.3 */
|
||||
|
||||
#ifdef TLS1_3_VERSION
|
||||
if (SSL_version(ssl_conn) == TLS1_3_VERSION) {
|
||||
return 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* renew if non-default key */
|
||||
|
||||
if (i != 0) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4567,6 +4783,42 @@ ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
|||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
#ifdef SSL_get_negotiated_group
|
||||
|
||||
int nid;
|
||||
|
||||
nid = SSL_get_negotiated_group(c->ssl->connection);
|
||||
|
||||
if (nid != NID_undef) {
|
||||
|
||||
if ((nid & TLSEXT_nid_unknown) == 0) {
|
||||
s->len = ngx_strlen(OBJ_nid2sn(nid));
|
||||
s->data = (u_char *) OBJ_nid2sn(nid);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
s->len = sizeof("0x0000") - 1;
|
||||
|
||||
s->data = ngx_pnalloc(pool, s->len);
|
||||
if (s->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_sprintf(s->data, "0x%04xd", nid & 0xffff);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
s->len = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
|
|
@ -4734,6 +4986,36 @@ ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
|||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_alpn_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
|
||||
unsigned int len;
|
||||
const unsigned char *data;
|
||||
|
||||
SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
|
||||
|
||||
if (len > 0) {
|
||||
|
||||
s->data = ngx_pnalloc(pool, len);
|
||||
if (s->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(s->data, data, len);
|
||||
s->len = len;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
s->len = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <openssl/ocsp.h>
|
||||
#endif
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
|
|
@ -110,6 +109,7 @@ struct ngx_ssl_connection_s {
|
|||
unsigned handshake_rejected:1;
|
||||
unsigned renegotiation:1;
|
||||
unsigned buffer:1;
|
||||
unsigned sendfile:1;
|
||||
unsigned no_wait_shutdown:1;
|
||||
unsigned no_send_shutdown:1;
|
||||
unsigned shutdown_without_free:1;
|
||||
|
|
@ -208,10 +208,6 @@ 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);
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER)
|
||||
RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
|
||||
int key_length);
|
||||
#endif
|
||||
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);
|
||||
|
|
@ -260,6 +256,8 @@ ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
|
|||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
|
|
@ -270,6 +268,8 @@ ngx_int_t ngx_ssl_get_early_data(ngx_connection_t *c, ngx_pool_t *pool,
|
|||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_alpn_protocol(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
ngx_str_t *s);
|
||||
ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ ngx_event_expire_timers(void)
|
|||
return;
|
||||
}
|
||||
|
||||
ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
|
||||
ev = ngx_rbtree_data(node, ngx_event_t, timer);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
|
||||
"event timer del: %d: %M",
|
||||
|
|
@ -113,7 +113,7 @@ ngx_event_no_timers_left(void)
|
|||
node;
|
||||
node = ngx_rbtree_next(&ngx_event_timer_rbtree, node))
|
||||
{
|
||||
ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
|
||||
ev = ngx_rbtree_data(node, ngx_event_t, timer);
|
||||
|
||||
if (!ev->cancelable) {
|
||||
return NGX_AGAIN;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
typedef struct {
|
||||
ngx_http_complex_value_t *realm;
|
||||
ngx_http_complex_value_t user_file;
|
||||
ngx_http_complex_value_t *user_file;
|
||||
} ngx_http_auth_basic_loc_conf_t;
|
||||
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||
|
||||
alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);
|
||||
|
||||
if (alcf->realm == NULL || alcf->user_file.value.data == NULL) {
|
||||
if (alcf->realm == NULL || alcf->user_file == NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) {
|
||||
if (ngx_http_complex_value(r, alcf->user_file, &user_file) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -357,6 +357,9 @@ ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
conf->realm = NGX_CONF_UNSET_PTR;
|
||||
conf->user_file = NGX_CONF_UNSET_PTR;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
|
@ -367,13 +370,8 @@ ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_http_auth_basic_loc_conf_t *prev = parent;
|
||||
ngx_http_auth_basic_loc_conf_t *conf = child;
|
||||
|
||||
if (conf->realm == NULL) {
|
||||
conf->realm = prev->realm;
|
||||
}
|
||||
|
||||
if (conf->user_file.value.data == NULL) {
|
||||
conf->user_file = prev->user_file;
|
||||
}
|
||||
ngx_conf_merge_ptr_value(conf->realm, prev->realm, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->user_file, prev->user_file, NULL);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
|
@ -406,17 +404,22 @@ ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
ngx_str_t *value;
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
|
||||
if (alcf->user_file.value.data) {
|
||||
if (alcf->user_file != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
alcf->user_file = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
|
||||
if (alcf->user_file == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||
|
||||
ccv.cf = cf;
|
||||
ccv.value = &value[1];
|
||||
ccv.complex_value = &alcf->user_file;
|
||||
ccv.complex_value = alcf->user_file;
|
||||
ccv.zero = 1;
|
||||
ccv.conf_prefix = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1072,6 +1072,10 @@ ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found,
|
|||
static ngx_int_t
|
||||
ngx_http_dav_location(ngx_http_request_t *r)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
uintptr_t escape;
|
||||
|
||||
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
|
||||
if (r->headers_out.location == NULL) {
|
||||
return NGX_ERROR;
|
||||
|
|
@ -1079,7 +1083,26 @@ ngx_http_dav_location(ngx_http_request_t *r)
|
|||
|
||||
r->headers_out.location->hash = 1;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
r->headers_out.location->value = r->uri;
|
||||
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
|
||||
|
||||
if (escape) {
|
||||
len = r->uri.len + escape;
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
ngx_http_clear_location(r);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.location->value.len = len;
|
||||
r->headers_out.location->value.data = p;
|
||||
|
||||
ngx_escape_uri(p, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
|
||||
|
||||
} else {
|
||||
r->headers_out.location->value = r->uri;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2019,10 +2019,12 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
|
|||
break;
|
||||
}
|
||||
|
||||
/* there was error while a header line parsing */
|
||||
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent invalid header");
|
||||
"upstream sent invalid header: \"%*s\\x%02xd...\"",
|
||||
r->header_end - r->header_name_start,
|
||||
r->header_name_start, *r->header_end);
|
||||
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ typedef struct {
|
|||
ngx_uint_t ssl_verify_depth;
|
||||
ngx_str_t ssl_trusted_certificate;
|
||||
ngx_str_t ssl_crl;
|
||||
ngx_str_t ssl_certificate;
|
||||
ngx_str_t ssl_certificate_key;
|
||||
ngx_array_t *ssl_passwords;
|
||||
ngx_array_t *ssl_conf_commands;
|
||||
#endif
|
||||
} ngx_http_grpc_loc_conf_t;
|
||||
|
|
@ -426,16 +423,16 @@ static ngx_command_t ngx_http_grpc_commands[] = {
|
|||
|
||||
{ ngx_string("grpc_ssl_certificate"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_http_set_complex_value_zero_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate),
|
||||
offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("grpc_ssl_certificate_key"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_http_set_complex_value_zero_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate_key),
|
||||
offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate_key),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("grpc_ssl_password_file"),
|
||||
|
|
@ -2180,6 +2177,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
|||
}
|
||||
|
||||
ctx->rst = 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
||||
|
|
@ -3181,10 +3180,10 @@ ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
|
|||
ctx->field_rest -= size;
|
||||
|
||||
if (ctx->field_huffman) {
|
||||
if (ngx_http_v2_huff_decode(&ctx->field_state, p, size,
|
||||
&ctx->field_end,
|
||||
ctx->field_rest == 0,
|
||||
r->connection->log)
|
||||
if (ngx_http_huff_decode(&ctx->field_state, p, size,
|
||||
&ctx->field_end,
|
||||
ctx->field_rest == 0,
|
||||
r->connection->log)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
|
|
@ -3290,10 +3289,10 @@ ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
|
|||
ctx->field_rest -= size;
|
||||
|
||||
if (ctx->field_huffman) {
|
||||
if (ngx_http_v2_huff_decode(&ctx->field_state, p, size,
|
||||
&ctx->field_end,
|
||||
ctx->field_rest == 0,
|
||||
r->connection->log)
|
||||
if (ngx_http_huff_decode(&ctx->field_state, p, size,
|
||||
&ctx->field_end,
|
||||
ctx->field_rest == 0,
|
||||
r->connection->log)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
|
|
@ -3385,7 +3384,7 @@ ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ch == '\0' || ch == CR || ch == LF) {
|
||||
if (ch <= 0x20 || ch == 0x7f) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -3487,6 +3486,8 @@ ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
|
|||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
ctx->state = ngx_http_grpc_st_start;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -4340,7 +4341,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
|
|||
* conf->upstream.ignore_headers = 0;
|
||||
* conf->upstream.next_upstream = 0;
|
||||
* conf->upstream.hide_headers_hash = { NULL, 0 };
|
||||
* conf->upstream.ssl_name = NULL;
|
||||
*
|
||||
* conf->headers.lengths = NULL;
|
||||
* conf->headers.values = NULL;
|
||||
|
|
@ -4352,8 +4352,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
|
|||
* conf->ssl_ciphers = { 0, NULL };
|
||||
* conf->ssl_trusted_certificate = { 0, NULL };
|
||||
* conf->ssl_crl = { 0, NULL };
|
||||
* conf->ssl_certificate = { 0, NULL };
|
||||
* conf->ssl_certificate_key = { 0, NULL };
|
||||
*/
|
||||
|
||||
conf->upstream.local = NGX_CONF_UNSET_PTR;
|
||||
|
|
@ -4373,10 +4371,13 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
|
|||
|
||||
#if (NGX_HTTP_SSL)
|
||||
conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
|
||||
conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
|
||||
conf->upstream.ssl_server_name = NGX_CONF_UNSET;
|
||||
conf->upstream.ssl_verify = NGX_CONF_UNSET;
|
||||
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
|
||||
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
|
||||
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->ssl_conf_commands = NGX_CONF_UNSET_PTR;
|
||||
#endif
|
||||
|
||||
|
|
@ -4468,10 +4469,8 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
|
||||
"DEFAULT");
|
||||
|
||||
if (conf->upstream.ssl_name == NULL) {
|
||||
conf->upstream.ssl_name = prev->upstream.ssl_name;
|
||||
}
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
|
||||
prev->upstream.ssl_name, NULL);
|
||||
ngx_conf_merge_value(conf->upstream.ssl_server_name,
|
||||
prev->upstream.ssl_server_name, 0);
|
||||
ngx_conf_merge_value(conf->upstream.ssl_verify,
|
||||
|
|
@ -4482,11 +4481,12 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
prev->ssl_trusted_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate,
|
||||
prev->ssl_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate_key,
|
||||
prev->ssl_certificate_key, "");
|
||||
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
|
||||
prev->upstream.ssl_certificate, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
|
||||
prev->upstream.ssl_certificate_key, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords,
|
||||
prev->upstream.ssl_passwords, NULL);
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
|
||||
prev->ssl_conf_commands, NULL);
|
||||
|
|
@ -4842,15 +4842,15 @@ ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
ngx_str_t *value;
|
||||
|
||||
if (glcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
|
||||
if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
glcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||
glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||
|
||||
if (glcf->ssl_passwords == NULL) {
|
||||
if (glcf->upstream.ssl_passwords == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -4896,29 +4896,43 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
|
|||
cln->handler = ngx_ssl_cleanup_ctx;
|
||||
cln->data = glcf->upstream.ssl;
|
||||
|
||||
if (glcf->ssl_certificate.len) {
|
||||
|
||||
if (glcf->ssl_certificate_key.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"grpc_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"", &glcf->ssl_certificate);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->ssl_certificate,
|
||||
&glcf->ssl_certificate_key, glcf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (glcf->upstream.ssl_certificate) {
|
||||
|
||||
if (glcf->upstream.ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"grpc_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"",
|
||||
&glcf->upstream.ssl_certificate->value);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (glcf->upstream.ssl_certificate->lengths
|
||||
|| glcf->upstream.ssl_certificate_key->lengths)
|
||||
{
|
||||
glcf->upstream.ssl_passwords =
|
||||
ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords);
|
||||
if (glcf->upstream.ssl_passwords == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (ngx_ssl_certificate(cf, glcf->upstream.ssl,
|
||||
&glcf->upstream.ssl_certificate->value,
|
||||
&glcf->upstream.ssl_certificate_key->value,
|
||||
glcf->upstream.ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (glcf->upstream.ssl_verify) {
|
||||
if (glcf->ssl_trusted_certificate.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
|
|
|
|||
|
|
@ -11,31 +11,33 @@
|
|||
|
||||
#define NGX_HTTP_MP4_TRAK_ATOM 0
|
||||
#define NGX_HTTP_MP4_TKHD_ATOM 1
|
||||
#define NGX_HTTP_MP4_MDIA_ATOM 2
|
||||
#define NGX_HTTP_MP4_MDHD_ATOM 3
|
||||
#define NGX_HTTP_MP4_HDLR_ATOM 4
|
||||
#define NGX_HTTP_MP4_MINF_ATOM 5
|
||||
#define NGX_HTTP_MP4_VMHD_ATOM 6
|
||||
#define NGX_HTTP_MP4_SMHD_ATOM 7
|
||||
#define NGX_HTTP_MP4_DINF_ATOM 8
|
||||
#define NGX_HTTP_MP4_STBL_ATOM 9
|
||||
#define NGX_HTTP_MP4_STSD_ATOM 10
|
||||
#define NGX_HTTP_MP4_STTS_ATOM 11
|
||||
#define NGX_HTTP_MP4_STTS_DATA 12
|
||||
#define NGX_HTTP_MP4_STSS_ATOM 13
|
||||
#define NGX_HTTP_MP4_STSS_DATA 14
|
||||
#define NGX_HTTP_MP4_CTTS_ATOM 15
|
||||
#define NGX_HTTP_MP4_CTTS_DATA 16
|
||||
#define NGX_HTTP_MP4_STSC_ATOM 17
|
||||
#define NGX_HTTP_MP4_STSC_START 18
|
||||
#define NGX_HTTP_MP4_STSC_DATA 19
|
||||
#define NGX_HTTP_MP4_STSC_END 20
|
||||
#define NGX_HTTP_MP4_STSZ_ATOM 21
|
||||
#define NGX_HTTP_MP4_STSZ_DATA 22
|
||||
#define NGX_HTTP_MP4_STCO_ATOM 23
|
||||
#define NGX_HTTP_MP4_STCO_DATA 24
|
||||
#define NGX_HTTP_MP4_CO64_ATOM 25
|
||||
#define NGX_HTTP_MP4_CO64_DATA 26
|
||||
#define NGX_HTTP_MP4_EDTS_ATOM 2
|
||||
#define NGX_HTTP_MP4_ELST_ATOM 3
|
||||
#define NGX_HTTP_MP4_MDIA_ATOM 4
|
||||
#define NGX_HTTP_MP4_MDHD_ATOM 5
|
||||
#define NGX_HTTP_MP4_HDLR_ATOM 6
|
||||
#define NGX_HTTP_MP4_MINF_ATOM 7
|
||||
#define NGX_HTTP_MP4_VMHD_ATOM 8
|
||||
#define NGX_HTTP_MP4_SMHD_ATOM 9
|
||||
#define NGX_HTTP_MP4_DINF_ATOM 10
|
||||
#define NGX_HTTP_MP4_STBL_ATOM 11
|
||||
#define NGX_HTTP_MP4_STSD_ATOM 12
|
||||
#define NGX_HTTP_MP4_STTS_ATOM 13
|
||||
#define NGX_HTTP_MP4_STTS_DATA 14
|
||||
#define NGX_HTTP_MP4_STSS_ATOM 15
|
||||
#define NGX_HTTP_MP4_STSS_DATA 16
|
||||
#define NGX_HTTP_MP4_CTTS_ATOM 17
|
||||
#define NGX_HTTP_MP4_CTTS_DATA 18
|
||||
#define NGX_HTTP_MP4_STSC_ATOM 19
|
||||
#define NGX_HTTP_MP4_STSC_START 20
|
||||
#define NGX_HTTP_MP4_STSC_DATA 21
|
||||
#define NGX_HTTP_MP4_STSC_END 22
|
||||
#define NGX_HTTP_MP4_STSZ_ATOM 23
|
||||
#define NGX_HTTP_MP4_STSZ_DATA 24
|
||||
#define NGX_HTTP_MP4_STCO_ATOM 25
|
||||
#define NGX_HTTP_MP4_STCO_DATA 26
|
||||
#define NGX_HTTP_MP4_CO64_ATOM 27
|
||||
#define NGX_HTTP_MP4_CO64_DATA 28
|
||||
|
||||
#define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
|
||||
|
||||
|
|
@ -43,6 +45,7 @@
|
|||
typedef struct {
|
||||
size_t buffer_size;
|
||||
size_t max_buffer_size;
|
||||
ngx_flag_t start_key_frame;
|
||||
} ngx_http_mp4_conf_t;
|
||||
|
||||
|
||||
|
|
@ -53,6 +56,25 @@ typedef struct {
|
|||
} ngx_mp4_stsc_entry_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char size[4];
|
||||
u_char name[4];
|
||||
} ngx_mp4_edts_atom_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char size[4];
|
||||
u_char name[4];
|
||||
u_char version[1];
|
||||
u_char flags[3];
|
||||
u_char entries[4];
|
||||
u_char duration[8];
|
||||
u_char media_time[8];
|
||||
u_char media_rate[2];
|
||||
u_char reserved[2];
|
||||
} ngx_mp4_elst_atom_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t timescale;
|
||||
uint32_t time_to_sample_entries;
|
||||
|
|
@ -70,6 +92,9 @@ typedef struct {
|
|||
ngx_uint_t end_chunk_samples;
|
||||
uint64_t start_chunk_samples_size;
|
||||
uint64_t end_chunk_samples_size;
|
||||
uint64_t duration;
|
||||
uint64_t prefix;
|
||||
uint64_t movie_duration;
|
||||
off_t start_offset;
|
||||
off_t end_offset;
|
||||
|
||||
|
|
@ -85,6 +110,8 @@ typedef struct {
|
|||
|
||||
ngx_buf_t trak_atom_buf;
|
||||
ngx_buf_t tkhd_atom_buf;
|
||||
ngx_buf_t edts_atom_buf;
|
||||
ngx_buf_t elst_atom_buf;
|
||||
ngx_buf_t mdia_atom_buf;
|
||||
ngx_buf_t mdhd_atom_buf;
|
||||
ngx_buf_t hdlr_atom_buf;
|
||||
|
|
@ -111,6 +138,8 @@ typedef struct {
|
|||
ngx_buf_t co64_atom_buf;
|
||||
ngx_buf_t co64_data_buf;
|
||||
|
||||
ngx_mp4_edts_atom_t edts_atom;
|
||||
ngx_mp4_elst_atom_t elst_atom;
|
||||
ngx_mp4_stsc_entry_t stsc_start_chunk_entry;
|
||||
ngx_mp4_stsc_entry_t stsc_end_chunk_entry;
|
||||
} ngx_http_mp4_trak_t;
|
||||
|
|
@ -186,6 +215,14 @@ typedef struct {
|
|||
((u_char *) (p))[6] = n3; \
|
||||
((u_char *) (p))[7] = n4
|
||||
|
||||
#define ngx_mp4_get_16value(p) \
|
||||
( ((uint16_t) ((u_char *) (p))[0] << 8) \
|
||||
+ ( ((u_char *) (p))[1]) )
|
||||
|
||||
#define ngx_mp4_set_16value(p, n) \
|
||||
((u_char *) (p))[0] = (u_char) ((n) >> 8); \
|
||||
((u_char *) (p))[1] = (u_char) (n)
|
||||
|
||||
#define ngx_mp4_get_32value(p) \
|
||||
( ((uint32_t) ((u_char *) (p))[0] << 24) \
|
||||
+ ( ((u_char *) (p))[1] << 16) \
|
||||
|
|
@ -253,6 +290,8 @@ static void ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4,
|
|||
ngx_http_mp4_trak_t *trak);
|
||||
static ngx_int_t ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4,
|
||||
uint64_t atom_data_size);
|
||||
static void ngx_http_mp4_update_mdhd_atom(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak);
|
||||
static ngx_int_t ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4,
|
||||
uint64_t atom_data_size);
|
||||
static ngx_int_t ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4,
|
||||
|
|
@ -267,6 +306,8 @@ static ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4,
|
|||
uint64_t atom_data_size);
|
||||
static ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4,
|
||||
uint64_t atom_data_size);
|
||||
static void ngx_http_mp4_update_edts_atom(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak);
|
||||
static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak);
|
||||
static ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4,
|
||||
|
|
@ -277,6 +318,8 @@ static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
|
|||
ngx_http_mp4_trak_t *trak);
|
||||
static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak, ngx_uint_t start);
|
||||
static uint32_t ngx_http_mp4_seek_key_frame(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak, uint32_t start_sample);
|
||||
static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
|
||||
uint64_t atom_data_size);
|
||||
static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
|
||||
|
|
@ -340,6 +383,13 @@ static ngx_command_t ngx_http_mp4_commands[] = {
|
|||
offsetof(ngx_http_mp4_conf_t, max_buffer_size),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("mp4_start_key_frame"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_mp4_conf_t, start_key_frame),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
|
@ -822,10 +872,11 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||
|
||||
ngx_http_mp4_update_stbl_atom(mp4, &trak[i]);
|
||||
ngx_http_mp4_update_minf_atom(mp4, &trak[i]);
|
||||
trak[i].size += trak[i].mdhd_size;
|
||||
ngx_http_mp4_update_mdhd_atom(mp4, &trak[i]);
|
||||
trak[i].size += trak[i].hdlr_size;
|
||||
ngx_http_mp4_update_mdia_atom(mp4, &trak[i]);
|
||||
trak[i].size += trak[i].tkhd_size;
|
||||
ngx_http_mp4_update_edts_atom(mp4, &trak[i]);
|
||||
ngx_http_mp4_update_trak_atom(mp4, &trak[i]);
|
||||
|
||||
mp4->moov_size += trak[i].size;
|
||||
|
|
@ -1587,6 +1638,7 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
|
||||
trak = ngx_mp4_last_trak(mp4);
|
||||
trak->tkhd_size = atom_size;
|
||||
trak->movie_duration = duration;
|
||||
|
||||
ngx_mp4_set_32value(tkhd_atom->size, atom_size);
|
||||
|
||||
|
|
@ -1749,16 +1801,10 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
trak = ngx_mp4_last_trak(mp4);
|
||||
trak->mdhd_size = atom_size;
|
||||
trak->timescale = timescale;
|
||||
trak->duration = duration;
|
||||
|
||||
ngx_mp4_set_32value(mdhd_atom->size, atom_size);
|
||||
|
||||
if (mdhd_atom->version[0] == 0) {
|
||||
ngx_mp4_set_32value(mdhd_atom->duration, duration);
|
||||
|
||||
} else {
|
||||
ngx_mp4_set_64value(mdhd64_atom->duration, duration);
|
||||
}
|
||||
|
||||
atom = &trak->mdhd_atom_buf;
|
||||
atom->temporary = 1;
|
||||
atom->pos = atom_header;
|
||||
|
|
@ -1772,6 +1818,33 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_mp4_update_mdhd_atom(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak)
|
||||
{
|
||||
ngx_buf_t *atom;
|
||||
ngx_mp4_mdhd_atom_t *mdhd_atom;
|
||||
ngx_mp4_mdhd64_atom_t *mdhd64_atom;
|
||||
|
||||
atom = trak->out[NGX_HTTP_MP4_MDHD_ATOM].buf;
|
||||
if (atom == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom->pos;
|
||||
mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom->pos;
|
||||
|
||||
if (mdhd_atom->version[0] == 0) {
|
||||
ngx_mp4_set_32value(mdhd_atom->duration, trak->duration);
|
||||
|
||||
} else {
|
||||
ngx_mp4_set_64value(mdhd64_atom->duration, trak->duration);
|
||||
}
|
||||
|
||||
trak->size += trak->mdhd_size;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
||||
{
|
||||
|
|
@ -1961,6 +2034,59 @@ ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_mp4_update_edts_atom(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak)
|
||||
{
|
||||
ngx_buf_t *atom;
|
||||
ngx_mp4_elst_atom_t *elst_atom;
|
||||
ngx_mp4_edts_atom_t *edts_atom;
|
||||
|
||||
if (trak->prefix == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||
"mp4 edts atom update prefix:%uL", trak->prefix);
|
||||
|
||||
edts_atom = &trak->edts_atom;
|
||||
ngx_mp4_set_32value(edts_atom->size, sizeof(ngx_mp4_edts_atom_t)
|
||||
+ sizeof(ngx_mp4_elst_atom_t));
|
||||
ngx_mp4_set_atom_name(edts_atom, 'e', 'd', 't', 's');
|
||||
|
||||
atom = &trak->edts_atom_buf;
|
||||
atom->temporary = 1;
|
||||
atom->pos = (u_char *) edts_atom;
|
||||
atom->last = (u_char *) edts_atom + sizeof(ngx_mp4_edts_atom_t);
|
||||
|
||||
trak->out[NGX_HTTP_MP4_EDTS_ATOM].buf = atom;
|
||||
|
||||
elst_atom = &trak->elst_atom;
|
||||
ngx_mp4_set_32value(elst_atom->size, sizeof(ngx_mp4_elst_atom_t));
|
||||
ngx_mp4_set_atom_name(elst_atom, 'e', 'l', 's', 't');
|
||||
|
||||
elst_atom->version[0] = 1;
|
||||
elst_atom->flags[0] = 0;
|
||||
elst_atom->flags[1] = 0;
|
||||
elst_atom->flags[2] = 0;
|
||||
|
||||
ngx_mp4_set_32value(elst_atom->entries, 1);
|
||||
ngx_mp4_set_64value(elst_atom->duration, trak->movie_duration);
|
||||
ngx_mp4_set_64value(elst_atom->media_time, trak->prefix);
|
||||
ngx_mp4_set_16value(elst_atom->media_rate, 1);
|
||||
ngx_mp4_set_16value(elst_atom->reserved, 0);
|
||||
|
||||
atom = &trak->elst_atom_buf;
|
||||
atom->temporary = 1;
|
||||
atom->pos = (u_char *) elst_atom;
|
||||
atom->last = (u_char *) elst_atom + sizeof(ngx_mp4_elst_atom_t);
|
||||
|
||||
trak->out[NGX_HTTP_MP4_ELST_ATOM].buf = atom;
|
||||
|
||||
trak->size += sizeof(ngx_mp4_edts_atom_t) + sizeof(ngx_mp4_elst_atom_t);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak)
|
||||
|
|
@ -2159,7 +2285,7 @@ static ngx_int_t
|
|||
ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
||||
ngx_http_mp4_trak_t *trak, ngx_uint_t start)
|
||||
{
|
||||
uint32_t count, duration, rest;
|
||||
uint32_t count, duration, rest, key_prefix;
|
||||
uint64_t start_time;
|
||||
ngx_buf_t *data;
|
||||
ngx_uint_t start_sample, entries, start_sec;
|
||||
|
|
@ -2183,7 +2309,7 @@ ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
|||
|
||||
data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
|
||||
|
||||
start_time = (uint64_t) start_sec * trak->timescale / 1000;
|
||||
start_time = (uint64_t) start_sec * trak->timescale / 1000 + trak->prefix;
|
||||
|
||||
entries = trak->time_to_sample_entries;
|
||||
start_sample = 0;
|
||||
|
|
@ -2229,6 +2355,26 @@ ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
|
|||
found:
|
||||
|
||||
if (start) {
|
||||
key_prefix = ngx_http_mp4_seek_key_frame(mp4, trak, start_sample);
|
||||
|
||||
start_sample -= key_prefix;
|
||||
|
||||
while (rest < key_prefix) {
|
||||
trak->prefix += rest * duration;
|
||||
key_prefix -= rest;
|
||||
|
||||
entry--;
|
||||
entries++;
|
||||
|
||||
count = ngx_mp4_get_32value(entry->count);
|
||||
duration = ngx_mp4_get_32value(entry->duration);
|
||||
rest = count;
|
||||
}
|
||||
|
||||
trak->prefix += key_prefix * duration;
|
||||
trak->duration += trak->prefix;
|
||||
rest -= key_prefix;
|
||||
|
||||
ngx_mp4_set_32value(entry->count, count - rest);
|
||||
data->pos = (u_char *) entry;
|
||||
trak->time_to_sample_entries = entries;
|
||||
|
|
@ -2253,6 +2399,49 @@ found:
|
|||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
ngx_http_mp4_seek_key_frame(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak,
|
||||
uint32_t start_sample)
|
||||
{
|
||||
uint32_t key_prefix, sample, *entry, *end;
|
||||
ngx_buf_t *data;
|
||||
ngx_http_mp4_conf_t *conf;
|
||||
|
||||
conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
|
||||
if (!conf->start_key_frame) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry = (uint32_t *) data->pos;
|
||||
end = (uint32_t *) data->last;
|
||||
|
||||
/* sync samples starts from 1 */
|
||||
start_sample++;
|
||||
|
||||
key_prefix = 0;
|
||||
|
||||
while (entry < end) {
|
||||
sample = ngx_mp4_get_32value(entry);
|
||||
if (sample > start_sample) {
|
||||
break;
|
||||
}
|
||||
|
||||
key_prefix = start_sample - sample;
|
||||
entry++;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||
"mp4 key frame prefix:%uD", key_prefix);
|
||||
|
||||
return key_prefix;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char size[4];
|
||||
u_char name[4];
|
||||
|
|
@ -3590,6 +3779,7 @@ ngx_http_mp4_create_conf(ngx_conf_t *cf)
|
|||
|
||||
conf->buffer_size = NGX_CONF_UNSET_SIZE;
|
||||
conf->max_buffer_size = NGX_CONF_UNSET_SIZE;
|
||||
conf->start_key_frame = NGX_CONF_UNSET;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
|
@ -3604,6 +3794,7 @@ ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024);
|
||||
ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size,
|
||||
10 * 1024 * 1024);
|
||||
ngx_conf_merge_value(conf->start_key_frame, prev->start_key_frame, 0);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,9 +124,6 @@ typedef struct {
|
|||
ngx_uint_t ssl_verify_depth;
|
||||
ngx_str_t ssl_trusted_certificate;
|
||||
ngx_str_t ssl_crl;
|
||||
ngx_str_t ssl_certificate;
|
||||
ngx_str_t ssl_certificate_key;
|
||||
ngx_array_t *ssl_passwords;
|
||||
ngx_array_t *ssl_conf_commands;
|
||||
#endif
|
||||
} ngx_http_proxy_loc_conf_t;
|
||||
|
|
@ -753,16 +750,16 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
|||
|
||||
{ ngx_string("proxy_ssl_certificate"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_http_set_complex_value_zero_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate),
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_ssl_certificate_key"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_http_set_complex_value_zero_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key),
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate_key),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_ssl_password_file"),
|
||||
|
|
@ -1189,7 +1186,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
|
|||
|
||||
loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
|
||||
|
||||
if (r->quoted_uri || r->space_in_uri || r->internal) {
|
||||
if (r->quoted_uri || r->internal) {
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
|
||||
r->uri.len - loc_len, NGX_ESCAPE_URI);
|
||||
} else {
|
||||
|
|
@ -1302,7 +1299,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
|||
loc_len = (r->valid_location && ctx->vars.uri.len) ?
|
||||
plcf->location.len : 0;
|
||||
|
||||
if (r->quoted_uri || r->space_in_uri || r->internal) {
|
||||
if (r->quoted_uri || r->internal) {
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
|
||||
r->uri.len - loc_len, NGX_ESCAPE_URI);
|
||||
}
|
||||
|
|
@ -2022,10 +2019,12 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
/* there was error while a header line parsing */
|
||||
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent invalid header");
|
||||
"upstream sent invalid header: \"%*s\\x%02xd...\"",
|
||||
r->header_end - r->header_name_start,
|
||||
r->header_name_start, *r->header_end);
|
||||
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
|
@ -2338,6 +2337,7 @@ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
|
|||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
u->keepalive = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -3327,9 +3327,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
|||
* conf->upstream.hide_headers_hash = { NULL, 0 };
|
||||
* conf->upstream.store_lengths = NULL;
|
||||
* conf->upstream.store_values = NULL;
|
||||
* conf->upstream.ssl_name = NULL;
|
||||
*
|
||||
* conf->method = NULL;
|
||||
* conf->location = NULL;
|
||||
* conf->url = { 0, NULL };
|
||||
* conf->headers.lengths = NULL;
|
||||
|
|
@ -3347,8 +3345,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
|||
* conf->ssl_ciphers = { 0, NULL };
|
||||
* conf->ssl_trusted_certificate = { 0, NULL };
|
||||
* conf->ssl_crl = { 0, NULL };
|
||||
* conf->ssl_certificate = { 0, NULL };
|
||||
* conf->ssl_certificate_key = { 0, NULL };
|
||||
*/
|
||||
|
||||
conf->upstream.store = NGX_CONF_UNSET;
|
||||
|
|
@ -3400,20 +3396,26 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
|||
|
||||
#if (NGX_HTTP_SSL)
|
||||
conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
|
||||
conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
|
||||
conf->upstream.ssl_server_name = NGX_CONF_UNSET;
|
||||
conf->upstream.ssl_verify = NGX_CONF_UNSET;
|
||||
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->ssl_verify_depth = NGX_CONF_UNSET_UINT;
|
||||
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
|
||||
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
|
||||
#endif
|
||||
|
||||
/* "proxy_cyclic_temp_file" is disabled */
|
||||
conf->upstream.cyclic_temp_file = 0;
|
||||
|
||||
conf->upstream.change_buffering = 1;
|
||||
|
||||
conf->headers_source = NGX_CONF_UNSET_PTR;
|
||||
|
||||
conf->method = NGX_CONF_UNSET_PTR;
|
||||
|
||||
conf->redirect = NGX_CONF_UNSET;
|
||||
conf->upstream.change_buffering = 1;
|
||||
|
||||
conf->cookie_domains = NGX_CONF_UNSET_PTR;
|
||||
conf->cookie_paths = NGX_CONF_UNSET_PTR;
|
||||
|
|
@ -3708,10 +3710,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
#endif
|
||||
|
||||
if (conf->method == NULL) {
|
||||
conf->method = prev->method;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.pass_request_headers,
|
||||
prev->upstream.pass_request_headers, 1);
|
||||
ngx_conf_merge_value(conf->upstream.pass_request_body,
|
||||
|
|
@ -3732,10 +3730,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
|
||||
"DEFAULT");
|
||||
|
||||
if (conf->upstream.ssl_name == NULL) {
|
||||
conf->upstream.ssl_name = prev->upstream.ssl_name;
|
||||
}
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
|
||||
prev->upstream.ssl_name, NULL);
|
||||
ngx_conf_merge_value(conf->upstream.ssl_server_name,
|
||||
prev->upstream.ssl_server_name, 0);
|
||||
ngx_conf_merge_value(conf->upstream.ssl_verify,
|
||||
|
|
@ -3746,11 +3742,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
prev->ssl_trusted_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate,
|
||||
prev->ssl_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate_key,
|
||||
prev->ssl_certificate_key, "");
|
||||
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
|
||||
prev->upstream.ssl_certificate, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
|
||||
prev->upstream.ssl_certificate_key, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords,
|
||||
prev->upstream.ssl_passwords, NULL);
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
|
||||
prev->ssl_conf_commands, NULL);
|
||||
|
|
@ -3761,6 +3758,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
#endif
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->method, prev->method, NULL);
|
||||
|
||||
ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
|
||||
|
||||
if (conf->redirect) {
|
||||
|
|
@ -4859,15 +4858,15 @@ ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
ngx_str_t *value;
|
||||
|
||||
if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
|
||||
if (plcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||
plcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||
|
||||
if (plcf->ssl_passwords == NULL) {
|
||||
if (plcf->upstream.ssl_passwords == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -4946,29 +4945,43 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
|
|||
cln->handler = ngx_ssl_cleanup_ctx;
|
||||
cln->data = plcf->upstream.ssl;
|
||||
|
||||
if (plcf->ssl_certificate.len) {
|
||||
|
||||
if (plcf->ssl_certificate_key.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"proxy_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"", &plcf->ssl_certificate);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate,
|
||||
&plcf->ssl_certificate_key, plcf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (plcf->upstream.ssl_certificate) {
|
||||
|
||||
if (plcf->upstream.ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"proxy_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"",
|
||||
&plcf->upstream.ssl_certificate->value);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (plcf->upstream.ssl_certificate->lengths
|
||||
|| plcf->upstream.ssl_certificate_key->lengths)
|
||||
{
|
||||
plcf->upstream.ssl_passwords =
|
||||
ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords);
|
||||
if (plcf->upstream.ssl_passwords == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (ngx_ssl_certificate(cf, plcf->upstream.ssl,
|
||||
&plcf->upstream.ssl_certificate->value,
|
||||
&plcf->upstream.ssl_certificate_key->value,
|
||||
plcf->upstream.ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plcf->upstream.ssl_verify) {
|
||||
if (plcf->ssl_trusted_certificate.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
|
|
|
|||
|
|
@ -1140,10 +1140,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
|
|||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
/* there was error while a header line parsing */
|
||||
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent invalid header");
|
||||
"upstream sent invalid header: \"%*s\\x%02xd...\"",
|
||||
r->header_end - r->header_name_start,
|
||||
r->header_name_start, *r->header_end);
|
||||
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,11 +302,12 @@ ngx_http_secure_link_create_conf(ngx_conf_t *cf)
|
|||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* conf->variable = NULL;
|
||||
* conf->md5 = NULL;
|
||||
* conf->secret = { 0, NULL };
|
||||
*/
|
||||
|
||||
conf->variable = NGX_CONF_UNSET_PTR;
|
||||
conf->md5 = NGX_CONF_UNSET_PTR;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +319,9 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_http_secure_link_conf_t *conf = child;
|
||||
|
||||
if (conf->secret.data) {
|
||||
ngx_conf_init_ptr_value(conf->variable, NULL);
|
||||
ngx_conf_init_ptr_value(conf->md5, NULL);
|
||||
|
||||
if (conf->variable || conf->md5) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"secure_link_secret\" cannot be mixed with "
|
||||
|
|
@ -328,13 +332,8 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
if (conf->variable == NULL) {
|
||||
conf->variable = prev->variable;
|
||||
}
|
||||
|
||||
if (conf->md5 == NULL) {
|
||||
conf->md5 = prev->md5;
|
||||
}
|
||||
ngx_conf_merge_ptr_value(conf->variable, prev->variable, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->md5, prev->md5, NULL);
|
||||
|
||||
if (conf->variable == NULL && conf->md5 == NULL) {
|
||||
conf->secret = prev->secret;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
|
|||
#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
|
||||
#define NGX_DEFAULT_ECDH_CURVE "auto"
|
||||
|
||||
#define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1"
|
||||
#define NGX_HTTP_ALPN_PROTOS "\x08http/1.1\x08http/1.0\x08http/0.9"
|
||||
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
|
|
@ -26,11 +26,6 @@ static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
|
|||
const unsigned char *in, unsigned int inlen, void *arg);
|
||||
#endif
|
||||
|
||||
#ifdef TLSEXT_TYPE_next_proto_neg
|
||||
static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
|
||||
const unsigned char **out, unsigned int *outlen, void *arg);
|
||||
#endif
|
||||
|
||||
static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
|
||||
|
|
@ -347,6 +342,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
|
|||
{ ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_curve"), NULL, ngx_http_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_curve, NGX_HTTP_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 },
|
||||
|
||||
|
|
@ -363,6 +361,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
|
|||
{ ngx_string("ssl_server_name"), NULL, ngx_http_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_server_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_alpn_protocol"), NULL, ngx_http_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_alpn_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
|
||||
|
||||
|
|
@ -444,22 +445,20 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
|
|||
hc = c->data;
|
||||
|
||||
if (hc->addr_conf->http2) {
|
||||
srv =
|
||||
(unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
|
||||
srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
|
||||
srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS;
|
||||
srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
|
||||
srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS;
|
||||
srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1;
|
||||
}
|
||||
|
||||
if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
|
||||
in, inlen)
|
||||
!= OPENSSL_NPN_NEGOTIATED)
|
||||
{
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
|
|
@ -471,44 +470,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef TLSEXT_TYPE_next_proto_neg
|
||||
|
||||
static int
|
||||
ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
|
||||
const unsigned char **out, unsigned int *outlen, void *arg)
|
||||
{
|
||||
#if (NGX_HTTP_V2 || NGX_DEBUG)
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised");
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
{
|
||||
ngx_http_connection_t *hc;
|
||||
|
||||
hc = c->data;
|
||||
|
||||
if (hc->addr_conf->http2) {
|
||||
*out =
|
||||
(unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
|
||||
*outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
|
||||
*outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_ssl_static_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
|
|
@ -792,10 +753,12 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef TLSEXT_TYPE_next_proto_neg
|
||||
SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx,
|
||||
ngx_http_ssl_npn_advertised, NULL);
|
||||
#endif
|
||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||
conf->prefer_server_ciphers)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
|
|
@ -829,13 +792,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||
conf->prefer_server_ciphers)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
conf->ssl.buffer_size = conf->buffer_size;
|
||||
|
||||
if (conf->verify) {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||
{
|
||||
u_char *last, *location;
|
||||
size_t root, len;
|
||||
uintptr_t escape;
|
||||
ngx_str_t path;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t level;
|
||||
|
|
@ -155,14 +156,18 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
len = r->uri.len + 1;
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
|
||||
NGX_ESCAPE_URI);
|
||||
|
||||
if (!clcf->alias && r->args.len == 0) {
|
||||
if (!clcf->alias && r->args.len == 0 && escape == 0) {
|
||||
len = r->uri.len + 1;
|
||||
location = path.data + root;
|
||||
|
||||
*last = '/';
|
||||
|
||||
} else {
|
||||
len = r->uri.len + escape + 1;
|
||||
|
||||
if (r->args.len) {
|
||||
len += r->args.len + 1;
|
||||
}
|
||||
|
|
@ -173,7 +178,13 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
last = ngx_copy(location, r->uri.data, r->uri.len);
|
||||
if (escape) {
|
||||
last = (u_char *) ngx_escape_uri(location, r->uri.data,
|
||||
r->uri.len, NGX_ESCAPE_URI);
|
||||
|
||||
} else {
|
||||
last = ngx_copy(location, r->uri.data, r->uri.len);
|
||||
}
|
||||
|
||||
*last = '/';
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,6 @@ typedef struct {
|
|||
ngx_uint_t ssl_verify_depth;
|
||||
ngx_str_t ssl_trusted_certificate;
|
||||
ngx_str_t ssl_crl;
|
||||
ngx_str_t ssl_certificate;
|
||||
ngx_str_t ssl_certificate_key;
|
||||
ngx_array_t *ssl_passwords;
|
||||
ngx_array_t *ssl_conf_commands;
|
||||
#endif
|
||||
} ngx_http_uwsgi_loc_conf_t;
|
||||
|
|
@ -548,16 +545,16 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
|
|||
|
||||
{ ngx_string("uwsgi_ssl_certificate"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_http_set_complex_value_zero_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate),
|
||||
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("uwsgi_ssl_certificate_key"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_http_set_complex_value_zero_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key),
|
||||
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate_key),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("uwsgi_ssl_password_file"),
|
||||
|
|
@ -1364,10 +1361,12 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
|
|||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
/* there was error while a header line parsing */
|
||||
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent invalid header");
|
||||
"upstream sent invalid header: \"%*s\\x%02xd...\"",
|
||||
r->header_end - r->header_name_start,
|
||||
r->header_name_start, *r->header_end);
|
||||
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
|
@ -1509,10 +1508,13 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
|
|||
|
||||
#if (NGX_HTTP_SSL)
|
||||
conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
|
||||
conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
|
||||
conf->upstream.ssl_server_name = NGX_CONF_UNSET;
|
||||
conf->upstream.ssl_verify = NGX_CONF_UNSET;
|
||||
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
|
||||
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
|
||||
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->ssl_conf_commands = NGX_CONF_UNSET_PTR;
|
||||
#endif
|
||||
|
||||
|
|
@ -1824,10 +1826,8 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
|
||||
"DEFAULT");
|
||||
|
||||
if (conf->upstream.ssl_name == NULL) {
|
||||
conf->upstream.ssl_name = prev->upstream.ssl_name;
|
||||
}
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
|
||||
prev->upstream.ssl_name, NULL);
|
||||
ngx_conf_merge_value(conf->upstream.ssl_server_name,
|
||||
prev->upstream.ssl_server_name, 0);
|
||||
ngx_conf_merge_value(conf->upstream.ssl_verify,
|
||||
|
|
@ -1838,11 +1838,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
prev->ssl_trusted_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate,
|
||||
prev->ssl_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate_key,
|
||||
prev->ssl_certificate_key, "");
|
||||
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
|
||||
prev->upstream.ssl_certificate, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
|
||||
prev->upstream.ssl_certificate_key, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords,
|
||||
prev->upstream.ssl_passwords, NULL);
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
|
||||
prev->ssl_conf_commands, NULL);
|
||||
|
|
@ -2377,15 +2378,15 @@ ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
ngx_str_t *value;
|
||||
|
||||
if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
|
||||
if (uwcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||
uwcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||
|
||||
if (uwcf->ssl_passwords == NULL) {
|
||||
if (uwcf->upstream.ssl_passwords == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -2431,29 +2432,43 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
|
|||
cln->handler = ngx_ssl_cleanup_ctx;
|
||||
cln->data = uwcf->upstream.ssl;
|
||||
|
||||
if (uwcf->ssl_certificate.len) {
|
||||
|
||||
if (uwcf->ssl_certificate_key.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"uwsgi_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"", &uwcf->ssl_certificate);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate,
|
||||
&uwcf->ssl_certificate_key, uwcf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (uwcf->upstream.ssl_certificate) {
|
||||
|
||||
if (uwcf->upstream.ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"uwsgi_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"",
|
||||
&uwcf->upstream.ssl_certificate->value);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (uwcf->upstream.ssl_certificate->lengths
|
||||
|| uwcf->upstream.ssl_certificate_key->lengths)
|
||||
{
|
||||
uwcf->upstream.ssl_passwords =
|
||||
ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords);
|
||||
if (uwcf->upstream.ssl_passwords == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (ngx_ssl_certificate(cf, uwcf->upstream.ssl,
|
||||
&uwcf->upstream.ssl_certificate->value,
|
||||
&uwcf->upstream.ssl_certificate_key->value,
|
||||
uwcf->upstream.ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwcf->upstream.ssl_verify) {
|
||||
if (uwcf->ssl_trusted_certificate.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
|
|||
ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
|
||||
static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
|
||||
ngx_http_core_loc_conf_t *pclcf);
|
||||
static ngx_int_t ngx_http_escape_location_name(ngx_conf_t *cf,
|
||||
ngx_http_core_loc_conf_t *clcf);
|
||||
static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
|
||||
const ngx_queue_t *two);
|
||||
static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
|
||||
|
|
@ -882,6 +884,41 @@ ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
|
|||
|
||||
ngx_queue_insert_tail(*locations, &lq->queue);
|
||||
|
||||
if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_escape_location_name(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
uintptr_t escape;
|
||||
|
||||
escape = 2 * ngx_escape_uri(NULL, clcf->name.data, clcf->name.len,
|
||||
NGX_ESCAPE_URI);
|
||||
|
||||
if (escape) {
|
||||
len = clcf->name.len + escape;
|
||||
|
||||
p = ngx_pnalloc(cf->pool, len);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
clcf->escaped_name.len = len;
|
||||
clcf->escaped_name.data = p;
|
||||
|
||||
ngx_escape_uri(p, clcf->name.data, clcf->name.len, NGX_ESCAPE_URI);
|
||||
|
||||
} else {
|
||||
clcf->escaped_name = clcf->name;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1301,13 +1338,12 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
}
|
||||
|
||||
#if (NGX_HTTP_V2 && NGX_HTTP_SSL \
|
||||
&& !defined TLSEXT_TYPE_application_layer_protocol_negotiation \
|
||||
&& !defined TLSEXT_TYPE_next_proto_neg)
|
||||
&& !defined TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
|
||||
if (lsopt->http2 && lsopt->ssl) {
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"nginx was built with OpenSSL that lacks ALPN "
|
||||
"and NPN support, HTTP/2 is not enabled for %V",
|
||||
"support, HTTP/2 is not enabled for %V",
|
||||
&lsopt->addr_text);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -167,6 +167,14 @@ ngx_uint_t ngx_http_degraded(ngx_http_request_t *);
|
|||
#endif
|
||||
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
ngx_int_t ngx_http_huff_decode(u_char *state, u_char *src, size_t len,
|
||||
u_char **dst, ngx_uint_t last, ngx_log_t *log);
|
||||
size_t ngx_http_huff_encode(u_char *src, size_t len, u_char *dst,
|
||||
ngx_uint_t lower);
|
||||
#endif
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_module;
|
||||
|
||||
extern ngx_str_t ngx_http_html_default_types[];
|
||||
|
|
|
|||
|
|
@ -19,10 +19,6 @@ typedef struct {
|
|||
static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
|
||||
ngx_file_t *file);
|
||||
static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file);
|
||||
static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
|
||||
#endif
|
||||
#endif
|
||||
#if (NGX_THREADS)
|
||||
static ngx_int_t ngx_http_copy_thread_handler(ngx_thread_task_t *task,
|
||||
|
|
@ -128,9 +124,6 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
#if (NGX_HAVE_FILE_AIO)
|
||||
if (ngx_file_aio && clcf->aio == NGX_HTTP_AIO_ON) {
|
||||
ctx->aio_handler = ngx_http_copy_aio_handler;
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
ctx->aio_preload = ngx_http_copy_aio_sendfile_preload;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -207,53 +200,6 @@ ngx_http_copy_aio_event_handler(ngx_event_t *ev)
|
|||
ngx_http_run_posted_requests(c);
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
|
||||
static ssize_t
|
||||
ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file)
|
||||
{
|
||||
ssize_t n;
|
||||
static u_char buf[1];
|
||||
ngx_event_aio_t *aio;
|
||||
ngx_http_request_t *r;
|
||||
ngx_output_chain_ctx_t *ctx;
|
||||
|
||||
n = ngx_file_aio_read(file->file, buf, 1, file->file_pos, NULL);
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
aio = file->file->aio;
|
||||
aio->handler = ngx_http_copy_aio_sendfile_event_handler;
|
||||
|
||||
r = aio->data;
|
||||
r->main->blocked++;
|
||||
r->aio = 1;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
|
||||
ctx->aio = 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
|
||||
{
|
||||
ngx_event_aio_t *aio;
|
||||
ngx_http_request_t *r;
|
||||
|
||||
aio = ev->data;
|
||||
r = aio->data;
|
||||
|
||||
r->main->blocked--;
|
||||
r->aio = 0;
|
||||
ev->complete = 0;
|
||||
|
||||
r->connection->write->handler(r->connection->write);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -263,6 +209,7 @@ static ngx_int_t
|
|||
ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
|
||||
{
|
||||
ngx_str_t name;
|
||||
ngx_connection_t *c;
|
||||
ngx_thread_pool_t *tp;
|
||||
ngx_http_request_t *r;
|
||||
ngx_output_chain_ctx_t *ctx;
|
||||
|
|
@ -270,6 +217,27 @@ ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
|
|||
|
||||
r = file->thread_ctx;
|
||||
|
||||
if (r->aio) {
|
||||
/*
|
||||
* tolerate sendfile() calls if another operation is already
|
||||
* running; this can happen due to subrequests, multiple calls
|
||||
* of the next body filter from a filter, or in HTTP/2 due to
|
||||
* a write event on the main connection
|
||||
*/
|
||||
|
||||
c = r->connection;
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
c = r->stream->connection->connection;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (task == c->sendfile_task) {
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
tp = clcf->thread_pool;
|
||||
|
||||
|
|
@ -323,6 +291,20 @@ ngx_http_copy_thread_event_handler(ngx_event_t *ev)
|
|||
r->main->blocked--;
|
||||
r->aio = 0;
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
|
||||
if (r->stream) {
|
||||
/*
|
||||
* for HTTP/2, update write event to make sure processing will
|
||||
* reach the main connection to handle sendfile() in threads
|
||||
*/
|
||||
|
||||
c->write->ready = 1;
|
||||
c->write->active = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (r->done) {
|
||||
/*
|
||||
* trigger connection event handler if the subrequest was
|
||||
|
|
|
|||
|
|
@ -1010,10 +1010,10 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r,
|
|||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
|
||||
if (r->args.len == 0) {
|
||||
r->headers_out.location->value = clcf->name;
|
||||
r->headers_out.location->value = clcf->escaped_name;
|
||||
|
||||
} else {
|
||||
len = clcf->name.len + 1 + r->args.len;
|
||||
len = clcf->escaped_name.len + 1 + r->args.len;
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
|
||||
if (p == NULL) {
|
||||
|
|
@ -1025,7 +1025,7 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r,
|
|||
r->headers_out.location->value.len = len;
|
||||
r->headers_out.location->value.data = p;
|
||||
|
||||
p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
|
||||
p = ngx_cpymem(p, clcf->escaped_name.data, clcf->escaped_name.len);
|
||||
*p++ = '?';
|
||||
ngx_memcpy(p, r->args.data, r->args.len);
|
||||
}
|
||||
|
|
@ -3467,6 +3467,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
|
|||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* clcf->escaped_name = { 0, NULL };
|
||||
* clcf->root = { 0, NULL };
|
||||
* clcf->limit_except = 0;
|
||||
* clcf->post_action = { 0, NULL };
|
||||
|
|
@ -3479,8 +3480,6 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
|
|||
* clcf->exact_match = 0;
|
||||
* clcf->auto_redirect = 0;
|
||||
* clcf->alias = 0;
|
||||
* clcf->limit_rate = NULL;
|
||||
* clcf->limit_rate_after = NULL;
|
||||
* clcf->gzip_proxied = 0;
|
||||
* clcf->keepalive_disable = 0;
|
||||
*/
|
||||
|
|
@ -3512,6 +3511,8 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
|
|||
clcf->send_timeout = NGX_CONF_UNSET_MSEC;
|
||||
clcf->send_lowat = NGX_CONF_UNSET_SIZE;
|
||||
clcf->postpone_output = NGX_CONF_UNSET_SIZE;
|
||||
clcf->limit_rate = NGX_CONF_UNSET_PTR;
|
||||
clcf->limit_rate_after = NGX_CONF_UNSET_PTR;
|
||||
clcf->keepalive_time = NGX_CONF_UNSET_MSEC;
|
||||
clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
|
||||
clcf->keepalive_header = NGX_CONF_UNSET;
|
||||
|
|
@ -3719,7 +3720,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_value(conf->internal, prev->internal, 0);
|
||||
ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
|
||||
ngx_conf_merge_size_value(conf->sendfile_max_chunk,
|
||||
prev->sendfile_max_chunk, 0);
|
||||
prev->sendfile_max_chunk, 2 * 1024 * 1024);
|
||||
ngx_conf_merge_size_value(conf->subrequest_output_buffer_size,
|
||||
prev->subrequest_output_buffer_size,
|
||||
(size_t) ngx_pagesize);
|
||||
|
|
@ -3743,13 +3744,9 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
|
||||
1460);
|
||||
|
||||
if (conf->limit_rate == NULL) {
|
||||
conf->limit_rate = prev->limit_rate;
|
||||
}
|
||||
|
||||
if (conf->limit_rate_after == NULL) {
|
||||
conf->limit_rate_after = prev->limit_rate_after;
|
||||
}
|
||||
ngx_conf_merge_ptr_value(conf->limit_rate, prev->limit_rate, NULL);
|
||||
ngx_conf_merge_ptr_value(conf->limit_rate_after,
|
||||
prev->limit_rate_after, NULL);
|
||||
|
||||
ngx_conf_merge_msec_value(conf->keepalive_time,
|
||||
prev->keepalive_time, 3600000);
|
||||
|
|
@ -4571,19 +4568,6 @@ ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
|
||||
if (ngx_strcmp(value[1].data, "sendfile") == 0) {
|
||||
clcf->aio = NGX_HTTP_AIO_ON;
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"the \"sendfile\" parameter of "
|
||||
"the \"aio\" directive is deprecated");
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (ngx_strncmp(value[1].data, "threads", 7) == 0
|
||||
&& (value[1].len == 7 || value[1].data[7] == '='))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -299,6 +299,7 @@ typedef struct {
|
|||
|
||||
struct ngx_http_core_loc_conf_s {
|
||||
ngx_str_t name; /* location name */
|
||||
ngx_str_t escaped_name;
|
||||
|
||||
#if (NGX_PCRE)
|
||||
ngx_http_regex_t *regex;
|
||||
|
|
@ -501,8 +502,8 @@ ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r);
|
|||
|
||||
|
||||
ngx_int_t ngx_http_subrequest(ngx_http_request_t *r,
|
||||
ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **sr,
|
||||
ngx_http_post_subrequest_t *psr, ngx_uint_t flags);
|
||||
ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
|
||||
ngx_http_post_subrequest_t *ps, ngx_uint_t flags);
|
||||
ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r,
|
||||
ngx_str_t *uri, ngx_str_t *args);
|
||||
ngx_int_t ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name);
|
||||
|
|
|
|||
|
|
@ -197,6 +197,10 @@ ngx_http_header_filter(ngx_http_request_t *r)
|
|||
}
|
||||
}
|
||||
|
||||
if (r->keepalive && (ngx_terminate || ngx_exiting)) {
|
||||
r->keepalive = 0;
|
||||
}
|
||||
|
||||
len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1
|
||||
/* the end of the header */
|
||||
+ sizeof(CRLF) - 1;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ typedef struct {
|
|||
u_char emit;
|
||||
u_char sym;
|
||||
u_char ending;
|
||||
} ngx_http_v2_huff_decode_code_t;
|
||||
} ngx_http_huff_decode_code_t;
|
||||
|
||||
|
||||
static ngx_inline ngx_int_t ngx_http_v2_huff_decode_bits(u_char *state,
|
||||
static ngx_inline ngx_int_t ngx_http_huff_decode_bits(u_char *state,
|
||||
u_char *ending, ngx_uint_t bits, u_char **dst);
|
||||
|
||||
|
||||
static ngx_http_v2_huff_decode_code_t ngx_http_v2_huff_decode_codes[256][16] =
|
||||
static ngx_http_huff_decode_code_t ngx_http_huff_decode_codes[256][16] =
|
||||
{
|
||||
/* 0 */
|
||||
{
|
||||
|
|
@ -2640,7 +2640,7 @@ static ngx_http_v2_huff_decode_code_t ngx_http_v2_huff_decode_codes[256][16] =
|
|||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst,
|
||||
ngx_http_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst,
|
||||
ngx_uint_t last, ngx_log_t *log)
|
||||
{
|
||||
u_char *end, ch, ending;
|
||||
|
|
@ -2653,7 +2653,7 @@ ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst,
|
|||
while (src != end) {
|
||||
ch = *src++;
|
||||
|
||||
if (ngx_http_v2_huff_decode_bits(state, &ending, ch >> 4, dst)
|
||||
if (ngx_http_huff_decode_bits(state, &ending, ch >> 4, dst)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0,
|
||||
|
|
@ -2663,7 +2663,7 @@ ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_v2_huff_decode_bits(state, &ending, ch & 0xf, dst)
|
||||
if (ngx_http_huff_decode_bits(state, &ending, ch & 0xf, dst)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0,
|
||||
|
|
@ -2692,12 +2692,12 @@ ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst,
|
|||
|
||||
|
||||
static ngx_inline ngx_int_t
|
||||
ngx_http_v2_huff_decode_bits(u_char *state, u_char *ending, ngx_uint_t bits,
|
||||
ngx_http_huff_decode_bits(u_char *state, u_char *ending, ngx_uint_t bits,
|
||||
u_char **dst)
|
||||
{
|
||||
ngx_http_v2_huff_decode_code_t code;
|
||||
ngx_http_huff_decode_code_t code;
|
||||
|
||||
code = ngx_http_v2_huff_decode_codes[*state][bits];
|
||||
code = ngx_http_huff_decode_codes[*state][bits];
|
||||
|
||||
if (code.next == *state) {
|
||||
return NGX_ERROR;
|
||||
|
|
@ -14,10 +14,10 @@
|
|||
typedef struct {
|
||||
uint32_t code;
|
||||
uint32_t len;
|
||||
} ngx_http_v2_huff_encode_code_t;
|
||||
} ngx_http_huff_encode_code_t;
|
||||
|
||||
|
||||
static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table[256] =
|
||||
static ngx_http_huff_encode_code_t ngx_http_huff_encode_table[256] =
|
||||
{
|
||||
{0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28},
|
||||
{0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28},
|
||||
|
|
@ -87,7 +87,7 @@ static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table[256] =
|
|||
|
||||
|
||||
/* same as above, but embeds lowercase transformation */
|
||||
static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] =
|
||||
static ngx_http_huff_encode_code_t ngx_http_huff_encode_table_lc[256] =
|
||||
{
|
||||
{0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28},
|
||||
{0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28},
|
||||
|
|
@ -161,10 +161,10 @@ static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] =
|
|||
#if (NGX_HAVE_LITTLE_ENDIAN)
|
||||
|
||||
#if (NGX_HAVE_GCC_BSWAP64)
|
||||
#define ngx_http_v2_huff_encode_buf(dst, buf) \
|
||||
#define ngx_http_huff_encode_buf(dst, buf) \
|
||||
(*(uint64_t *) (dst) = __builtin_bswap64(buf))
|
||||
#else
|
||||
#define ngx_http_v2_huff_encode_buf(dst, buf) \
|
||||
#define ngx_http_huff_encode_buf(dst, buf) \
|
||||
((dst)[0] = (u_char) ((buf) >> 56), \
|
||||
(dst)[1] = (u_char) ((buf) >> 48), \
|
||||
(dst)[2] = (u_char) ((buf) >> 40), \
|
||||
|
|
@ -176,28 +176,28 @@ static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] =
|
|||
#endif
|
||||
|
||||
#else /* !NGX_HAVE_LITTLE_ENDIAN */
|
||||
#define ngx_http_v2_huff_encode_buf(dst, buf) \
|
||||
#define ngx_http_huff_encode_buf(dst, buf) \
|
||||
(*(uint64_t *) (dst) = (buf))
|
||||
#endif
|
||||
|
||||
#else /* NGX_PTR_SIZE == 4 */
|
||||
|
||||
#define ngx_http_v2_huff_encode_buf(dst, buf) \
|
||||
#define ngx_http_huff_encode_buf(dst, buf) \
|
||||
(*(uint32_t *) (dst) = htonl(buf))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
size_t
|
||||
ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower)
|
||||
ngx_http_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower)
|
||||
{
|
||||
u_char *end;
|
||||
size_t hlen;
|
||||
ngx_uint_t buf, pending, code;
|
||||
ngx_http_v2_huff_encode_code_t *table, *next;
|
||||
u_char *end;
|
||||
size_t hlen;
|
||||
ngx_uint_t buf, pending, code;
|
||||
ngx_http_huff_encode_code_t *table, *next;
|
||||
|
||||
table = lower ? ngx_http_v2_huff_encode_table_lc
|
||||
: ngx_http_v2_huff_encode_table;
|
||||
table = lower ? ngx_http_huff_encode_table_lc
|
||||
: ngx_http_huff_encode_table;
|
||||
hlen = 0;
|
||||
buf = 0;
|
||||
pending = 0;
|
||||
|
|
@ -224,7 +224,7 @@ ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower)
|
|||
|
||||
buf |= code >> pending;
|
||||
|
||||
ngx_http_v2_huff_encode_buf(&dst[hlen], buf);
|
||||
ngx_http_huff_encode_buf(&dst[hlen], buf);
|
||||
|
||||
hlen += sizeof(buf);
|
||||
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
|
||||
static uint32_t usual[] = {
|
||||
0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */
|
||||
0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
|
||||
|
||||
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
|
||||
0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */
|
||||
|
|
@ -24,7 +24,7 @@ static uint32_t usual[] = {
|
|||
#endif
|
||||
|
||||
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
0x7fffffff, /* 0111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
|
||||
|
|
@ -116,10 +116,8 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
sw_host_end,
|
||||
sw_host_ip_literal,
|
||||
sw_port,
|
||||
sw_host_http_09,
|
||||
sw_after_slash_in_uri,
|
||||
sw_check_uri,
|
||||
sw_check_uri_http_09,
|
||||
sw_uri,
|
||||
sw_http_09,
|
||||
sw_http_H,
|
||||
|
|
@ -246,6 +244,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
r->method = NGX_HTTP_OPTIONS;
|
||||
}
|
||||
|
||||
if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' '))
|
||||
{
|
||||
r->method = NGX_HTTP_CONNECT;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
|
|
@ -393,7 +396,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
*/
|
||||
r->uri_start = r->schema_end + 1;
|
||||
r->uri_end = r->schema_end + 2;
|
||||
state = sw_host_http_09;
|
||||
state = sw_http_09;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
|
|
@ -467,35 +470,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
*/
|
||||
r->uri_start = r->schema_end + 1;
|
||||
r->uri_end = r->schema_end + 2;
|
||||
state = sw_host_http_09;
|
||||
state = sw_http_09;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
/* space+ after "http://host[:port] " */
|
||||
case sw_host_http_09:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
r->http_minor = 9;
|
||||
state = sw_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->http_minor = 9;
|
||||
goto done;
|
||||
case 'H':
|
||||
r->http_protocol.data = p;
|
||||
state = sw_http_H;
|
||||
break;
|
||||
default:
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* check "/.", "//", "%", and "\" (Win32) in URI */
|
||||
case sw_after_slash_in_uri:
|
||||
|
||||
|
|
@ -507,7 +488,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
switch (ch) {
|
||||
case ' ':
|
||||
r->uri_end = p;
|
||||
state = sw_check_uri_http_09;
|
||||
state = sw_http_09;
|
||||
break;
|
||||
case CR:
|
||||
r->uri_end = p;
|
||||
|
|
@ -547,9 +528,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
case '+':
|
||||
r->plus_in_uri = 1;
|
||||
break;
|
||||
case '\0':
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
default:
|
||||
if (ch < 0x20 || ch == 0x7f) {
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
state = sw_check_uri;
|
||||
break;
|
||||
}
|
||||
|
|
@ -579,7 +561,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
break;
|
||||
case ' ':
|
||||
r->uri_end = p;
|
||||
state = sw_check_uri_http_09;
|
||||
state = sw_http_09;
|
||||
break;
|
||||
case CR:
|
||||
r->uri_end = p;
|
||||
|
|
@ -611,36 +593,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
case '+':
|
||||
r->plus_in_uri = 1;
|
||||
break;
|
||||
case '\0':
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
/* space+ after URI */
|
||||
case sw_check_uri_http_09:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
r->http_minor = 9;
|
||||
state = sw_almost_done;
|
||||
break;
|
||||
case LF:
|
||||
r->http_minor = 9;
|
||||
goto done;
|
||||
case 'H':
|
||||
r->http_protocol.data = p;
|
||||
state = sw_http_H;
|
||||
break;
|
||||
default:
|
||||
r->space_in_uri = 1;
|
||||
state = sw_check_uri;
|
||||
p--;
|
||||
if (ch < 0x20 || ch == 0x7f) {
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* URI */
|
||||
case sw_uri:
|
||||
|
||||
|
|
@ -665,8 +625,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
case '#':
|
||||
r->complex_uri = 1;
|
||||
break;
|
||||
case '\0':
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
default:
|
||||
if (ch < 0x20 || ch == 0x7f) {
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -687,10 +650,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||
state = sw_http_H;
|
||||
break;
|
||||
default:
|
||||
r->space_in_uri = 1;
|
||||
state = sw_uri;
|
||||
p--;
|
||||
break;
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -933,7 +893,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||
break;
|
||||
}
|
||||
|
||||
if (ch == '\0') {
|
||||
if (ch <= 0x20 || ch == 0x7f || ch == ':') {
|
||||
r->header_end = p;
|
||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||
}
|
||||
|
||||
|
|
@ -1001,7 +962,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||
break;
|
||||
}
|
||||
|
||||
if (ch == '\0') {
|
||||
if (ch <= 0x20 || ch == 0x7f) {
|
||||
r->header_end = p;
|
||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||
}
|
||||
|
||||
|
|
@ -1024,6 +986,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||
r->header_end = p;
|
||||
goto done;
|
||||
case '\0':
|
||||
r->header_end = p;
|
||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||
default:
|
||||
r->header_start = p;
|
||||
|
|
@ -1047,6 +1010,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||
r->header_end = p;
|
||||
goto done;
|
||||
case '\0':
|
||||
r->header_end = p;
|
||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1062,6 +1026,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||
case LF:
|
||||
goto done;
|
||||
case '\0':
|
||||
r->header_end = p;
|
||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||
default:
|
||||
state = sw_value;
|
||||
|
|
@ -1165,10 +1130,6 @@ ngx_http_parse_uri(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
r->space_in_uri = 1;
|
||||
state = sw_check_uri;
|
||||
break;
|
||||
case '.':
|
||||
r->complex_uri = 1;
|
||||
state = sw_uri;
|
||||
|
|
@ -1199,6 +1160,9 @@ ngx_http_parse_uri(ngx_http_request_t *r)
|
|||
r->plus_in_uri = 1;
|
||||
break;
|
||||
default:
|
||||
if (ch <= 0x20 || ch == 0x7f) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
state = sw_check_uri;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1226,9 +1190,6 @@ ngx_http_parse_uri(ngx_http_request_t *r)
|
|||
case '.':
|
||||
r->uri_ext = p + 1;
|
||||
break;
|
||||
case ' ':
|
||||
r->space_in_uri = 1;
|
||||
break;
|
||||
#if (NGX_WIN32)
|
||||
case '\\':
|
||||
r->complex_uri = 1;
|
||||
|
|
@ -1250,6 +1211,11 @@ ngx_http_parse_uri(ngx_http_request_t *r)
|
|||
case '+':
|
||||
r->plus_in_uri = 1;
|
||||
break;
|
||||
default:
|
||||
if (ch <= 0x20 || ch == 0x7f) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1261,12 +1227,14 @@ ngx_http_parse_uri(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
r->space_in_uri = 1;
|
||||
break;
|
||||
case '#':
|
||||
r->complex_uri = 1;
|
||||
break;
|
||||
default:
|
||||
if (ch <= 0x20 || ch == 0x7f) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -607,7 +607,7 @@ ngx_http_alloc_request(ngx_connection_t *c)
|
|||
}
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
if (c->ssl) {
|
||||
if (c->ssl && !c->ssl->sendfile) {
|
||||
r->main_filter_need_in_memory = 1;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -806,8 +806,7 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
|
|||
c->ssl->no_wait_shutdown = 1;
|
||||
|
||||
#if (NGX_HTTP_V2 \
|
||||
&& (defined TLSEXT_TYPE_application_layer_protocol_negotiation \
|
||||
|| defined TLSEXT_TYPE_next_proto_neg))
|
||||
&& defined TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
{
|
||||
unsigned int len;
|
||||
const unsigned char *data;
|
||||
|
|
@ -817,19 +816,8 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
|
|||
|
||||
if (hc->addr_conf->http2) {
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
|
||||
|
||||
#ifdef TLSEXT_TYPE_next_proto_neg
|
||||
if (len == 0) {
|
||||
SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* TLSEXT_TYPE_next_proto_neg */
|
||||
SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
|
||||
#endif
|
||||
|
||||
if (len == 2 && data[0] == 'h' && data[1] == '2') {
|
||||
ngx_http_v2_init(c->read);
|
||||
return;
|
||||
|
|
@ -1043,12 +1031,14 @@ ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
|
|||
}
|
||||
|
||||
ngx_http_free_request(r, 0);
|
||||
c->log->action = "SSL handshaking";
|
||||
c->destroyed = 0;
|
||||
return 1;
|
||||
|
||||
failed:
|
||||
|
||||
ngx_http_free_request(r, 0);
|
||||
c->log->action = "SSL handshaking";
|
||||
c->destroyed = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1262,7 +1252,7 @@ ngx_http_process_request_uri(ngx_http_request_t *r)
|
|||
r->unparsed_uri.len = r->uri_end - r->uri_start;
|
||||
r->unparsed_uri.data = r->uri_start;
|
||||
|
||||
r->valid_unparsed_uri = (r->space_in_uri || r->empty_path_in_uri) ? 0 : 1;
|
||||
r->valid_unparsed_uri = r->empty_path_in_uri ? 0 : 1;
|
||||
|
||||
if (r->uri_ext) {
|
||||
if (r->args_start) {
|
||||
|
|
@ -1520,7 +1510,9 @@ ngx_http_process_request_headers(ngx_event_t *rev)
|
|||
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||
"client sent invalid header line");
|
||||
"client sent invalid header line: \"%*s\\x%02xd...\"",
|
||||
r->header_end - r->header_name_start,
|
||||
r->header_name_start, *r->header_end);
|
||||
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
break;
|
||||
|
|
@ -1978,20 +1970,28 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
|||
}
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_TRACE) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent TRACE method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->headers_in.transfer_encoding) {
|
||||
if (r->http_version < NGX_HTTP_VERSION_11) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent HTTP/1.0 request with "
|
||||
"\"Transfer-Encoding\" header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->headers_in.transfer_encoding->value.len == 7
|
||||
&& ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
|
||||
(u_char *) "chunked", 7) == 0)
|
||||
{
|
||||
r->headers_in.content_length = NULL;
|
||||
r->headers_in.content_length_n = -1;
|
||||
if (r->headers_in.content_length) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent \"Content-Length\" and "
|
||||
"\"Transfer-Encoding\" headers "
|
||||
"at the same time");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_in.chunked = 1;
|
||||
|
||||
} else {
|
||||
|
|
@ -2011,6 +2011,20 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
|||
}
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_CONNECT) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent CONNECT method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_TRACE) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent TRACE method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2158,15 +2172,16 @@ ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
|
|||
}
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
return NGX_DECLINED;
|
||||
|
||||
default:
|
||||
|
||||
if (ngx_path_separator(ch)) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (ch <= 0x20 || ch == 0x7f) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
alloc = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,22 +25,23 @@
|
|||
#define NGX_HTTP_VERSION_11 1001
|
||||
#define NGX_HTTP_VERSION_20 2000
|
||||
|
||||
#define NGX_HTTP_UNKNOWN 0x0001
|
||||
#define NGX_HTTP_GET 0x0002
|
||||
#define NGX_HTTP_HEAD 0x0004
|
||||
#define NGX_HTTP_POST 0x0008
|
||||
#define NGX_HTTP_PUT 0x0010
|
||||
#define NGX_HTTP_DELETE 0x0020
|
||||
#define NGX_HTTP_MKCOL 0x0040
|
||||
#define NGX_HTTP_COPY 0x0080
|
||||
#define NGX_HTTP_MOVE 0x0100
|
||||
#define NGX_HTTP_OPTIONS 0x0200
|
||||
#define NGX_HTTP_PROPFIND 0x0400
|
||||
#define NGX_HTTP_PROPPATCH 0x0800
|
||||
#define NGX_HTTP_LOCK 0x1000
|
||||
#define NGX_HTTP_UNLOCK 0x2000
|
||||
#define NGX_HTTP_PATCH 0x4000
|
||||
#define NGX_HTTP_TRACE 0x8000
|
||||
#define NGX_HTTP_UNKNOWN 0x00000001
|
||||
#define NGX_HTTP_GET 0x00000002
|
||||
#define NGX_HTTP_HEAD 0x00000004
|
||||
#define NGX_HTTP_POST 0x00000008
|
||||
#define NGX_HTTP_PUT 0x00000010
|
||||
#define NGX_HTTP_DELETE 0x00000020
|
||||
#define NGX_HTTP_MKCOL 0x00000040
|
||||
#define NGX_HTTP_COPY 0x00000080
|
||||
#define NGX_HTTP_MOVE 0x00000100
|
||||
#define NGX_HTTP_OPTIONS 0x00000200
|
||||
#define NGX_HTTP_PROPFIND 0x00000400
|
||||
#define NGX_HTTP_PROPPATCH 0x00000800
|
||||
#define NGX_HTTP_LOCK 0x00001000
|
||||
#define NGX_HTTP_UNLOCK 0x00002000
|
||||
#define NGX_HTTP_PATCH 0x00004000
|
||||
#define NGX_HTTP_TRACE 0x00008000
|
||||
#define NGX_HTTP_CONNECT 0x00010000
|
||||
|
||||
#define NGX_HTTP_CONNECTION_CLOSE 1
|
||||
#define NGX_HTTP_CONNECTION_KEEP_ALIVE 2
|
||||
|
|
@ -301,6 +302,9 @@ typedef struct {
|
|||
ngx_chain_t *busy;
|
||||
ngx_http_chunked_t *chunked;
|
||||
ngx_http_client_body_handler_pt post_handler;
|
||||
unsigned filter_need_buffering:1;
|
||||
unsigned last_sent:1;
|
||||
unsigned last_saved:1;
|
||||
} ngx_http_request_body_t;
|
||||
|
||||
|
||||
|
|
@ -467,9 +471,6 @@ struct ngx_http_request_s {
|
|||
/* URI with "+" */
|
||||
unsigned plus_in_uri:1;
|
||||
|
||||
/* URI with " " */
|
||||
unsigned space_in_uri:1;
|
||||
|
||||
/* URI with empty path */
|
||||
unsigned empty_path_in_uri:1;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,11 +62,16 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* rb->temp_file = NULL;
|
||||
* rb->bufs = NULL;
|
||||
* rb->buf = NULL;
|
||||
* rb->free = NULL;
|
||||
* rb->busy = NULL;
|
||||
* rb->chunked = NULL;
|
||||
* rb->received = 0;
|
||||
* rb->filter_need_buffering = 0;
|
||||
* rb->last_sent = 0;
|
||||
* rb->last_saved = 0;
|
||||
*/
|
||||
|
||||
rb->rest = -1;
|
||||
|
|
@ -144,7 +149,7 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|||
}
|
||||
}
|
||||
|
||||
if (rb->rest == 0) {
|
||||
if (rb->rest == 0 && rb->last_saved) {
|
||||
/* the whole request body was pre-read */
|
||||
r->request_body_no_buffering = 0;
|
||||
post_handler(r);
|
||||
|
|
@ -172,6 +177,10 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|||
size += preread;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
size++;
|
||||
}
|
||||
|
||||
} else {
|
||||
size = clcf->client_body_buffer_size;
|
||||
}
|
||||
|
|
@ -270,6 +279,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t flush;
|
||||
ngx_chain_t out;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_request_body_t *rb;
|
||||
|
|
@ -277,12 +287,17 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||
|
||||
c = r->connection;
|
||||
rb = r->request_body;
|
||||
flush = 1;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http read client request body");
|
||||
|
||||
for ( ;; ) {
|
||||
for ( ;; ) {
|
||||
if (rb->rest == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (rb->buf->last == rb->buf->end) {
|
||||
|
||||
/* update chains */
|
||||
|
|
@ -306,12 +321,25 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rb->filter_need_buffering) {
|
||||
clcf = ngx_http_get_module_loc_conf(r,
|
||||
ngx_http_core_module);
|
||||
ngx_add_timer(c->read, clcf->client_body_timeout);
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"busy buffers after request body flush");
|
||||
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
flush = 0;
|
||||
rb->buf->pos = rb->buf->start;
|
||||
rb->buf->last = rb->buf->start;
|
||||
}
|
||||
|
|
@ -323,6 +351,10 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||
size = (size_t) rest;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
n = c->recv(c, rb->buf->last, size);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
|
|
@ -347,6 +379,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||
|
||||
/* pass buffer to request body filter chain */
|
||||
|
||||
flush = 0;
|
||||
out.buf = rb->buf;
|
||||
out.next = NULL;
|
||||
|
||||
|
|
@ -368,11 +401,19 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http client request body rest %O", rb->rest);
|
||||
|
||||
if (rb->rest == 0) {
|
||||
if (flush) {
|
||||
rc = ngx_http_request_body_filter(r, NULL);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (rb->rest == 0 && rb->last_saved) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!c->read->ready) {
|
||||
if (!c->read->ready || rb->rest == 0) {
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
ngx_add_timer(c->read, clcf->client_body_timeout);
|
||||
|
|
@ -939,15 +980,32 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
|
||||
rb = r->request_body;
|
||||
|
||||
out = NULL;
|
||||
ll = &out;
|
||||
|
||||
if (rb->rest == -1) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http request body content length filter");
|
||||
|
||||
rb->rest = r->headers_in.content_length_n;
|
||||
}
|
||||
|
||||
out = NULL;
|
||||
ll = &out;
|
||||
if (rb->rest == 0) {
|
||||
|
||||
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
||||
if (tl == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
b = tl->buf;
|
||||
|
||||
ngx_memzero(b, sizeof(ngx_buf_t));
|
||||
|
||||
b->last_buf = 1;
|
||||
|
||||
*ll = tl;
|
||||
ll = &tl->next;
|
||||
}
|
||||
}
|
||||
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
|
||||
|
|
@ -1011,6 +1069,9 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
|
||||
rb = r->request_body;
|
||||
|
||||
out = NULL;
|
||||
ll = &out;
|
||||
|
||||
if (rb->rest == -1) {
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
|
|
@ -1027,9 +1088,6 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
rb->rest = cscf->large_client_header_buffers.size;
|
||||
}
|
||||
|
||||
out = NULL;
|
||||
ll = &out;
|
||||
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
|
||||
b = NULL;
|
||||
|
|
@ -1186,15 +1244,16 @@ ngx_int_t
|
|||
ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
{
|
||||
ngx_buf_t *b;
|
||||
ngx_chain_t *cl;
|
||||
ngx_chain_t *cl, *tl, **ll;
|
||||
ngx_http_request_body_t *rb;
|
||||
|
||||
rb = r->request_body;
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
ll = &rb->bufs;
|
||||
|
||||
for (cl = rb->bufs; cl; cl = cl->next) {
|
||||
|
||||
#if 0
|
||||
for (cl = rb->bufs; cl; cl = cl->next) {
|
||||
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
||||
"http body old buf t:%d f:%d %p, pos %p, size: %z "
|
||||
"file: %O, size: %O",
|
||||
|
|
@ -1203,10 +1262,13 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
cl->buf->last - cl->buf->pos,
|
||||
cl->buf->file_pos,
|
||||
cl->buf->file_last - cl->buf->file_pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
ll = &cl->next;
|
||||
}
|
||||
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
|
||||
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
||||
"http body new buf t:%d f:%d %p, pos %p, size: %z "
|
||||
"file: %O, size: %O",
|
||||
|
|
@ -1215,15 +1277,31 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
cl->buf->last - cl->buf->pos,
|
||||
cl->buf->file_pos,
|
||||
cl->buf->file_last - cl->buf->file_pos);
|
||||
|
||||
if (cl->buf->last_buf) {
|
||||
|
||||
if (rb->last_saved) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"duplicate last buf in save filter");
|
||||
*ll = NULL;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rb->last_saved = 1;
|
||||
}
|
||||
|
||||
tl = ngx_alloc_chain_link(r->pool);
|
||||
if (tl == NULL) {
|
||||
*ll = NULL;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
tl->buf = cl->buf;
|
||||
*ll = tl;
|
||||
ll = &tl->next;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* TODO: coalesce neighbouring buffers */
|
||||
|
||||
if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
*ll = NULL;
|
||||
|
||||
if (r->request_body_no_buffering) {
|
||||
return NGX_OK;
|
||||
|
|
@ -1231,7 +1309,7 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
|
||||
if (rb->rest > 0) {
|
||||
|
||||
if (rb->buf && rb->buf->last == rb->buf->end
|
||||
if (rb->bufs && rb->buf && rb->buf->last == rb->buf->end
|
||||
&& ngx_http_write_request_body(r) != NGX_OK)
|
||||
{
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
|
|
@ -1240,10 +1318,18 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* rb->rest == 0 */
|
||||
if (!rb->last_saved) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (rb->temp_file || r->request_body_in_file_only) {
|
||||
|
||||
if (rb->bufs && rb->bufs->buf->in_file) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"body already in file");
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_write_request_body(r) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
cv = (ngx_http_complex_value_t **) (p + cmd->offset);
|
||||
|
||||
if (*cv != NULL) {
|
||||
if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +275,44 @@ ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
char *p = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_http_complex_value_t **cv;
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
|
||||
cv = (ngx_http_complex_value_t **) (p + cmd->offset);
|
||||
|
||||
if (*cv != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
*cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
|
||||
if (*cv == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||
|
||||
ccv.cf = cf;
|
||||
ccv.value = &value[1];
|
||||
ccv.complex_value = *cv;
|
||||
ccv.zero = 1;
|
||||
|
||||
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
|
|
|
|||
|
|
@ -216,6 +216,8 @@ size_t ngx_http_complex_value_size(ngx_http_request_t *r,
|
|||
ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv);
|
||||
char *ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
char *ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
char *ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
|
|
|||
|
|
@ -187,6 +187,8 @@ static void ngx_http_upstream_ssl_handshake(ngx_http_request_t *,
|
|||
static void ngx_http_upstream_ssl_save_session(ngx_connection_t *c);
|
||||
static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u, ngx_connection_t *c);
|
||||
static ngx_int_t ngx_http_upstream_ssl_certificate(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u, ngx_connection_t *c);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1509,8 +1511,9 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
|
|||
static void
|
||||
ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *c;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
r->connection->log->action = "connecting to upstream";
|
||||
|
||||
|
|
@ -1597,10 +1600,12 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||
|
||||
/* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
u->writer.out = NULL;
|
||||
u->writer.last = &u->writer.out;
|
||||
u->writer.connection = c;
|
||||
u->writer.limit = 0;
|
||||
u->writer.limit = clcf->sendfile_max_chunk;
|
||||
|
||||
if (u->request_sent) {
|
||||
if (ngx_http_upstream_reinit(r, u) != NGX_OK) {
|
||||
|
|
@ -1681,9 +1686,6 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
|
|||
return;
|
||||
}
|
||||
|
||||
c->sendfile = 0;
|
||||
u->output.sendfile = 0;
|
||||
|
||||
if (u->conf->ssl_server_name || u->conf->ssl_verify) {
|
||||
if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
|
|
@ -1692,6 +1694,16 @@ 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 (ngx_http_upstream_ssl_certificate(r, u, c) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (u->conf->ssl_session_reuse) {
|
||||
c->ssl->save_session = ngx_http_upstream_ssl_save_session;
|
||||
|
||||
|
|
@ -1779,6 +1791,11 @@ ngx_http_upstream_ssl_handshake(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
|||
}
|
||||
}
|
||||
|
||||
if (!c->ssl->sendfile) {
|
||||
c->sendfile = 0;
|
||||
u->output.sendfile = 0;
|
||||
}
|
||||
|
||||
c->write->handler = ngx_http_upstream_handler;
|
||||
c->read->handler = ngx_http_upstream_handler;
|
||||
|
||||
|
|
@ -1912,6 +1929,45 @@ done:
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_ssl_certificate(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u, ngx_connection_t *c)
|
||||
{
|
||||
ngx_str_t cert, key;
|
||||
|
||||
if (ngx_http_complex_value(r, u->conf->ssl_certificate, &cert)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http upstream ssl cert: \"%s\"", cert.data);
|
||||
|
||||
if (*cert.data == '\0') {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ngx_http_complex_value(r, u->conf->ssl_certificate_key, &key)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http upstream ssl key: \"%s\"", key.data);
|
||||
|
||||
if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key,
|
||||
u->conf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -3791,6 +3847,7 @@ ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
|
|||
{
|
||||
ngx_str_t name;
|
||||
ngx_event_pipe_t *p;
|
||||
ngx_connection_t *c;
|
||||
ngx_thread_pool_t *tp;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
|
@ -3798,6 +3855,27 @@ ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
|
|||
r = file->thread_ctx;
|
||||
p = r->upstream->pipe;
|
||||
|
||||
if (r->aio) {
|
||||
/*
|
||||
* tolerate sendfile() calls if another operation is already
|
||||
* running; this can happen due to subrequests, multiple calls
|
||||
* of the next body filter from a filter, or in HTTP/2 due to
|
||||
* a write event on the main connection
|
||||
*/
|
||||
|
||||
c = r->connection;
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
c = r->stream->connection->connection;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (task == c->sendfile_task) {
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
tp = clcf->thread_pool;
|
||||
|
||||
|
|
@ -3849,6 +3927,20 @@ ngx_http_upstream_thread_event_handler(ngx_event_t *ev)
|
|||
r->main->blocked--;
|
||||
r->aio = 0;
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
|
||||
if (r->stream) {
|
||||
/*
|
||||
* for HTTP/2, update write event to make sure processing will
|
||||
* reach the main connection to handle sendfile() in threads
|
||||
*/
|
||||
|
||||
c->write->ready = 1;
|
||||
c->write->active = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (r->done) {
|
||||
/*
|
||||
* trigger connection event handler if the subrequest was
|
||||
|
|
|
|||
|
|
@ -234,6 +234,10 @@ typedef struct {
|
|||
ngx_http_complex_value_t *ssl_name;
|
||||
ngx_flag_t ssl_server_name;
|
||||
ngx_flag_t ssl_verify;
|
||||
|
||||
ngx_http_complex_value_t *ssl_certificate;
|
||||
ngx_http_complex_value_t *ssl_certificate_key;
|
||||
ngx_array_t *ssl_passwords;
|
||||
#endif
|
||||
|
||||
ngx_str_t module;
|
||||
|
|
|
|||
|
|
@ -321,18 +321,13 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||
delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate);
|
||||
|
||||
if (delay > 0) {
|
||||
limit = 0;
|
||||
c->write->delayed = 1;
|
||||
ngx_add_timer(c->write, delay);
|
||||
}
|
||||
}
|
||||
|
||||
if (limit
|
||||
&& c->write->ready
|
||||
&& c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
|
||||
{
|
||||
c->write->delayed = 1;
|
||||
ngx_add_timer(c->write, 1);
|
||||
if (chain && c->write->ready && !c->write->delayed) {
|
||||
ngx_post_event(c->write, &ngx_posted_next_events);
|
||||
}
|
||||
|
||||
for (cl = r->out; cl && cl != chain; /* void */) {
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
|
|||
static void ngx_http_v2_run_request(ngx_http_request_t *r);
|
||||
static void ngx_http_v2_run_request_handler(ngx_event_t *ev);
|
||||
static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r,
|
||||
u_char *pos, size_t size, ngx_uint_t last);
|
||||
u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush);
|
||||
static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r);
|
||||
static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r);
|
||||
|
||||
|
|
@ -1140,9 +1140,10 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
h2c->payload_bytes += size;
|
||||
|
||||
if (r->request_body) {
|
||||
rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed);
|
||||
rc = ngx_http_v2_process_request_body(r, pos, size,
|
||||
stream->in_closed, 0);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
if (rc != NGX_OK && rc != NGX_AGAIN) {
|
||||
stream->skip_data = 1;
|
||||
ngx_http_finalize_request(r, rc);
|
||||
}
|
||||
|
|
@ -1599,10 +1600,10 @@ ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
h2c->state.length -= size;
|
||||
h2c->state.field_rest -= size;
|
||||
|
||||
if (ngx_http_v2_huff_decode(&h2c->state.field_state, pos, size,
|
||||
&h2c->state.field_end,
|
||||
h2c->state.field_rest == 0,
|
||||
h2c->connection->log)
|
||||
if (ngx_http_huff_decode(&h2c->state.field_state, pos, size,
|
||||
&h2c->state.field_end,
|
||||
h2c->state.field_rest == 0,
|
||||
h2c->connection->log)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||
|
|
@ -3457,7 +3458,7 @@ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ch == '\0' || ch == LF || ch == CR || ch == ':'
|
||||
if (ch <= 0x20 || ch == 0x7f || ch == ':'
|
||||
|| (ch >= 'A' && ch <= 'Z'))
|
||||
{
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
|
|
@ -3606,7 +3607,8 @@ ngx_http_v2_parse_method(ngx_http_request_t *r, ngx_str_t *value)
|
|||
{ 4, "LOCK", NGX_HTTP_LOCK },
|
||||
{ 6, "UNLOCK", NGX_HTTP_UNLOCK },
|
||||
{ 5, "PATCH", NGX_HTTP_PATCH },
|
||||
{ 5, "TRACE", NGX_HTTP_TRACE }
|
||||
{ 5, "TRACE", NGX_HTTP_TRACE },
|
||||
{ 7, "CONNECT", NGX_HTTP_CONNECT }
|
||||
}, *test;
|
||||
|
||||
if (r->method_name.len) {
|
||||
|
|
@ -4026,16 +4028,30 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r)
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
rb->rest = 1;
|
||||
|
||||
/* set rb->filter_need_buffering */
|
||||
|
||||
rc = ngx_http_top_request_body_filter(r, NULL);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
stream->skip_data = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
len = r->headers_in.content_length_n;
|
||||
|
||||
if (r->request_body_no_buffering && !stream->in_closed) {
|
||||
if (len < 0 || len > (off_t) clcf->client_body_buffer_size) {
|
||||
len = clcf->client_body_buffer_size;
|
||||
|
||||
if (len < 0 || len > (off_t) clcf->client_body_buffer_size) {
|
||||
len = clcf->client_body_buffer_size;
|
||||
}
|
||||
} else {
|
||||
len++;
|
||||
}
|
||||
|
||||
if (r->request_body_no_buffering || rb->filter_need_buffering) {
|
||||
|
||||
/*
|
||||
* We need a room to store data up to the stream's initial window size,
|
||||
|
|
@ -4049,57 +4065,54 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r)
|
|||
if (len > NGX_HTTP_V2_MAX_WINDOW) {
|
||||
len = NGX_HTTP_V2_MAX_WINDOW;
|
||||
}
|
||||
|
||||
rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
|
||||
|
||||
} else if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size
|
||||
&& !r->request_body_in_file_only)
|
||||
{
|
||||
rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
|
||||
|
||||
} else {
|
||||
rb->buf = ngx_calloc_buf(r->pool);
|
||||
|
||||
if (rb->buf != NULL) {
|
||||
rb->buf->sync = 1;
|
||||
}
|
||||
}
|
||||
|
||||
rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
|
||||
|
||||
if (rb->buf == NULL) {
|
||||
stream->skip_data = 1;
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rb->rest = 1;
|
||||
|
||||
buf = stream->preread;
|
||||
|
||||
if (stream->in_closed) {
|
||||
r->request_body_no_buffering = 0;
|
||||
if (!rb->filter_need_buffering) {
|
||||
r->request_body_no_buffering = 0;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
rc = ngx_http_v2_process_request_body(r, buf->pos,
|
||||
buf->last - buf->pos, 1);
|
||||
buf->last - buf->pos, 1, 0);
|
||||
ngx_pfree(r->pool, buf->start);
|
||||
|
||||
} else {
|
||||
rc = ngx_http_v2_process_request_body(r, NULL, 0, 1, 0);
|
||||
}
|
||||
|
||||
if (rc != NGX_AGAIN) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return ngx_http_v2_process_request_body(r, NULL, 0, 1);
|
||||
r->read_event_handler = ngx_http_v2_read_client_request_body_handler;
|
||||
r->write_event_handler = ngx_http_request_empty_handler;
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
rc = ngx_http_v2_process_request_body(r, buf->pos,
|
||||
buf->last - buf->pos, 0);
|
||||
buf->last - buf->pos, 0, 0);
|
||||
|
||||
ngx_pfree(r->pool, buf->start);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
if (rc != NGX_OK && rc != NGX_AGAIN) {
|
||||
stream->skip_data = 1;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (r->request_body_no_buffering) {
|
||||
if (r->request_body_no_buffering || rb->filter_need_buffering) {
|
||||
size = (size_t) len - h2scf->preread_size;
|
||||
|
||||
} else {
|
||||
|
|
@ -4141,9 +4154,9 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r)
|
|||
|
||||
static ngx_int_t
|
||||
ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos,
|
||||
size_t size, ngx_uint_t last)
|
||||
size_t size, ngx_uint_t last, ngx_uint_t flush)
|
||||
{
|
||||
ngx_buf_t *buf;
|
||||
size_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *fc;
|
||||
ngx_http_request_body_t *rb;
|
||||
|
|
@ -4151,77 +4164,122 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos,
|
|||
|
||||
fc = r->connection;
|
||||
rb = r->request_body;
|
||||
buf = rb->buf;
|
||||
|
||||
if (size) {
|
||||
if (buf->sync) {
|
||||
buf->pos = buf->start = pos;
|
||||
buf->last = buf->end = pos + size;
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||
"http2 process request body");
|
||||
|
||||
r->request_body_in_file_only = 1;
|
||||
if (size == 0 && !last && !flush) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (size > (size_t) (buf->end - buf->last)) {
|
||||
ngx_log_error(NGX_LOG_INFO, fc->log, 0,
|
||||
"client intended to send body data "
|
||||
"larger than declared");
|
||||
for ( ;; ) {
|
||||
for ( ;; ) {
|
||||
if (rb->buf->last == rb->buf->end && size) {
|
||||
|
||||
return NGX_HTTP_BAD_REQUEST;
|
||||
if (r->request_body_no_buffering) {
|
||||
|
||||
/* should never happen due to flow control */
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, fc->log, 0,
|
||||
"no space in http2 body buffer");
|
||||
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
/* update chains */
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||
"http2 body update chains");
|
||||
|
||||
rc = ngx_http_v2_filter_request_body(r);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rb->busy != NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, fc->log, 0,
|
||||
"busy buffers after request body flush");
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rb->buf->pos = rb->buf->start;
|
||||
rb->buf->last = rb->buf->start;
|
||||
}
|
||||
|
||||
buf->last = ngx_cpymem(buf->last, pos, size);
|
||||
/* copy body data to the buffer */
|
||||
|
||||
n = rb->buf->end - rb->buf->last;
|
||||
|
||||
if (n > size) {
|
||||
n = size;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
rb->buf->last = ngx_cpymem(rb->buf->last, pos, n);
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||
"http2 request body recv %uz", n);
|
||||
|
||||
pos += n;
|
||||
size -= n;
|
||||
|
||||
if (size == 0 && last) {
|
||||
rb->rest = 0;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||
"http2 request body rest %O", rb->rest);
|
||||
|
||||
if (flush) {
|
||||
rc = ngx_http_v2_filter_request_body(r);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (rb->rest == 0 && rb->last_saved) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
ngx_add_timer(fc->read, clcf->client_body_timeout);
|
||||
|
||||
if (!flush) {
|
||||
ngx_post_event(fc->read, &ngx_posted_events);
|
||||
}
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (last) {
|
||||
rb->rest = 0;
|
||||
|
||||
if (fc->read->timer_set) {
|
||||
ngx_del_timer(fc->read);
|
||||
}
|
||||
|
||||
if (r->request_body_no_buffering) {
|
||||
ngx_post_event(fc->read, &ngx_posted_events);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
rc = ngx_http_v2_filter_request_body(r);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (buf->sync) {
|
||||
/* prevent reusing this buffer in the upstream module */
|
||||
rb->buf = NULL;
|
||||
}
|
||||
|
||||
if (r->headers_in.chunked) {
|
||||
r->headers_in.content_length_n = rb->received;
|
||||
}
|
||||
|
||||
r->read_event_handler = ngx_http_block_reading;
|
||||
rb->post_handler(r);
|
||||
|
||||
return NGX_OK;
|
||||
if (fc->read->timer_set) {
|
||||
ngx_del_timer(fc->read);
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
ngx_add_timer(fc->read, clcf->client_body_timeout);
|
||||
|
||||
if (r->request_body_no_buffering) {
|
||||
ngx_post_event(fc->read, &ngx_posted_events);
|
||||
if (!flush) {
|
||||
ngx_post_event(fc->read, &ngx_posted_events);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (buf->sync) {
|
||||
return ngx_http_v2_filter_request_body(r);
|
||||
if (r->headers_in.chunked) {
|
||||
r->headers_in.content_length_n = rb->received;
|
||||
}
|
||||
|
||||
r->read_event_handler = ngx_http_block_reading;
|
||||
rb->post_handler(r);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -4238,7 +4296,7 @@ ngx_http_v2_filter_request_body(ngx_http_request_t *r)
|
|||
rb = r->request_body;
|
||||
buf = rb->buf;
|
||||
|
||||
if (buf->pos == buf->last && rb->rest) {
|
||||
if (buf->pos == buf->last && (rb->rest || rb->last_sent)) {
|
||||
cl = NULL;
|
||||
goto update;
|
||||
}
|
||||
|
|
@ -4301,6 +4359,7 @@ ngx_http_v2_filter_request_body(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
b->last_buf = 1;
|
||||
rb->last_sent = 1;
|
||||
}
|
||||
|
||||
b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body;
|
||||
|
|
@ -4320,7 +4379,12 @@ update:
|
|||
static void
|
||||
ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_connection_t *fc;
|
||||
size_t window;
|
||||
ngx_buf_t *buf;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *fc;
|
||||
ngx_http_v2_stream_t *stream;
|
||||
ngx_http_v2_connection_t *h2c;
|
||||
|
||||
fc = r->connection;
|
||||
|
||||
|
|
@ -4346,6 +4410,75 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
|
|||
ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1);
|
||||
|
||||
if (rc != NGX_OK && rc != NGX_AGAIN) {
|
||||
r->stream->skip_data = 1;
|
||||
ngx_http_finalize_request(r, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r->stream->no_flow_control) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r->request_body->rest == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r->request_body->busy != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
stream = r->stream;
|
||||
h2c = stream->connection;
|
||||
|
||||
buf = r->request_body->buf;
|
||||
|
||||
buf->pos = buf->start;
|
||||
buf->last = buf->start;
|
||||
|
||||
window = buf->end - buf->start;
|
||||
|
||||
if (h2c->state.stream == stream) {
|
||||
window -= h2c->state.length;
|
||||
}
|
||||
|
||||
if (window <= stream->recv_window) {
|
||||
if (window < stream->recv_window) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"http2 negative window update");
|
||||
|
||||
stream->skip_data = 1;
|
||||
|
||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ngx_http_v2_send_window_update(h2c, stream->node->id,
|
||||
window - stream->recv_window)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
stream->skip_data = 1;
|
||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
stream->recv_window = window;
|
||||
|
||||
if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
|
||||
stream->skip_data = 1;
|
||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4358,11 +4491,13 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r)
|
|||
ngx_connection_t *fc;
|
||||
ngx_http_v2_stream_t *stream;
|
||||
ngx_http_v2_connection_t *h2c;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
stream = r->stream;
|
||||
fc = r->connection;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||
"http2 read unbuffered request body");
|
||||
|
||||
if (fc->read->timedout) {
|
||||
if (stream->recv_window) {
|
||||
stream->skip_data = 1;
|
||||
|
|
@ -4379,17 +4514,21 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r)
|
|||
return NGX_HTTP_BAD_REQUEST;
|
||||
}
|
||||
|
||||
rc = ngx_http_v2_filter_request_body(r);
|
||||
rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
if (rc != NGX_OK && rc != NGX_AGAIN) {
|
||||
stream->skip_data = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!r->request_body->rest) {
|
||||
if (rc == NGX_OK) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (r->request_body->rest == 0) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (r->request_body->busy != NULL) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
|
@ -4430,11 +4569,6 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r)
|
|||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (stream->recv_window == 0) {
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
ngx_add_timer(fc->read, clcf->client_body_timeout);
|
||||
}
|
||||
|
||||
stream->recv_window = window;
|
||||
|
||||
return NGX_AGAIN;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#define NGX_HTTP_V2_ALPN_ADVERTISE "\x02h2"
|
||||
#define NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_V2_ALPN_ADVERTISE
|
||||
#define NGX_HTTP_V2_ALPN_PROTO "\x02h2"
|
||||
|
||||
#define NGX_HTTP_V2_STATE_BUFFER_SIZE 16
|
||||
|
||||
|
|
@ -312,12 +311,6 @@ ngx_int_t ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c,
|
|||
ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size);
|
||||
|
||||
|
||||
ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len,
|
||||
u_char **dst, ngx_uint_t last, ngx_log_t *log);
|
||||
size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst,
|
||||
ngx_uint_t lower);
|
||||
|
||||
|
||||
#define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp,
|
|||
{
|
||||
size_t hlen;
|
||||
|
||||
hlen = ngx_http_v2_huff_encode(src, len, tmp, lower);
|
||||
hlen = ngx_http_huff_encode(src, len, tmp, lower);
|
||||
|
||||
if (hlen > 0) {
|
||||
*dst = NGX_HTTP_V2_ENCODE_HUFF;
|
||||
|
|
|
|||
|
|
@ -1432,6 +1432,9 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
|
|||
size = 0;
|
||||
#endif
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||
"http2 send chain: %p", in);
|
||||
|
||||
while (in) {
|
||||
size = ngx_buf_size(in->buf);
|
||||
|
||||
|
|
@ -1450,12 +1453,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
|
|||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
if (stream->queued) {
|
||||
fc->write->active = 1;
|
||||
fc->write->ready = 0;
|
||||
|
||||
} else {
|
||||
fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
|
||||
if (ngx_http_v2_filter_send(fc, stream) == NGX_ERROR) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -1464,9 +1463,16 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
|
|||
h2c = stream->connection;
|
||||
|
||||
if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) {
|
||||
fc->write->active = 1;
|
||||
fc->write->ready = 0;
|
||||
return in;
|
||||
|
||||
if (ngx_http_v2_filter_send(fc, stream) == NGX_ERROR) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) {
|
||||
fc->write->active = 1;
|
||||
fc->write->ready = 0;
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) {
|
||||
|
|
@ -1809,6 +1815,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) {
|
||||
fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
stream->blocked = 1;
|
||||
|
||||
if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ typedef struct {
|
|||
ngx_msec_t timeout;
|
||||
ngx_msec_t resolver_timeout;
|
||||
|
||||
ngx_uint_t max_errors;
|
||||
|
||||
ngx_str_t server_name;
|
||||
|
||||
u_char *file_name;
|
||||
|
|
@ -231,14 +233,15 @@ typedef struct {
|
|||
ngx_uint_t command;
|
||||
ngx_array_t args;
|
||||
|
||||
ngx_uint_t errors;
|
||||
ngx_uint_t login_attempt;
|
||||
|
||||
/* used to parse POP3/IMAP/SMTP command */
|
||||
|
||||
ngx_uint_t state;
|
||||
u_char *tag_start;
|
||||
u_char *cmd_start;
|
||||
u_char *arg_start;
|
||||
u_char *arg_end;
|
||||
ngx_uint_t literal_len;
|
||||
} ngx_mail_session_t;
|
||||
|
||||
|
|
@ -321,6 +324,7 @@ typedef ngx_int_t (*ngx_mail_parse_command_pt)(ngx_mail_session_t *s);
|
|||
|
||||
struct ngx_mail_protocol_s {
|
||||
ngx_str_t name;
|
||||
ngx_str_t alpn;
|
||||
in_port_t port[4];
|
||||
ngx_uint_t type;
|
||||
|
||||
|
|
|
|||
|
|
@ -1137,8 +1137,8 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
|
|||
ngx_str_t login, passwd;
|
||||
ngx_connection_t *c;
|
||||
#if (NGX_MAIL_SSL)
|
||||
ngx_str_t verify, subject, issuer, serial, fingerprint,
|
||||
raw_cert, cert;
|
||||
ngx_str_t protocol, cipher, verify, subject, issuer,
|
||||
serial, fingerprint, raw_cert, cert;
|
||||
ngx_mail_ssl_conf_t *sslcf;
|
||||
#endif
|
||||
ngx_mail_core_srv_conf_t *cscf;
|
||||
|
|
@ -1155,6 +1155,25 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
|
|||
|
||||
#if (NGX_MAIL_SSL)
|
||||
|
||||
if (c->ssl) {
|
||||
|
||||
if (ngx_ssl_get_protocol(c, pool, &protocol) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protocol.len = ngx_strlen(protocol.data);
|
||||
|
||||
if (ngx_ssl_get_cipher_name(c, pool, &cipher) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cipher.len = ngx_strlen(cipher.data);
|
||||
|
||||
} else {
|
||||
ngx_str_null(&protocol);
|
||||
ngx_str_null(&cipher);
|
||||
}
|
||||
|
||||
sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
|
||||
|
||||
if (c->ssl && sslcf->verify) {
|
||||
|
|
@ -1252,6 +1271,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
|
|||
|
||||
if (c->ssl) {
|
||||
len += sizeof("Auth-SSL: on" CRLF) - 1
|
||||
+ sizeof("Auth-SSL-Protocol: ") - 1 + protocol.len
|
||||
+ sizeof(CRLF) - 1
|
||||
+ sizeof("Auth-SSL-Cipher: ") - 1 + cipher.len
|
||||
+ sizeof(CRLF) - 1
|
||||
+ sizeof("Auth-SSL-Verify: ") - 1 + verify.len
|
||||
+ sizeof(CRLF) - 1
|
||||
+ sizeof("Auth-SSL-Subject: ") - 1 + subject.len
|
||||
|
|
@ -1373,6 +1396,20 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
|
|||
b->last = ngx_cpymem(b->last, "Auth-SSL: on" CRLF,
|
||||
sizeof("Auth-SSL: on" CRLF) - 1);
|
||||
|
||||
if (protocol.len) {
|
||||
b->last = ngx_cpymem(b->last, "Auth-SSL-Protocol: ",
|
||||
sizeof("Auth-SSL-Protocol: ") - 1);
|
||||
b->last = ngx_copy(b->last, protocol.data, protocol.len);
|
||||
*b->last++ = CR; *b->last++ = LF;
|
||||
}
|
||||
|
||||
if (cipher.len) {
|
||||
b->last = ngx_cpymem(b->last, "Auth-SSL-Cipher: ",
|
||||
sizeof("Auth-SSL-Cipher: ") - 1);
|
||||
b->last = ngx_copy(b->last, cipher.data, cipher.len);
|
||||
*b->last++ = CR; *b->last++ = LF;
|
||||
}
|
||||
|
||||
if (verify.len) {
|
||||
b->last = ngx_cpymem(b->last, "Auth-SSL-Verify: ",
|
||||
sizeof("Auth-SSL-Verify: ") - 1);
|
||||
|
|
|
|||
|
|
@ -85,6 +85,13 @@ static ngx_command_t ngx_mail_core_commands[] = {
|
|||
offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("max_errors"),
|
||||
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot,
|
||||
NGX_MAIL_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_mail_core_srv_conf_t, max_errors),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
|
@ -163,6 +170,8 @@ ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
|
|||
cscf->timeout = NGX_CONF_UNSET_MSEC;
|
||||
cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
|
||||
|
||||
cscf->max_errors = NGX_CONF_UNSET_UINT;
|
||||
|
||||
cscf->resolver = NGX_CONF_UNSET_PTR;
|
||||
|
||||
cscf->file_name = cf->conf_file->file.name.data;
|
||||
|
|
@ -182,6 +191,7 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
|
||||
30000);
|
||||
|
||||
ngx_conf_merge_uint_value(conf->max_errors, prev->max_errors, 5);
|
||||
|
||||
ngx_conf_merge_str_value(conf->server_name, prev->server_name, "");
|
||||
|
||||
|
|
|
|||
|
|
@ -833,20 +833,23 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||
ngx_str_t l;
|
||||
ngx_mail_core_srv_conf_t *cscf;
|
||||
|
||||
n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last);
|
||||
if (s->buffer->last < s->buffer->end) {
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
ngx_mail_close_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last);
|
||||
|
||||
if (n > 0) {
|
||||
s->buffer->last += n;
|
||||
}
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
ngx_mail_close_connection(c);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
return NGX_AGAIN;
|
||||
if (n > 0) {
|
||||
s->buffer->last += n;
|
||||
}
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -871,7 +874,20 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) {
|
||||
if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) {
|
||||
|
||||
s->errors++;
|
||||
|
||||
if (s->errors >= cscf->max_errors) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||
"client sent too many invalid commands");
|
||||
s->quit = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rc == NGX_IMAP_NEXT) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,10 +101,9 @@ ngx_mail_imap_init_protocol(ngx_event_t *rev)
|
|||
void
|
||||
ngx_mail_imap_auth_state(ngx_event_t *rev)
|
||||
{
|
||||
u_char *p, *dst, *src, *end;
|
||||
ngx_str_t *arg;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t tag, i;
|
||||
ngx_uint_t tag;
|
||||
ngx_connection_t *c;
|
||||
ngx_mail_session_t *s;
|
||||
|
||||
|
|
@ -158,27 +157,6 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i",
|
||||
s->command);
|
||||
|
||||
if (s->backslash) {
|
||||
|
||||
arg = s->args.elts;
|
||||
|
||||
for (i = 0; i < s->args.nelts; i++) {
|
||||
dst = arg[i].data;
|
||||
end = dst + arg[i].len;
|
||||
|
||||
for (src = dst; src < end; dst++) {
|
||||
*dst = *src;
|
||||
if (*src++ == '\\') {
|
||||
*dst = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
arg[i].len = dst - arg[i].data;
|
||||
}
|
||||
|
||||
s->backslash = 0;
|
||||
}
|
||||
|
||||
switch (s->mail_state) {
|
||||
|
||||
case ngx_imap_start:
|
||||
|
|
@ -248,6 +226,10 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
|
|||
ngx_str_set(&s->out, imap_next);
|
||||
}
|
||||
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
s->blocked = 1;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
|
||||
case NGX_DONE:
|
||||
|
|
@ -297,13 +279,14 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
|
|||
|
||||
if (s->state) {
|
||||
/* preserve tag */
|
||||
s->arg_start = s->buffer->start + s->tag.len;
|
||||
s->buffer->pos = s->arg_start;
|
||||
s->buffer->last = s->arg_start;
|
||||
s->arg_start = s->buffer->pos;
|
||||
|
||||
} else {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
}
|
||||
|
||||
s->tag.len = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -481,6 +464,8 @@ ngx_mail_imap_starttls(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||
if (c->ssl == NULL) {
|
||||
sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
|
||||
if (sslcf->starttls) {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
c->read->handler = ngx_mail_starttls_handler;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ static ngx_str_t ngx_mail_imap_auth_methods_names[] = {
|
|||
|
||||
static ngx_mail_protocol_t ngx_mail_imap_protocol = {
|
||||
ngx_string("imap"),
|
||||
ngx_string("\x04imap"),
|
||||
{ 143, 993, 0, 0 },
|
||||
NGX_MAIL_IMAP_PROTOCOL,
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
|
|||
ngx_str_t *arg;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_command,
|
||||
sw_invalid,
|
||||
sw_spaces_before_argument,
|
||||
sw_argument,
|
||||
sw_almost_done
|
||||
|
|
@ -35,8 +37,14 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
|
|||
|
||||
/* POP3 command */
|
||||
case sw_start:
|
||||
s->cmd_start = p;
|
||||
state = sw_command;
|
||||
|
||||
/* fall through */
|
||||
|
||||
case sw_command:
|
||||
if (ch == ' ' || ch == CR || ch == LF) {
|
||||
c = s->buffer->start;
|
||||
c = s->cmd_start;
|
||||
|
||||
if (p - c == 4) {
|
||||
|
||||
|
|
@ -85,6 +93,9 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
|
|||
goto invalid;
|
||||
}
|
||||
|
||||
s->cmd.data = s->cmd_start;
|
||||
s->cmd.len = p - s->cmd_start;
|
||||
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
state = sw_spaces_before_argument;
|
||||
|
|
@ -104,16 +115,17 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
|
|||
|
||||
break;
|
||||
|
||||
case sw_invalid:
|
||||
goto invalid;
|
||||
|
||||
case sw_spaces_before_argument:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
state = sw_almost_done;
|
||||
s->arg_end = p;
|
||||
break;
|
||||
case LF:
|
||||
s->arg_end = p;
|
||||
goto done;
|
||||
default:
|
||||
if (s->args.nelts <= 2) {
|
||||
|
|
@ -188,37 +200,39 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
|
|||
done:
|
||||
|
||||
s->buffer->pos = p + 1;
|
||||
|
||||
if (s->arg_start) {
|
||||
arg = ngx_array_push(&s->args);
|
||||
if (arg == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
arg->len = s->arg_end - s->arg_start;
|
||||
arg->data = s->arg_start;
|
||||
s->arg_start = NULL;
|
||||
}
|
||||
|
||||
s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
invalid:
|
||||
|
||||
s->state = sw_start;
|
||||
s->arg_start = NULL;
|
||||
s->state = sw_invalid;
|
||||
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
/* skip invalid command till LF */
|
||||
|
||||
for ( /* void */ ; p < s->buffer->last; p++) {
|
||||
if (*p == LF) {
|
||||
s->state = sw_start;
|
||||
s->buffer->pos = p + 1;
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
s->buffer->pos = p;
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_mail_imap_parse_command(ngx_mail_session_t *s)
|
||||
{
|
||||
u_char ch, *p, *c;
|
||||
u_char ch, *p, *c, *dst, *src, *end;
|
||||
ngx_str_t *arg;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_tag,
|
||||
sw_invalid,
|
||||
sw_spaces_before_command,
|
||||
sw_command,
|
||||
sw_spaces_before_argument,
|
||||
|
|
@ -241,31 +255,45 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s)
|
|||
|
||||
/* IMAP tag */
|
||||
case sw_start:
|
||||
s->tag_start = p;
|
||||
state = sw_tag;
|
||||
|
||||
/* fall through */
|
||||
|
||||
case sw_tag:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
s->tag.len = p - s->buffer->start + 1;
|
||||
s->tag.data = s->buffer->start;
|
||||
s->tag.len = p - s->tag_start + 1;
|
||||
s->tag.data = s->tag_start;
|
||||
state = sw_spaces_before_command;
|
||||
break;
|
||||
case CR:
|
||||
s->state = sw_start;
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
case LF:
|
||||
s->state = sw_start;
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
goto invalid;
|
||||
default:
|
||||
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')
|
||||
&& (ch < '0' || ch > '9') && ch != '-' && ch != '.'
|
||||
&& ch != '_')
|
||||
{
|
||||
goto invalid;
|
||||
}
|
||||
if (p - s->tag_start > 31) {
|
||||
goto invalid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case sw_invalid:
|
||||
goto invalid;
|
||||
|
||||
case sw_spaces_before_command:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case CR:
|
||||
s->state = sw_start;
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
case LF:
|
||||
s->state = sw_start;
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
goto invalid;
|
||||
default:
|
||||
s->cmd_start = p;
|
||||
state = sw_command;
|
||||
|
|
@ -385,6 +413,9 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s)
|
|||
goto invalid;
|
||||
}
|
||||
|
||||
s->cmd.data = s->cmd_start;
|
||||
s->cmd.len = p - s->cmd_start;
|
||||
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
state = sw_spaces_before_argument;
|
||||
|
|
@ -410,10 +441,8 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s)
|
|||
break;
|
||||
case CR:
|
||||
state = sw_almost_done;
|
||||
s->arg_end = p;
|
||||
break;
|
||||
case LF:
|
||||
s->arg_end = p;
|
||||
goto done;
|
||||
case '"':
|
||||
if (s->args.nelts <= 2) {
|
||||
|
|
@ -460,6 +489,22 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s)
|
|||
}
|
||||
arg->len = p - s->arg_start;
|
||||
arg->data = s->arg_start;
|
||||
|
||||
if (s->backslash) {
|
||||
dst = s->arg_start;
|
||||
end = p;
|
||||
|
||||
for (src = dst; src < end; dst++) {
|
||||
*dst = *src;
|
||||
if (*src++ == '\\') {
|
||||
*dst = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
arg->len = dst - s->arg_start;
|
||||
s->backslash = 0;
|
||||
}
|
||||
|
||||
s->arg_start = NULL;
|
||||
|
||||
switch (ch) {
|
||||
|
|
@ -588,34 +633,46 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s)
|
|||
done:
|
||||
|
||||
s->buffer->pos = p + 1;
|
||||
|
||||
if (s->arg_start) {
|
||||
arg = ngx_array_push(&s->args);
|
||||
if (arg == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
arg->len = s->arg_end - s->arg_start;
|
||||
arg->data = s->arg_start;
|
||||
|
||||
s->arg_start = NULL;
|
||||
s->cmd_start = NULL;
|
||||
s->quoted = 0;
|
||||
s->no_sync_literal = 0;
|
||||
s->literal_len = 0;
|
||||
}
|
||||
|
||||
s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
invalid:
|
||||
|
||||
s->state = sw_start;
|
||||
s->state = sw_invalid;
|
||||
s->quoted = 0;
|
||||
s->backslash = 0;
|
||||
s->no_sync_literal = 0;
|
||||
s->literal_len = 0;
|
||||
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
/* skip invalid command till LF */
|
||||
|
||||
for ( /* void */ ; p < s->buffer->last; p++) {
|
||||
if (*p == LF) {
|
||||
s->state = sw_start;
|
||||
s->buffer->pos = p + 1;
|
||||
|
||||
/* detect non-synchronizing literals */
|
||||
|
||||
if ((size_t) (p - s->buffer->start) > sizeof("{1+}") - 1) {
|
||||
p--;
|
||||
|
||||
if (*p == CR) {
|
||||
p--;
|
||||
}
|
||||
|
||||
if (*p == '}' && *(p - 1) == '+') {
|
||||
s->quit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
s->buffer->pos = p;
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -758,10 +815,8 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
|
|||
break;
|
||||
case CR:
|
||||
state = sw_almost_done;
|
||||
s->arg_end = p;
|
||||
break;
|
||||
case LF:
|
||||
s->arg_end = p;
|
||||
goto done;
|
||||
default:
|
||||
if (s->args.nelts <= 10) {
|
||||
|
|
@ -821,17 +876,6 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
|
|||
done:
|
||||
|
||||
s->buffer->pos = p + 1;
|
||||
|
||||
if (s->arg_start) {
|
||||
arg = ngx_array_push(&s->args);
|
||||
if (arg == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
arg->len = s->arg_end - s->arg_start;
|
||||
arg->data = s->arg_start;
|
||||
s->arg_start = NULL;
|
||||
}
|
||||
|
||||
s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument;
|
||||
|
||||
return NGX_OK;
|
||||
|
|
@ -839,21 +883,20 @@ done:
|
|||
invalid:
|
||||
|
||||
s->state = sw_invalid;
|
||||
s->arg_start = NULL;
|
||||
|
||||
/* skip invalid command till LF */
|
||||
|
||||
for (p = s->buffer->pos; p < s->buffer->last; p++) {
|
||||
for ( /* void */ ; p < s->buffer->last; p++) {
|
||||
if (*p == LF) {
|
||||
s->state = sw_start;
|
||||
p++;
|
||||
break;
|
||||
s->buffer->pos = p + 1;
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
s->buffer->pos = p;
|
||||
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -262,6 +262,10 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
|
|||
}
|
||||
}
|
||||
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
s->blocked = 1;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
|
||||
case NGX_DONE:
|
||||
|
|
@ -283,11 +287,14 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
|
|||
case NGX_OK:
|
||||
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
}
|
||||
|
||||
if (s->state) {
|
||||
s->arg_start = s->buffer->start;
|
||||
s->arg_start = s->buffer->pos;
|
||||
}
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
|
|
@ -400,6 +407,8 @@ ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||
if (c->ssl == NULL) {
|
||||
sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
|
||||
if (sslcf->starttls) {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
c->read->handler = ngx_mail_starttls_handler;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ static ngx_str_t ngx_mail_pop3_auth_methods_names[] = {
|
|||
|
||||
static ngx_mail_protocol_t ngx_mail_pop3_protocol = {
|
||||
ngx_string("pop3"),
|
||||
ngx_string("\x04pop3"),
|
||||
{ 110, 995, 0, 0 },
|
||||
NGX_MAIL_POP3_PROTOCOL,
|
||||
|
||||
|
|
|
|||
|
|
@ -327,6 +327,10 @@ 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) {
|
||||
ngx_post_event(c->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
ngx_mail_proxy_handler(s->connection->write);
|
||||
|
||||
return;
|
||||
|
|
@ -482,6 +486,10 @@ 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) {
|
||||
ngx_post_event(c->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
ngx_mail_proxy_handler(s->connection->write);
|
||||
|
||||
return;
|
||||
|
|
@ -813,13 +821,12 @@ 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) {
|
||||
ngx_mail_proxy_handler(s->connection->write);
|
||||
|
||||
} else {
|
||||
ngx_mail_proxy_handler(c->write);
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
ngx_post_event(c->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
ngx_mail_proxy_handler(s->connection->write);
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ static ngx_str_t ngx_mail_smtp_auth_methods_names[] = {
|
|||
|
||||
static ngx_mail_protocol_t ngx_mail_smtp_protocol = {
|
||||
ngx_string("smtp"),
|
||||
ngx_string("\x04smtp"),
|
||||
{ 25, 465, 587, 0 },
|
||||
NGX_MAIL_SMTP_PROTOCOL,
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@
|
|||
#define NGX_DEFAULT_ECDH_CURVE "auto"
|
||||
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
static int ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
|
||||
const unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg);
|
||||
#endif
|
||||
|
||||
static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
|
||||
static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child);
|
||||
|
||||
|
|
@ -244,6 +250,54 @@ ngx_module_t ngx_mail_ssl_module = {
|
|||
static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL");
|
||||
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
|
||||
static int
|
||||
ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
|
||||
unsigned char *outlen, const unsigned char *in, unsigned int inlen,
|
||||
void *arg)
|
||||
{
|
||||
unsigned int srvlen;
|
||||
unsigned char *srv;
|
||||
ngx_connection_t *c;
|
||||
ngx_mail_session_t *s;
|
||||
ngx_mail_core_srv_conf_t *cscf;
|
||||
#if (NGX_DEBUG)
|
||||
unsigned int i;
|
||||
#endif
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
s = c->data;
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
for (i = 0; i < inlen; i += in[i] + 1) {
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"SSL ALPN supported by client: %*s",
|
||||
(size_t) in[i], &in[i + 1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
|
||||
|
||||
srv = cscf->protocol->alpn.data;
|
||||
srvlen = cscf->protocol->alpn.len;
|
||||
|
||||
if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
|
||||
in, inlen)
|
||||
!= OPENSSL_NPN_NEGOTIATED)
|
||||
{
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"SSL ALPN selected: %*s", (size_t) *outlen, *out);
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void *
|
||||
ngx_mail_ssl_create_conf(ngx_conf_t *cf)
|
||||
{
|
||||
|
|
@ -394,6 +448,17 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
cln->handler = ngx_ssl_cleanup_ctx;
|
||||
cln->data = &conf->ssl;
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_mail_ssl_alpn_select, NULL);
|
||||
#endif
|
||||
|
||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||
conf->prefer_server_ciphers)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
|
||||
conf->certificate_keys, conf->passwords)
|
||||
!= NGX_OK)
|
||||
|
|
@ -430,13 +495,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||
conf->prefer_server_ciphers)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,39 @@ typedef volatile ngx_atomic_uint_t ngx_atomic_t;
|
|||
#define ngx_cpu_pause()
|
||||
|
||||
|
||||
#elif (NGX_HAVE_GCC_ATOMIC)
|
||||
|
||||
/* GCC 4.1 builtin atomic operations */
|
||||
|
||||
#define NGX_HAVE_ATOMIC_OPS 1
|
||||
|
||||
typedef long ngx_atomic_int_t;
|
||||
typedef unsigned long ngx_atomic_uint_t;
|
||||
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1)
|
||||
#else
|
||||
#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1)
|
||||
#endif
|
||||
|
||||
typedef volatile ngx_atomic_uint_t ngx_atomic_t;
|
||||
|
||||
|
||||
#define ngx_atomic_cmp_set(lock, old, set) \
|
||||
__sync_bool_compare_and_swap(lock, old, set)
|
||||
|
||||
#define ngx_atomic_fetch_add(value, add) \
|
||||
__sync_fetch_and_add(value, add)
|
||||
|
||||
#define ngx_memory_barrier() __sync_synchronize()
|
||||
|
||||
#if ( __i386__ || __i386 || __amd64__ || __amd64 )
|
||||
#define ngx_cpu_pause() __asm__ ("pause")
|
||||
#else
|
||||
#define ngx_cpu_pause()
|
||||
#endif
|
||||
|
||||
|
||||
#elif (NGX_DARWIN_ATOMIC)
|
||||
|
||||
/*
|
||||
|
|
@ -88,39 +121,6 @@ typedef uint32_t ngx_atomic_uint_t;
|
|||
typedef volatile ngx_atomic_uint_t ngx_atomic_t;
|
||||
|
||||
|
||||
#elif (NGX_HAVE_GCC_ATOMIC)
|
||||
|
||||
/* GCC 4.1 builtin atomic operations */
|
||||
|
||||
#define NGX_HAVE_ATOMIC_OPS 1
|
||||
|
||||
typedef long ngx_atomic_int_t;
|
||||
typedef unsigned long ngx_atomic_uint_t;
|
||||
|
||||
#if (NGX_PTR_SIZE == 8)
|
||||
#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1)
|
||||
#else
|
||||
#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1)
|
||||
#endif
|
||||
|
||||
typedef volatile ngx_atomic_uint_t ngx_atomic_t;
|
||||
|
||||
|
||||
#define ngx_atomic_cmp_set(lock, old, set) \
|
||||
__sync_bool_compare_and_swap(lock, old, set)
|
||||
|
||||
#define ngx_atomic_fetch_add(value, add) \
|
||||
__sync_fetch_and_add(value, add)
|
||||
|
||||
#define ngx_memory_barrier() __sync_synchronize()
|
||||
|
||||
#if ( __i386__ || __i386 || __amd64__ || __amd64 )
|
||||
#define ngx_cpu_pause() __asm__ ("pause")
|
||||
#else
|
||||
#define ngx_cpu_pause()
|
||||
#endif
|
||||
|
||||
|
||||
#elif ( __i386__ || __i386 )
|
||||
|
||||
typedef int32_t ngx_atomic_int_t;
|
||||
|
|
|
|||
|
|
@ -32,23 +32,22 @@
|
|||
ngx_chain_t *
|
||||
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
{
|
||||
int rc, flags;
|
||||
off_t send, prev_send, sent;
|
||||
size_t file_size;
|
||||
ssize_t n;
|
||||
ngx_uint_t eintr, eagain;
|
||||
ngx_err_t err;
|
||||
ngx_buf_t *file;
|
||||
ngx_event_t *wev;
|
||||
ngx_chain_t *cl;
|
||||
ngx_iovec_t header, trailer;
|
||||
struct sf_hdtr hdtr;
|
||||
struct iovec headers[NGX_IOVS_PREALLOCATE];
|
||||
struct iovec trailers[NGX_IOVS_PREALLOCATE];
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
ngx_uint_t ebusy;
|
||||
ngx_event_aio_t *aio;
|
||||
int rc, flags;
|
||||
off_t send, prev_send, sent;
|
||||
size_t file_size;
|
||||
ssize_t n;
|
||||
ngx_err_t err;
|
||||
ngx_buf_t *file;
|
||||
ngx_uint_t eintr, eagain;
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
ngx_uint_t ebusy;
|
||||
#endif
|
||||
ngx_event_t *wev;
|
||||
ngx_chain_t *cl;
|
||||
ngx_iovec_t header, trailer;
|
||||
struct sf_hdtr hdtr;
|
||||
struct iovec headers[NGX_IOVS_PREALLOCATE];
|
||||
struct iovec trailers[NGX_IOVS_PREALLOCATE];
|
||||
|
||||
wev = c->write;
|
||||
|
||||
|
|
@ -77,11 +76,6 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
eagain = 0;
|
||||
flags = 0;
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE && NGX_SUPPRESS_WARN)
|
||||
aio = NULL;
|
||||
file = NULL;
|
||||
#endif
|
||||
|
||||
header.iovs = headers;
|
||||
header.nalloc = NGX_IOVS_PREALLOCATE;
|
||||
|
||||
|
|
@ -90,7 +84,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
|
||||
for ( ;; ) {
|
||||
eintr = 0;
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
ebusy = 0;
|
||||
#endif
|
||||
prev_send = send;
|
||||
|
|
@ -179,9 +173,14 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
|
||||
sent = 0;
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
aio = file->file->aio;
|
||||
flags = (aio && aio->preload_handler) ? SF_NODISKIO : 0;
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
|
||||
flags = (c->busy_count <= 2) ? SF_NODISKIO : 0;
|
||||
|
||||
if (file->file->directio) {
|
||||
flags |= SF_NOCACHE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
rc = sendfile(file->file->fd, c->fd, file->file_pos,
|
||||
|
|
@ -199,7 +198,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
eintr = 1;
|
||||
break;
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
case NGX_EBUSY:
|
||||
ebusy = 1;
|
||||
break;
|
||||
|
|
@ -252,54 +251,30 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
|
||||
in = ngx_chain_update_sent(in, sent);
|
||||
|
||||
#if (NGX_HAVE_AIO_SENDFILE)
|
||||
#if (NGX_HAVE_SENDFILE_NODISKIO)
|
||||
|
||||
if (ebusy) {
|
||||
if (aio->event.active) {
|
||||
/*
|
||||
* tolerate duplicate calls; they can happen due to subrequests
|
||||
* or multiple calls of the next body filter from a filter
|
||||
*/
|
||||
|
||||
if (sent) {
|
||||
c->busy_count = 0;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
if (sent == 0) {
|
||||
c->busy_count++;
|
||||
|
||||
if (c->busy_count > 2) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"sendfile(%V) returned busy again",
|
||||
&file->file->name);
|
||||
|
||||
c->busy_count = 0;
|
||||
aio->preload_handler = NULL;
|
||||
|
||||
send = prev_send;
|
||||
continue;
|
||||
}
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"sendfile() busy, count:%d", c->busy_count);
|
||||
|
||||
} else {
|
||||
c->busy_count = 0;
|
||||
}
|
||||
|
||||
n = aio->preload_handler(file);
|
||||
|
||||
if (n > 0) {
|
||||
send = prev_send + sent;
|
||||
continue;
|
||||
if (wev->posted) {
|
||||
ngx_delete_posted_event(wev);
|
||||
}
|
||||
|
||||
ngx_post_event(wev, &ngx_posted_next_events);
|
||||
|
||||
wev->ready = 0;
|
||||
return in;
|
||||
}
|
||||
|
||||
if (flags == SF_NODISKIO) {
|
||||
c->busy_count = 0;
|
||||
}
|
||||
c->busy_count = 0;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log);
|
|||
* On Linux up to 2.6.16 sendfile() does not allow to pass the count parameter
|
||||
* more than 2G-1 bytes even on 64-bit platforms: it returns EINVAL,
|
||||
* so we limit it to 2G-1 bytes.
|
||||
*
|
||||
* On Linux 2.6.16 and later, sendfile() silently limits the count parameter
|
||||
* to 2G minus the page size, even on 64-bit platforms.
|
||||
*/
|
||||
|
||||
#define NGX_SENDFILE_MAXSIZE 2147483647L
|
||||
|
|
@ -216,7 +219,6 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||
*/
|
||||
|
||||
send = prev_send + sent;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (send >= limit || in == NULL) {
|
||||
|
|
@ -377,15 +379,6 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size)
|
|||
return ctx->sent;
|
||||
}
|
||||
|
||||
if (task->event.active && ctx->file == file) {
|
||||
/*
|
||||
* tolerate duplicate calls; they can happen due to subrequests
|
||||
* or multiple calls of the next body filter from a filter
|
||||
*/
|
||||
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
ctx->file = file;
|
||||
ctx->socket = c->fd;
|
||||
ctx->size = size;
|
||||
|
|
|
|||
|
|
@ -398,6 +398,8 @@ ngx_pass_open_channel(ngx_cycle_t *cycle)
|
|||
ngx_int_t i;
|
||||
ngx_channel_t ch;
|
||||
|
||||
ngx_memzero(&ch, sizeof(ngx_channel_t));
|
||||
|
||||
ch.command = NGX_CMD_OPEN_CHANNEL;
|
||||
ch.pid = ngx_processes[ngx_process_slot].pid;
|
||||
ch.slot = ngx_process_slot;
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
|
|||
iov->iov_len += n;
|
||||
|
||||
} else {
|
||||
if (vec.nelts >= IOV_MAX) {
|
||||
if (vec.nelts == vec.nalloc) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -510,6 +510,10 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
|
|||
ls->ipv6only = addr[i].opt.ipv6only;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
ls->fastopen = addr[i].opt.fastopen;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
ls->reuseport = addr[i].opt.reuseport;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ typedef struct {
|
|||
int backlog;
|
||||
int rcvbuf;
|
||||
int sndbuf;
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
int fastopen;
|
||||
#endif
|
||||
int type;
|
||||
} ngx_stream_listen_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -615,6 +615,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
ls->type = SOCK_STREAM;
|
||||
ls->ctx = cf->ctx;
|
||||
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
ls->fastopen = -1;
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6)
|
||||
ls->ipv6only = 1;
|
||||
#endif
|
||||
|
|
@ -635,6 +639,21 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
continue;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) {
|
||||
ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9);
|
||||
ls->bind = 1;
|
||||
|
||||
if (ls->fastopen == NGX_ERROR) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid fastopen \"%V\"", &value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
|
||||
ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
|
||||
ls->bind = 1;
|
||||
|
|
@ -859,6 +878,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
if (ls->proxy_protocol) {
|
||||
return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
if (ls->fastopen != -1) {
|
||||
return "\"fastopen\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
als = cmcf->listen.elts;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ typedef struct {
|
|||
ngx_uint_t next_upstream_tries;
|
||||
ngx_flag_t next_upstream;
|
||||
ngx_flag_t proxy_protocol;
|
||||
ngx_flag_t half_close;
|
||||
ngx_stream_upstream_local_t *local;
|
||||
ngx_flag_t socket_keepalive;
|
||||
|
||||
|
|
@ -46,8 +47,8 @@ typedef struct {
|
|||
ngx_uint_t ssl_verify_depth;
|
||||
ngx_str_t ssl_trusted_certificate;
|
||||
ngx_str_t ssl_crl;
|
||||
ngx_str_t ssl_certificate;
|
||||
ngx_str_t ssl_certificate_key;
|
||||
ngx_stream_complex_value_t *ssl_certificate;
|
||||
ngx_stream_complex_value_t *ssl_certificate_key;
|
||||
ngx_array_t *ssl_passwords;
|
||||
ngx_array_t *ssl_conf_commands;
|
||||
|
||||
|
|
@ -101,6 +102,7 @@ static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s);
|
|||
static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc);
|
||||
static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c);
|
||||
static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s);
|
||||
static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s);
|
||||
static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf,
|
||||
ngx_stream_proxy_srv_conf_t *pscf);
|
||||
|
||||
|
|
@ -244,6 +246,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
|
|||
offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_half_close"),
|
||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
NGX_STREAM_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_stream_proxy_srv_conf_t, half_close),
|
||||
NULL },
|
||||
|
||||
#if (NGX_STREAM_SSL)
|
||||
|
||||
{ ngx_string("proxy_ssl"),
|
||||
|
|
@ -318,14 +327,14 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
|
|||
|
||||
{ ngx_string("proxy_ssl_certificate"),
|
||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_stream_set_complex_value_zero_slot,
|
||||
NGX_STREAM_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_ssl_certificate_key"),
|
||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
ngx_stream_set_complex_value_zero_slot,
|
||||
NGX_STREAM_SRV_CONF_OFFSET,
|
||||
offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key),
|
||||
NULL },
|
||||
|
|
@ -1060,6 +1069,15 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
|
|||
}
|
||||
}
|
||||
|
||||
if (pscf->ssl_certificate && (pscf->ssl_certificate->lengths
|
||||
|| pscf->ssl_certificate_key->lengths))
|
||||
{
|
||||
if (ngx_stream_proxy_ssl_certificate(s) != NGX_OK) {
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pscf->ssl_session_reuse) {
|
||||
pc->ssl->save_session = ngx_stream_proxy_ssl_save_session;
|
||||
|
||||
|
|
@ -1247,6 +1265,50 @@ done:
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s)
|
||||
{
|
||||
ngx_str_t cert, key;
|
||||
ngx_connection_t *c;
|
||||
ngx_stream_proxy_srv_conf_t *pscf;
|
||||
|
||||
c = s->upstream->peer.connection;
|
||||
|
||||
pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
|
||||
|
||||
if (ngx_stream_complex_value(s, pscf->ssl_certificate, &cert)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||
"stream upstream ssl cert: \"%s\"", cert.data);
|
||||
|
||||
if (*cert.data == '\0') {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ngx_stream_complex_value(s, pscf->ssl_certificate_key, &key)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||
"stream upstream ssl key: \"%s\"", key.data);
|
||||
|
||||
if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key,
|
||||
pscf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1701,6 +1763,24 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
|
|||
}
|
||||
|
||||
if (dst) {
|
||||
|
||||
if (dst->type == SOCK_STREAM && pscf->half_close
|
||||
&& src->read->eof && !u->half_closed && !dst->buffered)
|
||||
{
|
||||
if (ngx_shutdown_socket(dst->fd, NGX_WRITE_SHUTDOWN) == -1) {
|
||||
ngx_connection_error(c, ngx_socket_errno,
|
||||
ngx_shutdown_socket_n " failed");
|
||||
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
u->half_closed = 1;
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
|
||||
"stream proxy %s socket shutdown",
|
||||
from_upstream ? "client" : "upstream");
|
||||
}
|
||||
|
||||
if (ngx_handle_write_event(dst->write, 0) != NGX_OK) {
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
|
|
@ -1779,6 +1859,13 @@ ngx_stream_proxy_test_finalize(ngx_stream_session_t *s,
|
|||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (pscf->half_close) {
|
||||
/* avoid closing live connections until both read ends get EOF */
|
||||
if (!(c->read->eof && pc->read->eof && !c->buffered && !pc->buffered)) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
}
|
||||
|
||||
handler = c->log->handler;
|
||||
c->log->handler = NULL;
|
||||
|
||||
|
|
@ -1977,14 +2064,9 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
|
|||
*
|
||||
* conf->ssl_protocols = 0;
|
||||
* conf->ssl_ciphers = { 0, NULL };
|
||||
* conf->ssl_name = NULL;
|
||||
* conf->ssl_trusted_certificate = { 0, NULL };
|
||||
* conf->ssl_crl = { 0, NULL };
|
||||
* conf->ssl_certificate = { 0, NULL };
|
||||
* conf->ssl_certificate_key = { 0, NULL };
|
||||
*
|
||||
* conf->upload_rate = NULL;
|
||||
* conf->download_rate = NULL;
|
||||
* conf->ssl = NULL;
|
||||
* conf->upstream = NULL;
|
||||
* conf->upstream_value = NULL;
|
||||
|
|
@ -1994,6 +2076,8 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
|
|||
conf->timeout = NGX_CONF_UNSET_MSEC;
|
||||
conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC;
|
||||
conf->buffer_size = NGX_CONF_UNSET_SIZE;
|
||||
conf->upload_rate = NGX_CONF_UNSET_PTR;
|
||||
conf->download_rate = NGX_CONF_UNSET_PTR;
|
||||
conf->requests = NGX_CONF_UNSET_UINT;
|
||||
conf->responses = NGX_CONF_UNSET_UINT;
|
||||
conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
|
||||
|
|
@ -2001,13 +2085,17 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
|
|||
conf->proxy_protocol = NGX_CONF_UNSET;
|
||||
conf->local = NGX_CONF_UNSET_PTR;
|
||||
conf->socket_keepalive = NGX_CONF_UNSET;
|
||||
conf->half_close = NGX_CONF_UNSET;
|
||||
|
||||
#if (NGX_STREAM_SSL)
|
||||
conf->ssl_enable = NGX_CONF_UNSET;
|
||||
conf->ssl_session_reuse = NGX_CONF_UNSET;
|
||||
conf->ssl_name = NGX_CONF_UNSET_PTR;
|
||||
conf->ssl_server_name = NGX_CONF_UNSET;
|
||||
conf->ssl_verify = NGX_CONF_UNSET;
|
||||
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
|
||||
conf->ssl_certificate = NGX_CONF_UNSET_PTR;
|
||||
conf->ssl_certificate_key = NGX_CONF_UNSET_PTR;
|
||||
conf->ssl_passwords = NGX_CONF_UNSET_PTR;
|
||||
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
|
||||
#endif
|
||||
|
|
@ -2034,13 +2122,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_size_value(conf->buffer_size,
|
||||
prev->buffer_size, 16384);
|
||||
|
||||
if (conf->upload_rate == NULL) {
|
||||
conf->upload_rate = prev->upload_rate;
|
||||
}
|
||||
ngx_conf_merge_ptr_value(conf->upload_rate, prev->upload_rate, NULL);
|
||||
|
||||
if (conf->download_rate == NULL) {
|
||||
conf->download_rate = prev->download_rate;
|
||||
}
|
||||
ngx_conf_merge_ptr_value(conf->download_rate, prev->download_rate, NULL);
|
||||
|
||||
ngx_conf_merge_uint_value(conf->requests,
|
||||
prev->requests, 0);
|
||||
|
|
@ -2060,6 +2144,8 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_value(conf->socket_keepalive,
|
||||
prev->socket_keepalive, 0);
|
||||
|
||||
ngx_conf_merge_value(conf->half_close, prev->half_close, 0);
|
||||
|
||||
#if (NGX_STREAM_SSL)
|
||||
|
||||
ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0);
|
||||
|
|
@ -2073,9 +2159,7 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT");
|
||||
|
||||
if (conf->ssl_name == NULL) {
|
||||
conf->ssl_name = prev->ssl_name;
|
||||
}
|
||||
ngx_conf_merge_ptr_value(conf->ssl_name, prev->ssl_name, NULL);
|
||||
|
||||
ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 0);
|
||||
|
||||
|
|
@ -2089,11 +2173,11 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate,
|
||||
prev->ssl_certificate, "");
|
||||
ngx_conf_merge_ptr_value(conf->ssl_certificate,
|
||||
prev->ssl_certificate, NULL);
|
||||
|
||||
ngx_conf_merge_str_value(conf->ssl_certificate_key,
|
||||
prev->ssl_certificate_key, "");
|
||||
ngx_conf_merge_ptr_value(conf->ssl_certificate_key,
|
||||
prev->ssl_certificate_key, NULL);
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
|
||||
|
||||
|
|
@ -2137,27 +2221,41 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf)
|
|||
cln->handler = ngx_ssl_cleanup_ctx;
|
||||
cln->data = pscf->ssl;
|
||||
|
||||
if (pscf->ssl_certificate.len) {
|
||||
|
||||
if (pscf->ssl_certificate_key.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"proxy_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"", &pscf->ssl_certificate);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate,
|
||||
&pscf->ssl_certificate_key, pscf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, pscf->ssl, &pscf->ssl_ciphers, 0) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (pscf->ssl_certificate) {
|
||||
|
||||
if (pscf->ssl_certificate_key == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"no \"proxy_ssl_certificate_key\" is defined "
|
||||
"for certificate \"%V\"",
|
||||
&pscf->ssl_certificate->value);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (pscf->ssl_certificate->lengths
|
||||
|| pscf->ssl_certificate_key->lengths)
|
||||
{
|
||||
pscf->ssl_passwords =
|
||||
ngx_ssl_preserve_passwords(cf, pscf->ssl_passwords);
|
||||
if (pscf->ssl_passwords == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (ngx_ssl_certificate(cf, pscf->ssl,
|
||||
&pscf->ssl_certificate->value,
|
||||
&pscf->ssl_certificate_key->value,
|
||||
pscf->ssl_passwords)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pscf->ssl_verify) {
|
||||
if (pscf->ssl_trusted_certificate.len == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
|
||||
cv = (ngx_stream_complex_value_t **) (p + cmd->offset);
|
||||
|
||||
if (*cv != NULL) {
|
||||
if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
|
|
@ -277,6 +277,44 @@ ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
char *p = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_stream_complex_value_t **cv;
|
||||
ngx_stream_compile_complex_value_t ccv;
|
||||
|
||||
cv = (ngx_stream_complex_value_t **) (p + cmd->offset);
|
||||
|
||||
if (*cv != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
*cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t));
|
||||
if (*cv == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
|
||||
|
||||
ccv.cf = cf;
|
||||
ccv.value = &value[1];
|
||||
ccv.complex_value = *cv;
|
||||
ccv.zero = 1;
|
||||
|
||||
if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ ngx_int_t ngx_stream_compile_complex_value(
|
|||
ngx_stream_compile_complex_value_t *ccv);
|
||||
char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
char *ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
char *ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,13 @@ static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl,
|
|||
ngx_connection_t *c);
|
||||
static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
|
||||
static int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad,
|
||||
void *arg);
|
||||
#endif
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
static int ngx_stream_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
|
||||
const unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg);
|
||||
#endif
|
||||
#ifdef SSL_R_CERT_CB_ERROR
|
||||
static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg);
|
||||
|
|
@ -45,6 +51,8 @@ static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
void *conf);
|
||||
static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post,
|
||||
void *data);
|
||||
|
|
@ -211,6 +219,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
|
|||
offsetof(ngx_stream_ssl_conf_t, conf_commands),
|
||||
&ngx_stream_ssl_conf_command_post },
|
||||
|
||||
{ ngx_string("ssl_alpn"),
|
||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
||||
ngx_stream_ssl_alpn,
|
||||
NGX_STREAM_SRV_CONF_OFFSET,
|
||||
0,
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
|
@ -254,6 +269,9 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = {
|
|||
{ ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_curve"), NULL, ngx_stream_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_curve, NGX_STREAM_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 },
|
||||
|
||||
|
|
@ -266,6 +284,9 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = {
|
|||
{ ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_alpn_protocol"), NULL, ngx_stream_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_alpn_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 },
|
||||
|
||||
{ ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable,
|
||||
(uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 },
|
||||
|
||||
|
|
@ -434,7 +455,7 @@ ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
|
|||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
|
||||
int
|
||||
static int
|
||||
ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||
{
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
|
|
@ -443,9 +464,49 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
|
||||
static int
|
||||
ngx_stream_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
|
||||
unsigned char *outlen, const unsigned char *in, unsigned int inlen,
|
||||
void *arg)
|
||||
{
|
||||
ngx_str_t *alpn;
|
||||
#if (NGX_DEBUG)
|
||||
unsigned int i;
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
|
||||
for (i = 0; i < inlen; i += in[i] + 1) {
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||
"SSL ALPN supported by client: %*s",
|
||||
(size_t) in[i], &in[i + 1]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
alpn = arg;
|
||||
|
||||
if (SSL_select_next_proto((unsigned char **) out, outlen, alpn->data,
|
||||
alpn->len, in, inlen)
|
||||
!= OPENSSL_NPN_NEGOTIATED)
|
||||
{
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||
"SSL ALPN selected: %*s", (size_t) *outlen, *out);
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SSL_R_CERT_CB_ERROR
|
||||
|
||||
int
|
||||
static int
|
||||
ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
|
||||
{
|
||||
ngx_str_t cert, key;
|
||||
|
|
@ -602,6 +663,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf)
|
|||
* scf->client_certificate = { 0, NULL };
|
||||
* scf->trusted_certificate = { 0, NULL };
|
||||
* scf->crl = { 0, NULL };
|
||||
* scf->alpn = { 0, NULL };
|
||||
* scf->ciphers = { 0, NULL };
|
||||
* scf->shm_zone = NULL;
|
||||
*/
|
||||
|
|
@ -660,6 +722,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_str_value(conf->trusted_certificate,
|
||||
prev->trusted_certificate, "");
|
||||
ngx_conf_merge_str_value(conf->crl, prev->crl, "");
|
||||
ngx_conf_merge_str_value(conf->alpn, prev->alpn, "");
|
||||
|
||||
ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
|
||||
NGX_DEFAULT_ECDH_CURVE);
|
||||
|
|
@ -720,6 +783,20 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_stream_ssl_servername);
|
||||
#endif
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
if (conf->alpn.len) {
|
||||
SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_stream_ssl_alpn_select,
|
||||
&conf->alpn);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||
conf->prefer_server_ciphers)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
|
@ -752,13 +829,6 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
}
|
||||
}
|
||||
|
||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||
conf->prefer_server_ciphers)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (conf->verify) {
|
||||
|
||||
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
||||
|
|
@ -1056,6 +1126,60 @@ invalid:
|
|||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
|
||||
ngx_stream_ssl_conf_t *scf = conf;
|
||||
|
||||
u_char *p;
|
||||
size_t len;
|
||||
ngx_str_t *value;
|
||||
ngx_uint_t i;
|
||||
|
||||
if (scf->alpn.len) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
len = 0;
|
||||
|
||||
for (i = 1; i < cf->args->nelts; i++) {
|
||||
|
||||
if (value[i].len > 255) {
|
||||
return "protocol too long";
|
||||
}
|
||||
|
||||
len += value[i].len + 1;
|
||||
}
|
||||
|
||||
scf->alpn.data = ngx_pnalloc(cf->pool, len);
|
||||
if (scf->alpn.data == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
p = scf->alpn.data;
|
||||
|
||||
for (i = 1; i < cf->args->nelts; i++) {
|
||||
*p++ = value[i].len;
|
||||
p = ngx_cpymem(p, value[i].data, value[i].len);
|
||||
}
|
||||
|
||||
scf->alpn.len = len;
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"the \"ssl_alpn\" directive requires OpenSSL "
|
||||
"with ALPN support");
|
||||
return NGX_CONF_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ typedef struct {
|
|||
ngx_str_t client_certificate;
|
||||
ngx_str_t trusted_certificate;
|
||||
ngx_str_t crl;
|
||||
ngx_str_t alpn;
|
||||
|
||||
ngx_str_t ciphers;
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ typedef struct {
|
|||
ngx_stream_upstream_state_t *state;
|
||||
unsigned connected:1;
|
||||
unsigned proxy_protocol:1;
|
||||
unsigned half_closed:1;
|
||||
} ngx_stream_upstream_t;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue