mirror of
https://github.com/nginx/nginx.git
synced 2026-04-21 22:27:02 -04:00
Merge branch 'nginx:master' into feature/PROXY_V2_SUPPORT
This commit is contained in:
commit
8b09ca4613
47 changed files with 2603 additions and 162 deletions
14
auto/modules
14
auto/modules
|
|
@ -950,6 +950,20 @@ if [ $HTTP = YES ]; then
|
|||
. auto/module
|
||||
fi
|
||||
|
||||
if [ $HTTP_UPSTREAM_STICKY = YES ]; then
|
||||
have=NGX_HTTP_UPSTREAM_STICKY . auto/have
|
||||
have=NGX_HTTP_UPSTREAM_SID . auto/have
|
||||
|
||||
ngx_module_name=ngx_http_upstream_sticky_module
|
||||
ngx_module_incs=
|
||||
ngx_module_deps=
|
||||
ngx_module_srcs=src/http/modules/ngx_http_upstream_sticky_module.c
|
||||
ngx_module_libs=
|
||||
ngx_module_link=$HTTP_UPSTREAM_STICKY
|
||||
|
||||
. auto/module
|
||||
fi
|
||||
|
||||
if [ $HTTP_STUB_STATUS = YES ]; then
|
||||
have=NGX_STAT_STUB . auto/have
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ HTTP_UPSTREAM_LEAST_CONN=YES
|
|||
HTTP_UPSTREAM_RANDOM=YES
|
||||
HTTP_UPSTREAM_KEEPALIVE=YES
|
||||
HTTP_UPSTREAM_ZONE=YES
|
||||
HTTP_UPSTREAM_STICKY=YES
|
||||
|
||||
# STUB
|
||||
HTTP_STUB_STATUS=NO
|
||||
|
|
@ -292,6 +293,7 @@ $0: warning: the \"--with-ipv6\" option is deprecated"
|
|||
HTTP_UPSTREAM_RANDOM=NO ;;
|
||||
--without-http_upstream_keepalive_module) HTTP_UPSTREAM_KEEPALIVE=NO ;;
|
||||
--without-http_upstream_zone_module) HTTP_UPSTREAM_ZONE=NO ;;
|
||||
--without-http_upstream_sticky) HTTP_UPSTREAM_STICKY=NO ;;
|
||||
|
||||
--with-http_perl_module) HTTP_PERL=YES ;;
|
||||
--with-http_perl_module=dynamic) HTTP_PERL=DYNAMIC ;;
|
||||
|
|
@ -516,6 +518,7 @@ cat << END
|
|||
disable ngx_http_upstream_keepalive_module
|
||||
--without-http_upstream_zone_module
|
||||
disable ngx_http_upstream_zone_module
|
||||
--without-http_upstream_sticky disable sticky upstream modules
|
||||
|
||||
--with-http_perl_module enable ngx_http_perl_module
|
||||
--with-http_perl_module=dynamic enable dynamic ngx_http_perl_module
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ syn match ngxListenComment '#.*$'
|
|||
\ contained
|
||||
\ nextgroup=@ngxListenParams skipwhite skipempty
|
||||
syn keyword ngxListenOptions contained
|
||||
\ default_server ssl quic proxy_protocol
|
||||
\ default_server ssl quic proxy_protocol multipath
|
||||
\ setfib fastopen backlog rcvbuf sndbuf accept_filter deferred bind
|
||||
\ ipv6only reuseport so_keepalive
|
||||
\ nextgroup=@ngxListenParams skipwhite skipempty
|
||||
|
|
|
|||
|
|
@ -5,6 +5,255 @@
|
|||
<change_log title="nginx">
|
||||
|
||||
|
||||
<changes ver="1.29.7" date="2026-03-24">
|
||||
|
||||
<change type="security">
|
||||
<para lang="ru">
|
||||
при обработке COPY- или MOVE-запроса в location'е с включённым
|
||||
alias могло произойти переполнение буфера, что позволяло
|
||||
атакующему модифицировать исходный или целевой путь за пределы
|
||||
document root (CVE-2026-27654).<br/>
|
||||
Спасибо Calif.io при содействии Claude и Anthropic Research.
|
||||
</para>
|
||||
<para lang="en">
|
||||
a buffer overflow might occur while handling a COPY or MOVE
|
||||
request in a location with "alias", allowing an attacker
|
||||
to modify the source or destination path outside of the
|
||||
document root (CVE-2026-27654).<br/>
|
||||
Thanks to Calif.io in collaboration with Claude and Anthropic Research.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="security">
|
||||
<para lang="ru">
|
||||
обработка специально созданного mp4-файла модулем ngx_http_mp4_module
|
||||
на 32-битных платформах могла приводить к падению рабочего процесса,
|
||||
а также потенциально могла иметь другие последствия (CVE-2026-27784).<br/>
|
||||
Спасибо Prabhav Srinath (sprabhav7).
|
||||
</para>
|
||||
<para lang="en">
|
||||
processing of a specially crafted mp4 file by the ngx_http_mp4_module
|
||||
on 32-bit platforms might cause a worker process crash,
|
||||
or might have potential other impact (CVE-2026-27784).<br/>
|
||||
Thanks to Prabhav Srinath (sprabhav7).
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="security">
|
||||
<para lang="ru">
|
||||
обработка специально созданного mp4-файла модулем ngx_http_mp4_module
|
||||
могла приводить к падению рабочего процесса, а также потенциально
|
||||
могла иметь другие последствия (CVE-2026-32647).<br/>
|
||||
Спасибо Xint Code и Pavel Kohout (Aisle Research).
|
||||
</para>
|
||||
<para lang="en">
|
||||
processing of a specially crafted mp4 file by the ngx_http_mp4_module
|
||||
might cause a worker process crash, or might have potential
|
||||
other impact (CVE-2026-32647).<br/>
|
||||
Thanks to Xint Code and Pavel Kohout (Aisle Research).
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="security">
|
||||
<para lang="ru">
|
||||
если использовался метод аутентификации CRAM-MD5 или APOP, то
|
||||
в рабочем процессе мог произойти segmentation fault,
|
||||
если были разрешены повторные попытки аутентификации (CVE-2026-27651).<br/>
|
||||
Спасибо Arkadi Vainbrand.
|
||||
</para>
|
||||
<para lang="en">
|
||||
a segmentation fault might occur in a worker process
|
||||
if the CRAM-MD5 or APOP authentication methods were used
|
||||
and authentication retry was enabled (CVE-2026-27651).<br/>
|
||||
Thanks to Arkadi Vainbrand.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="security">
|
||||
<para lang="ru">
|
||||
атакующий мог использовать записи PTR DNS чтобы вставить данные
|
||||
в auth_http-запросы, а также в команду XCLIENT в SMTP-соединении
|
||||
к бекенду (CVE-2026-28753).<br/>
|
||||
Спасибо Asim Viladi Oglu Manizada, Colin Warren,
|
||||
Xiao Liu (Yunnan University), Yuan Tan (UC Riverside)
|
||||
и Bird Liu (Lanzhou University).
|
||||
</para>
|
||||
<para lang="en">
|
||||
an attacker might use PTR DNS records to inject data in
|
||||
auth_http requests, as well as in the XCLIENT command in
|
||||
the backend SMTP connection (CVE-2026-28753).<br/>
|
||||
Thanks to Asim Viladi Oglu Manizada, Colin Warren,
|
||||
Xiao Liu (Yunnan University), Yuan Tan (UC Riverside),
|
||||
and Bird Liu (Lanzhou University).
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="security">
|
||||
<para lang="ru">
|
||||
SSL handshake мог завершиться успешно при том, что OCSP
|
||||
отклонил клиентский сертификат в модуле stream (CVE-2026-28755).<br/>
|
||||
Спасибо Mufeed VH из Winfunc Research.
|
||||
</para>
|
||||
<para lang="en">
|
||||
SSL handshake might succeed despite OCSP rejecting a client
|
||||
certificate in the stream module (CVE-2026-28755).<br/>
|
||||
Thanks to Mufeed VH of Winfunc Research.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
параметр multipath директивы listen.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "multipath" parameter of the "listen" directive.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
параметр local директивы keepalive в блоке upstream.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "local" parameter of the "keepalive" directive
|
||||
in the "upstream" block.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="change">
|
||||
<para lang="ru">
|
||||
теперь директива keepalive в блоке upstream включена по умолчанию.
|
||||
</para>
|
||||
<para lang="en">
|
||||
now the "keepalive" directive in the "upstream" block is
|
||||
enabled by default.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="change">
|
||||
<para lang="ru">
|
||||
теперь модуль ngx_http_proxy_module поддерживает keepalive по умолчанию;
|
||||
значение proxy_http_version по умолчанию равно "1.1";
|
||||
proxy заголовок "Connection" по умолчанию больше не посылается.
|
||||
</para>
|
||||
<para lang="en">
|
||||
now ngx_http_proxy_module supports keepalive by default;
|
||||
the default value for "proxy_http_version" is "1.1";
|
||||
the "Connection" proxy header is not sent by default anymore.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
некорректный HTTP/2-запрос мог быть отправлен после переключения
|
||||
на следующий бэкенд при использовании буферизованного тела в модуле
|
||||
ngx_http_grpc_module.
|
||||
</para>
|
||||
<para lang="en">
|
||||
an invalid HTTP/2 request might be sent after switching to the next
|
||||
upstream if buffered body was used in the ngx_http_grpc_module.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
</changes>
|
||||
|
||||
|
||||
<changes ver="1.29.6" date="2026-03-10">
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
режим привязки сессий;
|
||||
директива sticky в блоке upstream модуля http;
|
||||
директива server поддерживает параметры route и drain.
|
||||
</para>
|
||||
<para lang="en">
|
||||
session affinity support;
|
||||
the "sticky" directive in the "upstream" block of the "http" module;
|
||||
the "server" directive supports the "route" and "drain" parameters.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="change">
|
||||
<para lang="ru">
|
||||
теперь nginx ограничивает размер и частоту отправки пакетов
|
||||
QUIC stateless reset.
|
||||
</para>
|
||||
<para lang="en">
|
||||
now nginx limits the size and rate of QUIC stateless reset packets.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
получение QUIC-пакета в другом рабочем процессе
|
||||
могло приводить к разрыву соединения.
|
||||
</para>
|
||||
<para lang="en">
|
||||
receiving a QUIC packet by a wrong worker process
|
||||
could cause the connection to terminate.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
при отправке закэшированного ответа HTTP/2
|
||||
в логах могли появляться сообщения
|
||||
"[crit] cache file ... contains invalid header".
|
||||
</para>
|
||||
<para lang="en">
|
||||
"[crit] cache file ... contains invalid header"
|
||||
messages might appear in logs
|
||||
when sending a cached HTTP/2 response.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
проксирование на scgi-бэкенды могло не работать при использовании
|
||||
chunked transfer encoding и директивы scgi_request_buffering.<br/>
|
||||
Спасибо Mufeed VH.
|
||||
</para>
|
||||
<para lang="en">
|
||||
proxying to scgi backends might not work when using
|
||||
chunked transfer encoding and the "scgi_request_buffering" directive.<br/>
|
||||
Thanks to Mufeed VH.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
в модуле ngx_http_mp4_module.<br/>
|
||||
Спасибо Andrew Lacambra.
|
||||
</para>
|
||||
<para lang="en">
|
||||
in the ngx_http_mp4_module.<br/>
|
||||
Thanks to Andrew Lacambra.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
nginx считал запятую разделителем в строке "Cookie"
|
||||
заголовка запроса при вычислении переменных "$cookie_...".
|
||||
</para>
|
||||
<para lang="en">
|
||||
nginx treated a comma as separator in the "Cookie"
|
||||
request header line when evaluating "$cookie_..." variables.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
в парсинге литеральных аргументов IMAP команд.
|
||||
</para>
|
||||
<para lang="en">
|
||||
in IMAP command literal argument parsing.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
</changes>
|
||||
|
||||
|
||||
<changes ver="1.29.5" date="2026-02-04">
|
||||
|
||||
<change type="security">
|
||||
|
|
@ -304,7 +553,7 @@ Thanks to Igor Morgenstern of Aisle Research.
|
|||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
в кешировании SSL-сертификатов во время переконфигурации.
|
||||
в кэшировании SSL-сертификатов во время переконфигурации.
|
||||
</para>
|
||||
<para lang="en">
|
||||
in SSL certificate caching during reconfiguration.
|
||||
|
|
@ -520,7 +769,7 @@ CUBIC congestion control in QUIC connections.
|
|||
|
||||
<change type="change">
|
||||
<para lang="ru">
|
||||
ограничение на максимальный размер кешируемых в разделяемой памяти
|
||||
ограничение на максимальный размер кэшируемых в разделяемой памяти
|
||||
SSL-сессий поднято до 8192.
|
||||
</para>
|
||||
<para lang="en">
|
||||
|
|
@ -779,7 +1028,7 @@ in the "proxy_store" directive.
|
|||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
SSL-сертификаты, секретные ключи и списки CRL теперь кешируются
|
||||
SSL-сертификаты, секретные ключи и списки CRL теперь кэшируются
|
||||
на старте или во время переконфигурации.
|
||||
</para>
|
||||
<para lang="en">
|
||||
|
|
@ -989,7 +1238,7 @@ directive in the stream module.
|
|||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
определение размера строки кеша процессора для некоторых архитектур.<br/>
|
||||
определение размера строки кэша процессора для некоторых архитектур.<br/>
|
||||
Спасибо Piotr Sikora.
|
||||
</para>
|
||||
<para lang="en">
|
||||
|
|
@ -16086,7 +16335,7 @@ listen unix domain socket had limited access rights.
|
|||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
закэшированные ответы ответов HTTP/0.9 неправильно обрабатывались.
|
||||
закэшированные ответы HTTP/0.9 неправильно обрабатывались.
|
||||
</para>
|
||||
<para lang="en">
|
||||
cached HTTP/0.9 responses were handled incorrectly.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ TEMP = tmp
|
|||
CC = cl
|
||||
OBJS = objs.msvc8
|
||||
OPENSSL = openssl-3.5.5
|
||||
ZLIB = zlib-1.3.1
|
||||
ZLIB = zlib-1.3.2
|
||||
PCRE = pcre2-10.47
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
#define _NGINX_H_INCLUDED_
|
||||
|
||||
|
||||
#define nginx_version 1029006
|
||||
#define NGINX_VERSION "1.29.6"
|
||||
#define nginx_version 1029007
|
||||
#define NGINX_VERSION "1.29.7"
|
||||
#define NGINX_VER "nginx/" NGINX_VERSION
|
||||
|
||||
#ifdef NGX_BUILD
|
||||
|
|
|
|||
|
|
@ -315,6 +315,25 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
|
|||
continue;
|
||||
}
|
||||
|
||||
#ifdef SO_PROTOCOL
|
||||
|
||||
olen = sizeof(int);
|
||||
|
||||
if (getsockopt(ls[i].fd, SOL_SOCKET, SO_PROTOCOL,
|
||||
(void *) &ls[i].protocol, &olen)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
|
||||
"getsockopt(SO_PROTOCOL) %V failed, ignored",
|
||||
&ls[i].addr_text);
|
||||
ls[i].protocol = 0;
|
||||
|
||||
} else if (ls[i].protocol == IPPROTO_TCP) {
|
||||
ls[i].protocol = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||
|
||||
olen = sizeof(int);
|
||||
|
|
@ -436,12 +455,16 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
|
||||
if (ls[i].add_reuseport) {
|
||||
if (ls[i].add_reuseport || ls[i].change_protocol) {
|
||||
|
||||
/*
|
||||
* to allow transition from a socket without SO_REUSEPORT
|
||||
* to multiple sockets with SO_REUSEPORT, we have to set
|
||||
* SO_REUSEPORT on the old socket before opening new ones
|
||||
*
|
||||
* to allow transition between different socket protocols
|
||||
* (e.g. IPPROTO_MPTCP), SO_REUSEPORT is set on both old
|
||||
* and new sockets
|
||||
*/
|
||||
|
||||
int reuseport = 1;
|
||||
|
|
@ -474,7 +497,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (ls[i].fd != (ngx_socket_t) -1) {
|
||||
if (ls[i].fd != (ngx_socket_t) -1 && !ls[i].change_protocol) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -487,7 +510,8 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
continue;
|
||||
}
|
||||
|
||||
s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
|
||||
s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type,
|
||||
ls[i].protocol);
|
||||
|
||||
if (s == (ngx_socket_t) -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||
|
|
@ -517,7 +541,9 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
|
||||
#if (NGX_HAVE_REUSEPORT)
|
||||
|
||||
if (ls[i].reuseport && !ngx_test_config) {
|
||||
if ((ls[i].reuseport || ls[i].change_protocol)
|
||||
&& !ngx_test_config)
|
||||
{
|
||||
int reuseport;
|
||||
|
||||
reuseport = 1;
|
||||
|
|
@ -651,6 +677,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
|
||||
if (ls[i].type != SOCK_STREAM) {
|
||||
ls[i].fd = s;
|
||||
ls[i].open = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -689,6 +716,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
|
|||
ls[i].listen = 1;
|
||||
|
||||
ls[i].fd = s;
|
||||
ls[i].open = 1;
|
||||
}
|
||||
|
||||
if (!failed) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ struct ngx_listening_s {
|
|||
ngx_str_t addr_text;
|
||||
|
||||
int type;
|
||||
int protocol;
|
||||
|
||||
int backlog;
|
||||
int rcvbuf;
|
||||
|
|
@ -76,6 +77,8 @@ struct ngx_listening_s {
|
|||
unsigned keepalive:2;
|
||||
unsigned quic:1;
|
||||
|
||||
unsigned change_protocol:1;
|
||||
|
||||
unsigned deferred_accept:1;
|
||||
unsigned delete_deferred:1;
|
||||
unsigned add_deferred:1;
|
||||
|
|
|
|||
|
|
@ -535,9 +535,15 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
|
|||
== NGX_OK)
|
||||
{
|
||||
nls[n].fd = ls[i].fd;
|
||||
nls[n].inherited = ls[i].inherited;
|
||||
nls[n].previous = &ls[i];
|
||||
ls[i].remain = 1;
|
||||
|
||||
if (ls[i].protocol != nls[n].protocol) {
|
||||
nls[n].change_protocol = 1;
|
||||
|
||||
} else {
|
||||
nls[n].inherited = ls[i].inherited;
|
||||
ls[i].remain = 1;
|
||||
}
|
||||
|
||||
if (ls[i].backlog != nls[n].backlog) {
|
||||
nls[n].listen = 1;
|
||||
|
|
@ -590,7 +596,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
|
|||
}
|
||||
|
||||
if (nls[n].fd == (ngx_socket_t) -1) {
|
||||
nls[n].open = 1;
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||
if (nls[n].accept_filter) {
|
||||
nls[n].add_deferred = 1;
|
||||
|
|
@ -605,20 +610,21 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
|
|||
}
|
||||
|
||||
} else {
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT)
|
||||
ls = cycle->listening.elts;
|
||||
for (i = 0; i < cycle->listening.nelts; i++) {
|
||||
ls[i].open = 1;
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||
#ifdef SO_ACCEPTFILTER
|
||||
if (ls[i].accept_filter) {
|
||||
ls[i].add_deferred = 1;
|
||||
}
|
||||
#endif
|
||||
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
||||
#ifdef TCP_DEFER_ACCEPT
|
||||
if (ls[i].deferred_accept) {
|
||||
ls[i].add_deferred = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ngx_open_listening_sockets(cycle) != NGX_OK) {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ struct ngx_log_s {
|
|||
char *action;
|
||||
|
||||
ngx_log_t *next;
|
||||
|
||||
NGX_COMPAT_BEGIN(5)
|
||||
NGX_COMPAT_END
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ struct ngx_peer_connection_s {
|
|||
|
||||
ngx_log_t *log;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID || NGX_COMPAT)
|
||||
ngx_str_t *hint;
|
||||
ngx_str_t *sid;
|
||||
#endif
|
||||
|
||||
unsigned cached:1;
|
||||
unsigned transparent:1;
|
||||
unsigned so_keepalive:1;
|
||||
|
|
@ -68,7 +73,7 @@ struct ngx_peer_connection_s {
|
|||
/* ngx_connection_log_error_e */
|
||||
unsigned log_error:2;
|
||||
|
||||
NGX_COMPAT_BEGIN(2)
|
||||
NGX_COMPAT_BEGIN(1)
|
||||
NGX_COMPAT_END
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -535,19 +535,20 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
|
|||
static ngx_int_t
|
||||
ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
|
||||
{
|
||||
u_char *p, *host, *last, ch;
|
||||
size_t len, root;
|
||||
ngx_err_t err;
|
||||
ngx_int_t rc, depth;
|
||||
ngx_uint_t overwrite, slash, dir, flags;
|
||||
ngx_str_t path, uri, duri, args;
|
||||
ngx_tree_ctx_t tree;
|
||||
ngx_copy_file_t cf;
|
||||
ngx_file_info_t fi;
|
||||
ngx_table_elt_t *dest, *over;
|
||||
ngx_ext_rename_file_t ext;
|
||||
ngx_http_dav_copy_ctx_t copy;
|
||||
ngx_http_dav_loc_conf_t *dlcf;
|
||||
u_char *p, *host, *last, ch;
|
||||
size_t len, root;
|
||||
ngx_err_t err;
|
||||
ngx_int_t rc, depth;
|
||||
ngx_uint_t overwrite, slash, dir, flags;
|
||||
ngx_str_t path, uri, duri, args;
|
||||
ngx_tree_ctx_t tree;
|
||||
ngx_copy_file_t cf;
|
||||
ngx_file_info_t fi;
|
||||
ngx_table_elt_t *dest, *over;
|
||||
ngx_ext_rename_file_t ext;
|
||||
ngx_http_dav_copy_ctx_t copy;
|
||||
ngx_http_dav_loc_conf_t *dlcf;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
|
|
@ -644,6 +645,18 @@ destination_done:
|
|||
return NGX_HTTP_CONFLICT;
|
||||
}
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
if (clcf->alias
|
||||
&& clcf->alias != NGX_MAX_SIZE_T_VALUE
|
||||
&& duri.len < clcf->alias)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent invalid \"Destination\" header: \"%V\"",
|
||||
&dest->value);
|
||||
return NGX_HTTP_BAD_REQUEST;
|
||||
}
|
||||
|
||||
depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH);
|
||||
|
||||
if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) {
|
||||
|
|
|
|||
|
|
@ -645,7 +645,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
|||
|
||||
if (ngx_strcmp(value[0].data, "include") == 0) {
|
||||
|
||||
rv = ngx_http_geo_include(cf, ctx, &value[1]);
|
||||
if (strpbrk((char *) value[1].data, "*?[") == NULL) {
|
||||
rv = ngx_http_geo_include(cf, ctx, &value[1]);
|
||||
|
||||
} else {
|
||||
rv = ngx_conf_include(cf, dummy, conf);
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
|
|
|
|||
|
|
@ -1224,6 +1224,9 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
|
|||
ctx->rst = 0;
|
||||
ctx->goaway = 0;
|
||||
ctx->connection = NULL;
|
||||
ctx->in = NULL;
|
||||
ctx->busy = NULL;
|
||||
ctx->out = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -901,8 +901,11 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||
}
|
||||
}
|
||||
|
||||
if (end_offset < start_offset) {
|
||||
end_offset = start_offset;
|
||||
if (end_offset <= start_offset) {
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"no data between start time and end time in \"%s\"",
|
||||
mp4->file.name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
mp4->moov_size += 8;
|
||||
|
|
@ -913,7 +916,7 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
|
|||
|
||||
*prev = &mp4->mdat_atom;
|
||||
|
||||
if (start_offset > mp4->mdat_data.buf->file_last) {
|
||||
if (start_offset >= mp4->mdat_data.buf->file_last) {
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"start time is out mp4 mdat atom in \"%s\"",
|
||||
mp4->file.name.data);
|
||||
|
|
@ -2294,7 +2297,7 @@ ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
"mp4 time-to-sample entries:%uD", entries);
|
||||
|
||||
if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t)
|
||||
+ entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 stts atom too small", mp4->file.name.data);
|
||||
|
|
@ -2609,7 +2612,7 @@ ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
atom->last = atom_table;
|
||||
|
||||
if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t)
|
||||
+ entries * sizeof(uint32_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(uint32_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 stss atom too small", mp4->file.name.data);
|
||||
|
|
@ -2814,7 +2817,7 @@ ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
atom->last = atom_table;
|
||||
|
||||
if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t)
|
||||
+ entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 ctts atom too small", mp4->file.name.data);
|
||||
|
|
@ -2996,7 +2999,7 @@ ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
"sample-to-chunk entries:%uD", entries);
|
||||
|
||||
if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t)
|
||||
+ entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 stsc atom too small", mp4->file.name.data);
|
||||
|
|
@ -3390,7 +3393,7 @@ ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
|
||||
if (size == 0) {
|
||||
if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t)
|
||||
+ entries * sizeof(uint32_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(uint32_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 stsz atom too small",
|
||||
|
|
@ -3444,7 +3447,7 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|||
if (data) {
|
||||
entries = trak->sample_sizes_entries;
|
||||
|
||||
if (trak->start_sample > entries) {
|
||||
if (trak->start_sample >= entries) {
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"start time is out mp4 stsz samples in \"%s\"",
|
||||
mp4->file.name.data);
|
||||
|
|
@ -3549,7 +3552,7 @@ ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
|
||||
|
||||
if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t)
|
||||
+ entries * sizeof(uint32_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(uint32_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 stco atom too small", mp4->file.name.data);
|
||||
|
|
@ -3619,7 +3622,7 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (trak->start_chunk > trak->chunks) {
|
||||
if (trak->start_chunk >= trak->chunks) {
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"start time is out mp4 stco chunks in \"%s\"",
|
||||
mp4->file.name.data);
|
||||
|
|
@ -3765,7 +3768,7 @@ ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
|
||||
|
||||
if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t)
|
||||
+ entries * sizeof(uint64_t) > atom_data_size)
|
||||
+ (uint64_t) entries * sizeof(uint64_t) > atom_data_size)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"\"%s\" mp4 co64 atom too small", mp4->file.name.data);
|
||||
|
|
@ -3834,7 +3837,7 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (trak->start_chunk > trak->chunks) {
|
||||
if (trak->start_chunk >= trak->chunks) {
|
||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||
"start time is out mp4 co64 chunks in \"%s\"",
|
||||
mp4->file.name.data);
|
||||
|
|
|
|||
|
|
@ -84,9 +84,6 @@ static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
|
|||
static ngx_int_t
|
||||
ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_internal_connection_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
|
|
@ -749,7 +746,7 @@ static char ngx_http_proxy_version_11[] = " HTTP/1.1" CRLF;
|
|||
|
||||
static ngx_keyval_t ngx_http_proxy_headers[] = {
|
||||
{ ngx_string("Host"), ngx_string("$proxy_internal_host") },
|
||||
{ ngx_string("Connection"), ngx_string("$proxy_internal_connection") },
|
||||
{ ngx_string("Connection"), ngx_string("") },
|
||||
{ ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
|
||||
{ ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
|
||||
{ ngx_string("TE"), ngx_string("") },
|
||||
|
|
@ -777,7 +774,7 @@ static ngx_str_t ngx_http_proxy_hide_headers[] = {
|
|||
|
||||
static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
|
||||
{ ngx_string("Host"), ngx_string("$proxy_internal_host") },
|
||||
{ ngx_string("Connection"), ngx_string("$proxy_internal_connection") },
|
||||
{ ngx_string("Connection"), ngx_string("") },
|
||||
{ ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
|
||||
{ ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
|
||||
{ ngx_string("TE"), ngx_string("") },
|
||||
|
|
@ -816,10 +813,6 @@ static ngx_http_variable_t ngx_http_proxy_vars[] = {
|
|||
ngx_http_proxy_host_variable, 1,
|
||||
NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
|
||||
|
||||
{ ngx_string("proxy_internal_connection"), NULL,
|
||||
ngx_http_proxy_internal_connection_variable, 0,
|
||||
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
|
||||
|
||||
{ ngx_string("proxy_internal_body_length"), NULL,
|
||||
ngx_http_proxy_internal_body_length_variable, 0,
|
||||
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
|
||||
|
|
@ -2777,29 +2770,6 @@ ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_internal_connection_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
ngx_http_proxy_ctx_t *ctx;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
||||
|
||||
if (ctx == NULL || !ctx->legacy) {
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
|
||||
ngx_str_set(v, "close");
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
|
|
@ -4030,7 +4000,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_ptr_value(conf->cookie_flags, prev->cookie_flags, NULL);
|
||||
|
||||
ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
|
||||
NGX_HTTP_VERSION_10);
|
||||
NGX_HTTP_VERSION_11);
|
||||
|
||||
ngx_conf_merge_uint_value(conf->headers_hash_max_size,
|
||||
prev->headers_hash_max_size, 512);
|
||||
|
|
|
|||
|
|
@ -946,6 +946,7 @@ ngx_http_proxy_v2_reinit_request(ngx_http_request_t *r)
|
|||
ctx->connection = NULL;
|
||||
ctx->in = NULL;
|
||||
ctx->busy = NULL;
|
||||
ctx->out = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,6 +200,17 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->cached = 0;
|
||||
pc->connection = NULL;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
peer = ngx_http_upstream_get_rr_peer_by_sid(&hp->rrp, pc->hint, &p, 1);
|
||||
|
||||
if (peer) {
|
||||
n = p / (8 * sizeof(uintptr_t));
|
||||
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
|
||||
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
/*
|
||||
|
|
@ -273,6 +284,10 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
found:
|
||||
#endif
|
||||
|
||||
hp->rrp.current = peer;
|
||||
ngx_http_upstream_rr_peer_ref(hp->rrp.peers, peer);
|
||||
|
||||
|
|
@ -280,6 +295,10 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->socklen = peer->socklen;
|
||||
pc->name = &peer->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &peer->sid;
|
||||
#endif
|
||||
|
||||
peer->conns++;
|
||||
|
||||
if (now - peer->checked > peer->fail_timeout) {
|
||||
|
|
@ -591,6 +610,14 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
points = hcf->points;
|
||||
point = &points->point[0];
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
best = ngx_http_upstream_get_rr_peer_by_sid(&hp->rrp, pc->hint, &best_i, 0);
|
||||
|
||||
if (best) {
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( ;; ) {
|
||||
server = point[hp->hash % points->number].server;
|
||||
|
||||
|
|
@ -671,6 +698,10 @@ found:
|
|||
pc->socklen = best->socklen;
|
||||
pc->name = &best->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &best->sid;
|
||||
#endif
|
||||
|
||||
best->conns++;
|
||||
|
||||
if (now - best->checked > best->fail_timeout) {
|
||||
|
|
|
|||
|
|
@ -183,6 +183,17 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
|
||||
hash = iphp->hash;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
peer = ngx_http_upstream_get_rr_peer_by_sid(&iphp->rrp, pc->hint, &p, 1);
|
||||
|
||||
if (peer) {
|
||||
n = p / (8 * sizeof(uintptr_t));
|
||||
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
|
||||
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) {
|
||||
|
|
@ -239,6 +250,10 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
found:
|
||||
#endif
|
||||
|
||||
iphp->rrp.current = peer;
|
||||
ngx_http_upstream_rr_peer_ref(iphp->rrp.peers, peer);
|
||||
|
||||
|
|
@ -246,6 +261,10 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->socklen = peer->socklen;
|
||||
pc->name = &peer->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &peer->sid;
|
||||
#endif
|
||||
|
||||
peer->conns++;
|
||||
|
||||
if (now - peer->checked > peer->fail_timeout) {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ typedef struct {
|
|||
ngx_queue_t cache;
|
||||
ngx_queue_t free;
|
||||
|
||||
ngx_http_upstream_init_pt original_init_upstream;
|
||||
ngx_http_upstream_init_peer_pt original_init_peer;
|
||||
|
||||
ngx_uint_t local; /* unsigned local:1; */
|
||||
|
||||
} ngx_http_upstream_keepalive_srv_conf_t;
|
||||
|
||||
|
||||
|
|
@ -34,6 +35,8 @@ typedef struct {
|
|||
socklen_t socklen;
|
||||
ngx_sockaddr_t sockaddr;
|
||||
|
||||
ngx_http_upstream_conf_t *tag;
|
||||
|
||||
} ngx_http_upstream_keepalive_cache_t;
|
||||
|
||||
|
||||
|
|
@ -52,6 +55,8 @@ typedef struct {
|
|||
ngx_event_save_peer_session_pt original_save_session;
|
||||
#endif
|
||||
|
||||
ngx_event_notify_peer_pt original_notify;
|
||||
|
||||
} ngx_http_upstream_keepalive_peer_data_t;
|
||||
|
||||
|
||||
|
|
@ -73,7 +78,12 @@ static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc,
|
|||
void *data);
|
||||
#endif
|
||||
|
||||
static void ngx_http_upstream_notify_keepalive_peer(ngx_peer_connection_t *pc,
|
||||
void *data, ngx_uint_t type);
|
||||
|
||||
static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf);
|
||||
static char *ngx_http_upstream_keepalive_init_main_conf(ngx_conf_t *cf,
|
||||
void *conf);
|
||||
static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
|
@ -81,7 +91,7 @@ static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
static ngx_command_t ngx_http_upstream_keepalive_commands[] = {
|
||||
|
||||
{ ngx_string("keepalive"),
|
||||
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
|
||||
NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12,
|
||||
ngx_http_upstream_keepalive,
|
||||
NGX_HTTP_SRV_CONF_OFFSET,
|
||||
0,
|
||||
|
|
@ -117,7 +127,7 @@ static ngx_http_module_t ngx_http_upstream_keepalive_module_ctx = {
|
|||
NULL, /* postconfiguration */
|
||||
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
ngx_http_upstream_keepalive_init_main_conf, /* init main configuration */
|
||||
|
||||
ngx_http_upstream_keepalive_create_conf, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
|
@ -143,52 +153,6 @@ ngx_module_t ngx_http_upstream_keepalive_module = {
|
|||
};
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_init_keepalive(ngx_conf_t *cf,
|
||||
ngx_http_upstream_srv_conf_t *us)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
ngx_http_upstream_keepalive_srv_conf_t *kcf;
|
||||
ngx_http_upstream_keepalive_cache_t *cached;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
|
||||
"init keepalive");
|
||||
|
||||
kcf = ngx_http_conf_upstream_srv_conf(us,
|
||||
ngx_http_upstream_keepalive_module);
|
||||
|
||||
ngx_conf_init_msec_value(kcf->time, 3600000);
|
||||
ngx_conf_init_msec_value(kcf->timeout, 60000);
|
||||
ngx_conf_init_uint_value(kcf->requests, 1000);
|
||||
|
||||
if (kcf->original_init_upstream(cf, us) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
kcf->original_init_peer = us->peer.init;
|
||||
|
||||
us->peer.init = ngx_http_upstream_init_keepalive_peer;
|
||||
|
||||
/* allocate cache items and add to free queue */
|
||||
|
||||
cached = ngx_pcalloc(cf->pool,
|
||||
sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached);
|
||||
if (cached == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_queue_init(&kcf->cache);
|
||||
ngx_queue_init(&kcf->free);
|
||||
|
||||
for (i = 0; i < kcf->max_cached; i++) {
|
||||
ngx_queue_insert_head(&kcf->free, &cached[i].queue);
|
||||
cached[i].conf = kcf;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
|
||||
ngx_http_upstream_srv_conf_t *us)
|
||||
|
|
@ -228,6 +192,11 @@ ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
|
|||
r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session;
|
||||
#endif
|
||||
|
||||
if (r->upstream->peer.notify) {
|
||||
kp->original_notify = r->upstream->peer.notify;
|
||||
r->upstream->peer.notify = ngx_http_upstream_notify_keepalive_peer;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +233,10 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
|
|||
item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
|
||||
c = item->connection;
|
||||
|
||||
if (kp->conf->local && item->tag != kp->upstream->conf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr,
|
||||
item->socklen, pc->socklen)
|
||||
== 0)
|
||||
|
|
@ -377,6 +350,7 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
|
|||
ngx_queue_insert_head(&kp->conf->cache, q);
|
||||
|
||||
item->connection = c;
|
||||
item->tag = u->conf;
|
||||
|
||||
pc->connection = NULL;
|
||||
|
||||
|
|
@ -507,6 +481,16 @@ ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data)
|
|||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_upstream_notify_keepalive_peer(ngx_peer_connection_t *pc, void *data,
|
||||
ngx_uint_t type)
|
||||
{
|
||||
ngx_http_upstream_keepalive_peer_data_t *kp = data;
|
||||
|
||||
kp->original_notify(pc, kp->data, type);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
|
||||
{
|
||||
|
|
@ -521,29 +505,89 @@ ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
|
|||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* conf->original_init_upstream = NULL;
|
||||
* conf->original_init_peer = NULL;
|
||||
* conf->max_cached = 0;
|
||||
* conf->local = 0;
|
||||
*/
|
||||
|
||||
conf->time = NGX_CONF_UNSET_MSEC;
|
||||
conf->timeout = NGX_CONF_UNSET_MSEC;
|
||||
conf->requests = NGX_CONF_UNSET_UINT;
|
||||
conf->max_cached = NGX_CONF_UNSET_UINT;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_upstream_keepalive_init_main_conf(ngx_conf_t *cf, void *conf)
|
||||
{
|
||||
ngx_uint_t i, j;
|
||||
ngx_http_upstream_srv_conf_t **uscfp;
|
||||
ngx_http_upstream_main_conf_t *umcf;
|
||||
ngx_http_upstream_keepalive_cache_t *cached;
|
||||
ngx_http_upstream_keepalive_srv_conf_t *kcf;
|
||||
|
||||
umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);
|
||||
|
||||
uscfp = umcf->upstreams.elts;
|
||||
|
||||
for (i = 0; i < umcf->upstreams.nelts; i++) {
|
||||
|
||||
/* skip implicit upstreams */
|
||||
if (uscfp[i]->srv_conf == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kcf = ngx_http_conf_upstream_srv_conf(uscfp[i],
|
||||
ngx_http_upstream_keepalive_module);
|
||||
|
||||
if (kcf->max_cached == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_conf_init_msec_value(kcf->time, 3600000);
|
||||
ngx_conf_init_msec_value(kcf->timeout, 60000);
|
||||
ngx_conf_init_uint_value(kcf->requests, 1000);
|
||||
|
||||
if (kcf->max_cached == NGX_CONF_UNSET_UINT) {
|
||||
kcf->local = 1;
|
||||
kcf->max_cached = 32;
|
||||
}
|
||||
|
||||
kcf->original_init_peer = uscfp[i]->peer.init;
|
||||
|
||||
uscfp[i]->peer.init = ngx_http_upstream_init_keepalive_peer;
|
||||
|
||||
/* allocate cache items and add to free queue */
|
||||
|
||||
cached = ngx_pcalloc(cf->pool,
|
||||
sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached);
|
||||
if (cached == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_queue_init(&kcf->cache);
|
||||
ngx_queue_init(&kcf->free);
|
||||
|
||||
for (j = 0; j < kcf->max_cached; j++) {
|
||||
ngx_queue_insert_head(&kcf->free, &cached[j].queue);
|
||||
cached[j].conf = kcf;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_upstream_srv_conf_t *uscf;
|
||||
ngx_http_upstream_keepalive_srv_conf_t *kcf = conf;
|
||||
|
||||
ngx_int_t n;
|
||||
ngx_str_t *value;
|
||||
|
||||
if (kcf->max_cached) {
|
||||
if (kcf->max_cached != NGX_CONF_UNSET_UINT) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
|
|
@ -553,7 +597,7 @@ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
n = ngx_atoi(value[1].data, value[1].len);
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
if (n == NGX_ERROR) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid value \"%V\" in \"%V\" directive",
|
||||
&value[1], &cmd->name);
|
||||
|
|
@ -562,15 +606,16 @@ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
kcf->max_cached = n;
|
||||
|
||||
/* init upstream handler */
|
||||
if (cf->args->nelts == 3) {
|
||||
if (ngx_strcmp(value[2].data, "local") == 0) {
|
||||
kcf->local = 1;
|
||||
|
||||
uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
|
||||
|
||||
kcf->original_init_upstream = uscf->peer.init_upstream
|
||||
? uscf->peer.init_upstream
|
||||
: ngx_http_upstream_init_round_robin;
|
||||
|
||||
uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;
|
||||
} else {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid parameter \"%V\"", &value[2]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,14 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
|
|||
p = 0;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
best = ngx_http_upstream_get_rr_peer_by_sid(rrp, pc->hint, &p, 0);
|
||||
|
||||
if (best) {
|
||||
goto best_chosen;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (peer = peers->peer, i = 0;
|
||||
peer;
|
||||
peer = peer->next, i++)
|
||||
|
|
@ -239,6 +247,10 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
|
|||
|
||||
best->current_weight -= total;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
best_chosen:
|
||||
#endif
|
||||
|
||||
if (now - best->checked > best->fail_timeout) {
|
||||
best->checked = now;
|
||||
}
|
||||
|
|
@ -247,6 +259,10 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->socklen = best->socklen;
|
||||
pc->name = &best->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &best->sid;
|
||||
#endif
|
||||
|
||||
best->conns++;
|
||||
|
||||
rrp->current = best;
|
||||
|
|
|
|||
|
|
@ -249,6 +249,17 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)
|
|||
|
||||
now = ngx_time();
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
peer = ngx_http_upstream_get_rr_peer_by_sid(rrp, pc->hint, &i, 1);
|
||||
|
||||
if (peer) {
|
||||
n = i / (8 * sizeof(uintptr_t));
|
||||
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
|
||||
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
i = ngx_http_upstream_peek_random_peer(peers, rp);
|
||||
|
|
@ -292,6 +303,10 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
found:
|
||||
#endif
|
||||
|
||||
rrp->current = peer;
|
||||
ngx_http_upstream_rr_peer_ref(peers, peer);
|
||||
|
||||
|
|
@ -303,6 +318,10 @@ ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->socklen = peer->socklen;
|
||||
pc->name = &peer->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &peer->sid;
|
||||
#endif
|
||||
|
||||
peer->conns++;
|
||||
|
||||
ngx_http_upstream_rr_peer_unlock(peers, peer);
|
||||
|
|
@ -357,6 +376,17 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data)
|
|||
p = 0;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
peer = ngx_http_upstream_get_rr_peer_by_sid(rrp, pc->hint, &i, 0);
|
||||
|
||||
if (peer) {
|
||||
n = i / (8 * sizeof(uintptr_t));
|
||||
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
|
||||
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
i = ngx_http_upstream_peek_random_peer(peers, rp);
|
||||
|
|
@ -410,6 +440,10 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
found:
|
||||
#endif
|
||||
|
||||
rrp->current = peer;
|
||||
ngx_http_upstream_rr_peer_ref(peers, peer);
|
||||
|
||||
|
|
@ -421,6 +455,10 @@ ngx_http_upstream_get_random2_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->socklen = peer->socklen;
|
||||
pc->name = &peer->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &peer->sid;
|
||||
#endif
|
||||
|
||||
peer->conns++;
|
||||
|
||||
ngx_http_upstream_rr_peers_unlock(peers);
|
||||
|
|
|
|||
1513
src/http/modules/ngx_http_upstream_sticky_module.c
Normal file
1513
src/http/modules/ngx_http_upstream_sticky_module.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -385,6 +385,9 @@ ngx_http_upstream_zone_copy_peer(ngx_http_upstream_rr_peers_t *peers,
|
|||
ngx_memcpy(dst, src, sizeof(ngx_http_upstream_rr_peer_t));
|
||||
dst->sockaddr = NULL;
|
||||
dst->name.data = NULL;
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
dst->sid.data = NULL;
|
||||
#endif
|
||||
dst->server.data = NULL;
|
||||
dst->host = NULL;
|
||||
}
|
||||
|
|
@ -399,9 +402,19 @@ ngx_http_upstream_zone_copy_peer(ngx_http_upstream_rr_peers_t *peers,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
dst->sid.data = ngx_slab_calloc_locked(pool, NGX_HTTP_UPSTREAM_SID_LEN);
|
||||
if (dst->sid.data == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (src) {
|
||||
ngx_memcpy(dst->sockaddr, src->sockaddr, src->socklen);
|
||||
ngx_memcpy(dst->name.data, src->name.data, src->name.len);
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
ngx_memcpy(dst->sid.data, src->sid.data, src->sid.len);
|
||||
#endif
|
||||
|
||||
dst->server.data = ngx_slab_alloc_locked(pool, src->server.len);
|
||||
if (dst->server.data == NULL) {
|
||||
|
|
@ -460,6 +473,12 @@ failed:
|
|||
ngx_slab_free_locked(pool, dst->server.data);
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
if (dst->sid.data) {
|
||||
ngx_slab_free_locked(pool, dst->sid.data);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dst->name.data) {
|
||||
ngx_slab_free_locked(pool, dst->name.data);
|
||||
}
|
||||
|
|
@ -573,6 +592,10 @@ ngx_http_upstream_zone_preresolve(ngx_http_upstream_rr_peer_t *resolve,
|
|||
peer->fail_timeout = template->fail_timeout;
|
||||
peer->down = template->down;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
ngx_http_upstream_copy_round_robin_sid(peer, template);
|
||||
#endif
|
||||
|
||||
(*peers->config)++;
|
||||
|
||||
*peerp = peer;
|
||||
|
|
@ -966,6 +989,10 @@ again:
|
|||
peer->fail_timeout = template->fail_timeout;
|
||||
peer->down = template->down;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
ngx_http_upstream_copy_round_robin_sid(peer, template);
|
||||
#endif
|
||||
|
||||
*peerp = peer;
|
||||
peerp = &peer->next;
|
||||
|
||||
|
|
|
|||
|
|
@ -1846,6 +1846,7 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
|
|||
#endif
|
||||
|
||||
ls->type = addr->opt.type;
|
||||
ls->protocol = addr->opt.protocol;
|
||||
ls->backlog = addr->opt.backlog;
|
||||
ls->rcvbuf = addr->opt.rcvbuf;
|
||||
ls->sndbuf = addr->opt.sndbuf;
|
||||
|
|
|
|||
|
|
@ -4223,6 +4223,19 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[n].data, "multipath") == 0) {
|
||||
#ifdef IPPROTO_MPTCP
|
||||
lsopt.protocol = IPPROTO_MPTCP;
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"multipath is not supported "
|
||||
"on this platform, ignored");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[n].data, "ssl") == 0) {
|
||||
#if (NGX_HTTP_SSL)
|
||||
lsopt.ssl = 1;
|
||||
|
|
@ -4389,6 +4402,12 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef IPPROTO_MPTCP
|
||||
if (lsopt.protocol == IPPROTO_MPTCP) {
|
||||
return "\"multipath\" parameter is incompatible with \"quic\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
if (lsopt.ssl) {
|
||||
return "\"ssl\" parameter is incompatible with \"quic\"";
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ typedef struct {
|
|||
int rcvbuf;
|
||||
int sndbuf;
|
||||
int type;
|
||||
int protocol;
|
||||
#if (NGX_HAVE_SETFIB)
|
||||
int setfib;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ static ngx_str_t ngx_http_status_lines[] = {
|
|||
ngx_string("404 Not Found"),
|
||||
ngx_string("405 Not Allowed"),
|
||||
ngx_string("406 Not Acceptable"),
|
||||
ngx_null_string, /* "407 Proxy Authentication Required" */
|
||||
ngx_string("407 Proxy Authentication Required"),
|
||||
ngx_string("408 Request Time-out"),
|
||||
ngx_string("409 Conflict"),
|
||||
ngx_string("410 Gone"),
|
||||
|
|
|
|||
|
|
@ -152,6 +152,10 @@ ngx_http_header_t ngx_http_headers_in[] = {
|
|||
offsetof(ngx_http_headers_in_t, authorization),
|
||||
ngx_http_process_unique_header_line },
|
||||
|
||||
{ ngx_string("Proxy-Authorization"),
|
||||
offsetof(ngx_http_headers_in_t, proxy_authorization),
|
||||
ngx_http_process_unique_header_line },
|
||||
|
||||
{ ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
|
||||
ngx_http_process_header_line },
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@
|
|||
#define NGX_HTTP_FORBIDDEN 403
|
||||
#define NGX_HTTP_NOT_FOUND 404
|
||||
#define NGX_HTTP_NOT_ALLOWED 405
|
||||
#define NGX_HTTP_PROXY_AUTH_REQUIRED 407
|
||||
#define NGX_HTTP_REQUEST_TIME_OUT 408
|
||||
#define NGX_HTTP_CONFLICT 409
|
||||
#define NGX_HTTP_LENGTH_REQUIRED 411
|
||||
|
|
@ -210,6 +211,7 @@ typedef struct {
|
|||
#endif
|
||||
|
||||
ngx_table_elt_t *authorization;
|
||||
ngx_table_elt_t *proxy_authorization;
|
||||
|
||||
ngx_table_elt_t *keep_alive;
|
||||
|
||||
|
|
@ -273,6 +275,7 @@ typedef struct {
|
|||
ngx_table_elt_t *content_range;
|
||||
ngx_table_elt_t *accept_ranges;
|
||||
ngx_table_elt_t *www_authenticate;
|
||||
ngx_table_elt_t *proxy_authenticate;
|
||||
ngx_table_elt_t *expires;
|
||||
ngx_table_elt_t *etag;
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,14 @@ static char ngx_http_error_406_page[] =
|
|||
;
|
||||
|
||||
|
||||
static char ngx_http_error_407_page[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>407 Proxy Authentication Required</title></head>" CRLF
|
||||
"<body>" CRLF
|
||||
"<center><h1>407 Proxy Authentication Required</h1></center>" CRLF
|
||||
;
|
||||
|
||||
|
||||
static char ngx_http_error_408_page[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>408 Request Time-out</title></head>" CRLF
|
||||
|
|
@ -364,7 +372,7 @@ static ngx_str_t ngx_http_error_pages[] = {
|
|||
ngx_string(ngx_http_error_404_page),
|
||||
ngx_string(ngx_http_error_405_page),
|
||||
ngx_string(ngx_http_error_406_page),
|
||||
ngx_null_string, /* 407 */
|
||||
ngx_string(ngx_http_error_407_page),
|
||||
ngx_string(ngx_http_error_408_page),
|
||||
ngx_string(ngx_http_error_409_page),
|
||||
ngx_string(ngx_http_error_410_page),
|
||||
|
|
|
|||
|
|
@ -2607,6 +2607,10 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||
}
|
||||
}
|
||||
|
||||
if (u->peer.notify) {
|
||||
u->peer.notify(&u->peer, u->peer.data, NGX_HTTP_UPSTREAM_NOTIFY_HEADER);
|
||||
}
|
||||
|
||||
if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -4593,6 +4597,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
|||
|
||||
u->peer.free(&u->peer, u->peer.data, state);
|
||||
u->peer.sockaddr = NULL;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
u->peer.sid = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
|
||||
|
|
@ -4776,6 +4784,10 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
|
|||
if (u->peer.free && u->peer.sockaddr) {
|
||||
u->peer.free(&u->peer, u->peer.data, 0);
|
||||
u->peer.sockaddr = NULL;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
u->peer.sid = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (u->peer.connection) {
|
||||
|
|
@ -6522,11 +6534,46 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
goto not_supported;
|
||||
}
|
||||
|
||||
us->down = 1;
|
||||
us->down = NGX_HTTP_UPSTREAM_FAILED;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_STICKY)
|
||||
if (ngx_strcmp(value[i].data, "drain") == 0) {
|
||||
|
||||
if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
|
||||
goto not_supported;
|
||||
}
|
||||
|
||||
us->down = NGX_HTTP_UPSTREAM_DRAINING;
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
if (ngx_strncmp(value[i].data, "route=", 6) == 0) {
|
||||
|
||||
us->sid.data = &value[i].data[6];
|
||||
us->sid.len = value[i].len - 6;
|
||||
|
||||
if (us->sid.len == 0) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "route is empty");
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (us->sid.len > NGX_HTTP_UPSTREAM_SID_LEN) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"route is longer than %d",
|
||||
NGX_HTTP_UPSTREAM_SID_LEN);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_ZONE)
|
||||
if (ngx_strcmp(value[i].data, "resolve") == 0) {
|
||||
resolve = 1;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@
|
|||
#define NGX_HTTP_UPSTREAM_IGN_VARY 0x00000200
|
||||
|
||||
|
||||
#define NGX_HTTP_UPSTREAM_NOTIFY_HEADER 0x1
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t status;
|
||||
ngx_msec_t response_time;
|
||||
|
|
@ -110,8 +113,9 @@ typedef struct {
|
|||
ngx_str_t service;
|
||||
#endif
|
||||
|
||||
NGX_COMPAT_BEGIN(2)
|
||||
NGX_COMPAT_END
|
||||
#if (NGX_HTTP_UPSTREAM_SID || NGX_COMPAT)
|
||||
ngx_str_t sid;
|
||||
#endif
|
||||
} ngx_http_upstream_server_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,14 +8,20 @@
|
|||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_md5.h>
|
||||
|
||||
|
||||
#define ngx_http_upstream_tries(p) ((p)->tries \
|
||||
+ ((p)->next ? (p)->next->tries : 0))
|
||||
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
static ngx_int_t ngx_http_upstream_create_sid(ngx_conf_t *cf,
|
||||
ngx_http_upstream_rr_peer_t *peer, ngx_str_t *route);
|
||||
#endif
|
||||
|
||||
static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
|
||||
ngx_http_upstream_rr_peer_data_t *rrp);
|
||||
ngx_http_upstream_rr_peer_data_t *rrp, ngx_peer_connection_t *pc);
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
|
|
@ -190,6 +196,14 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
|
|||
peer[n].down = server[i].down;
|
||||
peer[n].server = server[i].name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
if (ngx_http_upstream_create_sid(cf, &peer[n], &server[i].sid)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
*rpeerp = &peer[n];
|
||||
rpeerp = &peer[n].next;
|
||||
n++;
|
||||
|
|
@ -211,6 +225,14 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
|
|||
peer[n].down = server[i].down;
|
||||
peer[n].server = server[i].name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
if (ngx_http_upstream_create_sid(cf, &peer[n], &server[i].sid)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
*peerp = &peer[n];
|
||||
peerp = &peer[n].next;
|
||||
n++;
|
||||
|
|
@ -316,6 +338,14 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
|
|||
peer[n].down = server[i].down;
|
||||
peer[n].server = server[i].name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
if (ngx_http_upstream_create_sid(cf, &peer[n], &server[i].sid)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
*rpeerp = &peer[n];
|
||||
rpeerp = &peer[n].next;
|
||||
n++;
|
||||
|
|
@ -337,6 +367,14 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
|
|||
peer[n].down = server[i].down;
|
||||
peer[n].server = server[i].name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
if (ngx_http_upstream_create_sid(cf, &peer[n], &server[i].sid)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
*peerp = &peer[n];
|
||||
peerp = &peer[n].next;
|
||||
n++;
|
||||
|
|
@ -416,6 +454,63 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
|
|||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_create_sid(ngx_conf_t *cf, ngx_http_upstream_rr_peer_t *peer,
|
||||
ngx_str_t *route)
|
||||
{
|
||||
if (route->len) {
|
||||
peer->route = 1;
|
||||
peer->sid = *route;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
peer->sid.data = ngx_pnalloc(cf->pool, NGX_HTTP_UPSTREAM_SID_LEN);
|
||||
if (peer->sid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_http_upstream_init_round_robin_sid(peer, NULL);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_http_upstream_init_round_robin_sid(ngx_http_upstream_rr_peer_t *peer,
|
||||
ngx_str_t *route)
|
||||
{
|
||||
u_char hash[16];
|
||||
ngx_md5_t md5;
|
||||
|
||||
if (route && route->len) {
|
||||
peer->route = 1;
|
||||
peer->sid.len = route->len;
|
||||
ngx_memcpy(peer->sid.data, route->data, route->len);
|
||||
return;
|
||||
}
|
||||
|
||||
peer->route = 0;
|
||||
|
||||
/* SID is the MD5 hash of a printable socket address */
|
||||
|
||||
if (peer->name.len == 0) {
|
||||
peer->sid.len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_md5_init(&md5);
|
||||
ngx_md5_update(&md5, peer->name.data, peer->name.len);
|
||||
ngx_md5_final(hash, &md5);
|
||||
|
||||
ngx_hex_dump(peer->sid.data, hash, 16);
|
||||
peer->sid.len = NGX_HTTP_UPSTREAM_SID_LEN;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
|
||||
ngx_http_upstream_srv_conf_t *us)
|
||||
|
|
@ -624,15 +719,23 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
|
|||
#endif
|
||||
|
||||
if (peers->single) {
|
||||
peer = peers->peer;
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
peer = ngx_http_upstream_get_rr_peer_by_sid(rrp, pc->hint, &i, 0);
|
||||
|
||||
if (peer->down) {
|
||||
goto failed;
|
||||
}
|
||||
if (peer == NULL) {
|
||||
#endif
|
||||
peer = peers->peer;
|
||||
|
||||
if (peer->max_conns && peer->conns >= peer->max_conns) {
|
||||
goto failed;
|
||||
if (peer->down) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (peer->max_conns && peer->conns >= peer->max_conns) {
|
||||
goto failed;
|
||||
}
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
}
|
||||
#endif
|
||||
|
||||
rrp->current = peer;
|
||||
ngx_http_upstream_rr_peer_ref(peers, peer);
|
||||
|
|
@ -641,7 +744,7 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
|
|||
|
||||
/* there are several peers */
|
||||
|
||||
peer = ngx_http_upstream_get_peer(rrp);
|
||||
peer = ngx_http_upstream_get_peer(rrp, pc);
|
||||
|
||||
if (peer == NULL) {
|
||||
goto failed;
|
||||
|
|
@ -656,6 +759,10 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->socklen = peer->socklen;
|
||||
pc->name = &peer->name;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
pc->sid = &peer->sid;
|
||||
#endif
|
||||
|
||||
peer->conns++;
|
||||
|
||||
ngx_http_upstream_rr_peers_unlock(peers);
|
||||
|
|
@ -701,7 +808,8 @@ busy:
|
|||
|
||||
|
||||
static ngx_http_upstream_rr_peer_t *
|
||||
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
|
||||
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp,
|
||||
ngx_peer_connection_t *pc)
|
||||
{
|
||||
time_t now;
|
||||
uintptr_t m;
|
||||
|
|
@ -709,6 +817,12 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
|
|||
ngx_uint_t i, n, p;
|
||||
ngx_http_upstream_rr_peer_t *peer, *best;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
ngx_int_t low_limit;
|
||||
ngx_uint_t st_p;
|
||||
ngx_http_upstream_rr_peer_t *st_peer;
|
||||
#endif
|
||||
|
||||
now = ngx_time();
|
||||
|
||||
best = NULL;
|
||||
|
|
@ -718,6 +832,29 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
|
|||
p = 0;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
st_peer = ngx_http_upstream_get_rr_peer_by_sid(rrp, pc->hint, &p, 0);
|
||||
|
||||
if (st_peer) {
|
||||
|
||||
low_limit = -((ngx_int_t)(rrp->peers->total_weight - st_peer->weight));
|
||||
|
||||
/*
|
||||
* note: current code accounts only one sticky request in a row, if it
|
||||
* is required to account more, multiply low_limit by N below
|
||||
*/
|
||||
if (st_peer->current_weight <= low_limit) {
|
||||
|
||||
/* do not update weights if the limit exceeded */
|
||||
best = st_peer;
|
||||
goto best_chosen;
|
||||
}
|
||||
/* else: proceed to reweight with existing st_peer */
|
||||
}
|
||||
|
||||
st_p = p;
|
||||
#endif
|
||||
|
||||
for (peer = rrp->peers->peer, i = 0;
|
||||
peer;
|
||||
peer = peer->next, i++)
|
||||
|
|
@ -757,10 +894,25 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
/* prefer peer chosen by sticky to best from RR */
|
||||
|
||||
if (st_peer) {
|
||||
best = st_peer;
|
||||
p = st_p;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (best == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
best->current_weight -= total;
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
best_chosen:
|
||||
#endif
|
||||
|
||||
rrp->current = best;
|
||||
ngx_http_upstream_rr_peer_ref(rrp->peers, best);
|
||||
|
||||
|
|
@ -769,8 +921,6 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
|
|||
|
||||
rrp->tried[n] |= m;
|
||||
|
||||
best->current_weight -= total;
|
||||
|
||||
if (now - best->checked > best->fail_timeout) {
|
||||
best->checked = now;
|
||||
}
|
||||
|
|
@ -779,6 +929,81 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
|
|||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
|
||||
ngx_http_upstream_rr_peer_t *
|
||||
ngx_http_upstream_get_rr_peer_by_sid(ngx_http_upstream_rr_peer_data_t *rrp,
|
||||
ngx_str_t *hint, ngx_uint_t *p, ngx_uint_t lock)
|
||||
{
|
||||
uintptr_t m;
|
||||
ngx_uint_t i, n;
|
||||
ngx_http_upstream_rr_peer_t *peer;
|
||||
|
||||
if (hint == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (peer = rrp->peers->peer, i = 0;
|
||||
peer;
|
||||
peer = peer->next, i++)
|
||||
{
|
||||
|
||||
if (peer->sid.len == hint->len
|
||||
&& ngx_memcmp(peer->sid.data, hint->data, hint->len) == 0)
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
found:
|
||||
|
||||
n = i / (8 * sizeof(uintptr_t));
|
||||
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
|
||||
|
||||
if (rrp->tried[n] & m) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
ngx_http_upstream_rr_peer_lock(rrp->peers, peer);
|
||||
}
|
||||
|
||||
if (peer->down
|
||||
#if (NGX_HTTP_UPSTREAM_STICKY)
|
||||
& ~NGX_HTTP_UPSTREAM_DRAINING
|
||||
#endif
|
||||
) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (peer->max_fails
|
||||
&& peer->fails >= peer->max_fails
|
||||
&& ngx_time() - peer->checked <= peer->fail_timeout)
|
||||
{
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (peer->max_conns && peer->conns >= peer->max_conns) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
*p = i;
|
||||
return peer;
|
||||
|
||||
failed:
|
||||
|
||||
if (lock) {
|
||||
ngx_http_upstream_rr_peer_unlock(rrp->peers, peer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
|
||||
ngx_uint_t state)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,17 @@
|
|||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
#define NGX_HTTP_UPSTREAM_SID_LEN 32 /* md5 in hex */
|
||||
#endif
|
||||
|
||||
#define NGX_HTTP_UPSTREAM_FAILED 1
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_STICKY)
|
||||
#define NGX_HTTP_UPSTREAM_DRAINING 8
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct ngx_http_upstream_rr_peers_s ngx_http_upstream_rr_peers_t;
|
||||
typedef struct ngx_http_upstream_rr_peer_s ngx_http_upstream_rr_peer_t;
|
||||
|
||||
|
|
@ -62,6 +73,10 @@ struct ngx_http_upstream_rr_peer_s {
|
|||
int ssl_session_len;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID || NGX_COMPAT)
|
||||
unsigned route:1;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_ZONE)
|
||||
unsigned zombie:1;
|
||||
|
||||
|
|
@ -70,9 +85,13 @@ struct ngx_http_upstream_rr_peer_s {
|
|||
ngx_http_upstream_host_t *host;
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID || NGX_COMPAT)
|
||||
ngx_str_t sid;
|
||||
#endif
|
||||
|
||||
ngx_http_upstream_rr_peer_t *next;
|
||||
|
||||
NGX_COMPAT_BEGIN(15)
|
||||
NGX_COMPAT_BEGIN(13)
|
||||
NGX_COMPAT_END
|
||||
};
|
||||
|
||||
|
|
@ -151,6 +170,9 @@ ngx_http_upstream_rr_peer_free_locked(ngx_http_upstream_rr_peers_t *peers,
|
|||
|
||||
ngx_slab_free_locked(peers->shpool, peer->sockaddr);
|
||||
ngx_slab_free_locked(peers->shpool, peer->name.data);
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
ngx_slab_free_locked(peers->shpool, peer->sid.data);
|
||||
#endif
|
||||
|
||||
if (peer->server.data) {
|
||||
ngx_slab_free_locked(peers->shpool, peer->server.data);
|
||||
|
|
@ -235,5 +257,19 @@ void ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
|
|||
void *data);
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_UPSTREAM_SID)
|
||||
|
||||
#define ngx_http_upstream_copy_round_robin_sid(dst, src) \
|
||||
ngx_http_upstream_init_round_robin_sid(dst, \
|
||||
(src)->route ? &(src)->sid : NULL)
|
||||
|
||||
void ngx_http_upstream_init_round_robin_sid(ngx_http_upstream_rr_peer_t *peer,
|
||||
ngx_str_t *route);
|
||||
ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_rr_peer_by_sid(
|
||||
ngx_http_upstream_rr_peer_data_t *rrp, ngx_str_t *hint, ngx_uint_t *p,
|
||||
ngx_uint_t lock);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_ */
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
|
|||
ls->log.data = &ls->addr_text;
|
||||
ls->log.handler = ngx_accept_log_error;
|
||||
|
||||
ls->protocol = addr[i].opt.protocol;
|
||||
ls->backlog = addr[i].opt.backlog;
|
||||
ls->rcvbuf = addr[i].opt.rcvbuf;
|
||||
ls->sndbuf = addr[i].opt.sndbuf;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ typedef struct {
|
|||
int tcp_keepintvl;
|
||||
int tcp_keepcnt;
|
||||
#endif
|
||||
int protocol;
|
||||
int backlog;
|
||||
int rcvbuf;
|
||||
int sndbuf;
|
||||
|
|
|
|||
|
|
@ -1328,7 +1328,7 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
|
|||
b->last = ngx_cpymem(b->last, "Auth-Salt: ", sizeof("Auth-Salt: ") - 1);
|
||||
b->last = ngx_copy(b->last, s->salt.data, s->salt.len);
|
||||
|
||||
s->passwd.data = NULL;
|
||||
ngx_str_null(&s->passwd);
|
||||
}
|
||||
|
||||
b->last = ngx_cpymem(b->last, "Auth-Protocol: ",
|
||||
|
|
|
|||
|
|
@ -447,6 +447,18 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[i].data, "multipath") == 0) {
|
||||
#ifdef IPPROTO_MPTCP
|
||||
ls->protocol = IPPROTO_MPTCP;
|
||||
ls->bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"multipath is not supported "
|
||||
"on this platform, ignored");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[i].data, "ssl") == 0) {
|
||||
#if (NGX_MAIL_SSL)
|
||||
ngx_mail_ssl_conf_t *sslcf;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
|
||||
static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
|
||||
static ngx_int_t ngx_mail_smtp_validate_host(ngx_str_t *name);
|
||||
static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
|
||||
static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
|
||||
static void ngx_mail_smtp_block_reading(ngx_event_t *rev);
|
||||
|
|
@ -127,6 +128,20 @@ ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ngx_mail_smtp_validate_host(&ctx->name) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"%V resolved to invalid host name \"%V\"",
|
||||
&c->addr_text, &ctx->name);
|
||||
|
||||
s->host = smtp_tempunavail;
|
||||
|
||||
ngx_resolve_addr_done(ctx);
|
||||
|
||||
ngx_mail_smtp_greeting(s, s->connection);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
c->log->action = "in resolving client hostname";
|
||||
|
||||
s->host.data = ngx_pstrdup(c->pool, &ctx->name);
|
||||
|
|
@ -149,6 +164,36 @@ ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_mail_smtp_validate_host(ngx_str_t *name)
|
||||
{
|
||||
u_char ch;
|
||||
ngx_uint_t i;
|
||||
|
||||
if (name->len == 0) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
for (i = 0; i < name->len; i++) {
|
||||
ch = name->data[i];
|
||||
|
||||
/* allow only characters from RFC 1034, Section 3.5 */
|
||||
|
||||
if ((ch >= 'a' && ch <= 'z')
|
||||
|| (ch >= 'A' && ch <= 'Z')
|
||||
|| (ch >= '0' && ch <= '9')
|
||||
|| ch == '-' || ch == '.')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_mail_smtp_resolve_name(ngx_event_t *rev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1010,6 +1010,7 @@ ngx_stream_add_listening(ngx_conf_t *cf, ngx_stream_conf_addr_t *addr)
|
|||
ls->log.handler = ngx_accept_log_error;
|
||||
|
||||
ls->type = addr->opt.type;
|
||||
ls->protocol = addr->opt.protocol;
|
||||
ls->backlog = addr->opt.backlog;
|
||||
ls->rcvbuf = addr->opt.rcvbuf;
|
||||
ls->sndbuf = addr->opt.sndbuf;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ typedef struct {
|
|||
int rcvbuf;
|
||||
int sndbuf;
|
||||
int type;
|
||||
int protocol;
|
||||
#if (NGX_HAVE_SETFIB)
|
||||
int setfib;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1202,6 +1202,19 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[i].data, "multipath") == 0) {
|
||||
#ifdef IPPROTO_MPTCP
|
||||
lsopt.protocol = IPPROTO_MPTCP;
|
||||
lsopt.set = 1;
|
||||
lsopt.bind = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"multipath is not supported "
|
||||
"on this platform, ignored");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[i].data, "ssl") == 0) {
|
||||
#if (NGX_STREAM_SSL)
|
||||
lsopt.ssl = 1;
|
||||
|
|
@ -1338,6 +1351,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef IPPROTO_MPTCP
|
||||
if (lsopt.protocol == IPPROTO_MPTCP) {
|
||||
return "\"multipath\" parameter is incompatible with \"udp\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_STREAM_SSL)
|
||||
if (lsopt.ssl) {
|
||||
return "\"ssl\" parameter is incompatible with \"udp\"";
|
||||
|
|
|
|||
|
|
@ -605,7 +605,12 @@ ngx_stream_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
|||
|
||||
if (ngx_strcmp(value[0].data, "include") == 0) {
|
||||
|
||||
rv = ngx_stream_geo_include(cf, ctx, &value[1]);
|
||||
if (strpbrk((char *) value[1].data, "*?[") == NULL) {
|
||||
rv = ngx_stream_geo_include(cf, ctx, &value[1]);
|
||||
|
||||
} else {
|
||||
rv = ngx_conf_include(cf, dummy, conf);
|
||||
}
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
|||
long rc;
|
||||
X509 *cert;
|
||||
ngx_int_t rv;
|
||||
const char *str;
|
||||
ngx_connection_t *c;
|
||||
ngx_stream_ssl_srv_conf_t *sscf;
|
||||
|
||||
|
|
@ -487,6 +488,15 @@ ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
|||
|
||||
X509_free(cert);
|
||||
}
|
||||
|
||||
if (ngx_ssl_ocsp_get_status(c, &str) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||
"client SSL certificate verify error: %s", str);
|
||||
|
||||
ngx_ssl_remove_cached_session(c->ssl->session_ctx,
|
||||
(SSL_get0_session(c->ssl->connection)));
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ ngx_stream_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
goto not_supported;
|
||||
}
|
||||
|
||||
us->down = 1;
|
||||
us->down = NGX_STREAM_UPSTREAM_FAILED;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
#include <ngx_stream.h>
|
||||
|
||||
|
||||
#define NGX_STREAM_UPSTREAM_FAILED 1
|
||||
|
||||
|
||||
typedef struct ngx_stream_upstream_rr_peers_s ngx_stream_upstream_rr_peers_t;
|
||||
typedef struct ngx_stream_upstream_rr_peer_s ngx_stream_upstream_rr_peer_t;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue