Compare commits
94
Commits
f3f38a56ad
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
008819315c
|
||
|
|
677450910d
|
||
|
|
d23cd2f0e0
|
||
|
|
72680e2bd2
|
||
|
|
10689fcf23
|
||
|
|
c8ca86a8d2
|
||
|
|
9b69c0a792
|
||
|
|
38112b0b03
|
||
|
|
8407b245de
|
||
|
|
cdf4d451e4
|
||
|
|
141b7448a4
|
||
|
|
b54c866079
|
||
|
|
f1c30863fd
|
||
|
|
d3a0c6f60b
|
||
|
|
da1c2b041b
|
||
|
|
605baf04af
|
||
|
|
e5ed7cb934
|
||
|
|
b839120943
|
||
|
|
da5d29fcc3
|
||
|
|
a204ef38f1
|
||
|
|
840eeb7822
|
||
|
|
b44a2acbe4
|
||
|
|
5343d2bbc5
|
||
|
|
0ad16b54fb
|
||
|
|
5dd8c93d82
|
||
|
|
ce239236e3
|
||
|
|
2c96cb11ab
|
||
|
|
f0749362b8
|
||
|
|
17760a9544
|
||
|
|
73d234d143
|
||
|
|
0d55d860d8
|
||
|
|
214d1434e0
|
||
|
|
b09da0b6bc
|
||
|
|
cacff59229
|
||
|
|
31970d8a16
|
||
|
|
d62ff9ef6d
|
||
|
|
0e342ce410
|
||
|
|
17c9415840
|
||
|
|
b882d7f6f8
|
||
|
|
c80cd29962
|
||
|
|
7ed9723455
|
||
|
|
c58ddf89e9
|
||
|
|
49dbf201ac
|
||
|
|
a5a19139a3
|
||
|
|
801540a2d5
|
||
|
|
980e7d0358
|
||
|
|
d477388bae
|
||
|
|
795a5f5d70
|
||
|
|
c975811c7b
|
||
|
|
5a5ea54d48
|
||
|
|
fd07a01249
|
||
|
|
f6849c3590
|
||
|
|
ab20392497
|
||
|
|
347c3f34fe
|
||
|
|
3850d60a81
|
||
|
|
de1993b3e5
|
||
|
|
796de73034
|
||
|
|
978d81dd1b
|
||
|
|
df26e63ebf
|
||
|
|
bcbd6417f6
|
||
|
|
1a084f42db
|
||
|
|
1d1103eacb
|
||
|
|
b013300457
|
||
|
|
f898acf52b
|
||
|
|
2fc052617a
|
||
|
|
d9ff2e8286
|
||
|
|
f65d4faa78
|
||
|
|
d12bc8b656
|
||
|
|
7451bdd624
|
||
|
|
38c401869f
|
||
|
|
8be97f4f6c
|
||
|
|
50320dd197
|
||
|
|
a6a35de341
|
||
|
|
deb38ff87c
|
||
|
|
8b760dce84
|
||
|
|
97092a7563
|
||
|
|
f6e254ee01
|
||
|
|
f5c2a2fc32
|
||
|
|
9c64adbaf0
|
||
|
|
f730927e80
|
||
|
|
51eeb183ba
|
||
|
|
10d3e51b9a
|
||
|
|
a3411665e2
|
||
|
|
c0b58bbcf6
|
||
|
|
d808b37656
|
||
|
|
03397594eb
|
||
|
|
4306e53ad8
|
||
|
|
b68cbb3eb3
|
||
|
|
ce26759c9c
|
||
|
|
21524b58bf
|
||
|
|
f56ad45457
|
||
|
|
cbaaa317da
|
||
|
|
ae67e2622d
|
||
|
|
47cdb7029d
|
+3
-3
@@ -7,9 +7,6 @@
|
|||||||
[submodule "lib/nginx-dav-ext-module"]
|
[submodule "lib/nginx-dav-ext-module"]
|
||||||
path = lib/nginx-dav-ext-module
|
path = lib/nginx-dav-ext-module
|
||||||
url = https://github.com/arut/nginx-dav-ext-module.git
|
url = https://github.com/arut/nginx-dav-ext-module.git
|
||||||
[submodule "lib/ngx_brotli"]
|
|
||||||
path = lib/ngx_brotli
|
|
||||||
url = https://github.com/eustas/ngx_brotli.git
|
|
||||||
[submodule "lib/ngx_devel_kit"]
|
[submodule "lib/ngx_devel_kit"]
|
||||||
path = lib/ngx_devel_kit
|
path = lib/ngx_devel_kit
|
||||||
url = https://github.com/simplresty/ngx_devel_kit.git
|
url = https://github.com/simplresty/ngx_devel_kit.git
|
||||||
@@ -35,3 +32,6 @@
|
|||||||
[submodule "lib/nginx-http-flv-module"]
|
[submodule "lib/nginx-http-flv-module"]
|
||||||
path = lib/nginx-http-flv-module
|
path = lib/nginx-http-flv-module
|
||||||
url = https://github.com/winshining/nginx-http-flv-module.git
|
url = https://github.com/winshining/nginx-http-flv-module.git
|
||||||
|
[submodule "lib/ngx_brotli"]
|
||||||
|
path = lib/ngx_brotli
|
||||||
|
url = https://github.com/google/ngx_brotli.git
|
||||||
@@ -440,3 +440,15 @@ d2fd76709909767fc727a5b4affcf1dc9ca488a7 release-1.15.9
|
|||||||
0130ca3d58437b3c7c707cdddd813d530c68da9a release-1.15.12
|
0130ca3d58437b3c7c707cdddd813d530c68da9a release-1.15.12
|
||||||
054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0
|
054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0
|
||||||
7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1
|
7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1
|
||||||
|
2fc9f853a6b7cd29dc84e0af2ed3cf78e0da6ca8 release-1.17.2
|
||||||
|
ed4303aa1b31a9aad5440640c0840d9d0af45fed release-1.17.3
|
||||||
|
ce2ced3856909f36f8130c99eaa4dbdbae636ddc release-1.17.4
|
||||||
|
9af0dddbddb2c368bfedd2801bc100ffad01e19b release-1.17.5
|
||||||
|
de68d0d94320cbf033599c6f3ca37e5335c67fd7 release-1.17.6
|
||||||
|
e56295fe0ea76bf53b06bffa77a2d3a9a335cb8c release-1.17.7
|
||||||
|
fdacd273711ddf20f778c1fb91529ab53979a454 release-1.17.8
|
||||||
|
5e8d52bca714d4b85284ddb649d1ba4a3ca978a8 release-1.17.9
|
||||||
|
c44970de01474f6f3e01b0adea85ec1d03e3a5f2 release-1.17.10
|
||||||
|
cbe6ba650211541310618849168631ce0b788f35 release-1.19.0
|
||||||
|
062920e2f3bf871ef7a3d8496edec1b3065faf80 release-1.19.1
|
||||||
|
a7b46539f507e6c64efa0efda69ad60b6f4ffbce release-1.19.2
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
# Hakase-nginx
|
# Hakase-nginx
|
||||||
**My nginx build files.**
|
**My nginx build files.**
|
||||||
|
|
||||||
|
## This repository is no longer operational. Use an alternative such as tengine.
|
||||||
|
|
||||||
Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/)
|
Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/)
|
||||||
|
|
||||||
## Please install dependency library.
|
## Please install dependency library.
|
||||||
@@ -33,8 +35,8 @@ Example Web Server - [https://ssl.haka.se/](https://ssl.haka.se/)
|
|||||||
- Use the settings below to support older browsers. (TLS Protocol)
|
- Use the settings below to support older browsers. (TLS Protocol)
|
||||||
- ssl_protocols : TLSv1 TLSv1.1 TLSv1.2 TLSv1.3
|
- ssl_protocols : TLSv1 TLSv1.1 TLSv1.2 TLSv1.3
|
||||||
- ssl_ciphers : [TLS13+AESGCM+AES128|TLS13+CHACHA20]:TLS13+AESGCM+AES256:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES
|
- ssl_ciphers : [TLS13+AESGCM+AES128|TLS13+CHACHA20]:TLS13+AESGCM+AES256:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES
|
||||||
- TLS v1.3 (**final**)
|
- TLS v1.3
|
||||||
- Use OpenSSL-3.0.0-dev (**final**)
|
- Use OpenSSL-3.0.0-alpha3-dev
|
||||||
- Use OpenSSL equal preference patch ([BoringSSL](https://github.com/google/boringssl) & [buik](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1))
|
- Use OpenSSL equal preference patch ([BoringSSL](https://github.com/google/boringssl) & [buik](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1))
|
||||||
- My OpenSSL patch is [here](https://github.com/hakasenyang/openssl-patch).
|
- My OpenSSL patch is [here](https://github.com/hakasenyang/openssl-patch).
|
||||||
- Prefers ChaCha20 suites with clients that don't have AES-NI(AES hardware acceleration) (e.g., Android devices)
|
- Prefers ChaCha20 suites with clients that don't have AES-NI(AES hardware acceleration) (e.g., Android devices)
|
||||||
|
|||||||
@@ -102,9 +102,9 @@ if [ "$GEOIP2" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/ng
|
|||||||
if [ "$VTS" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-module-vts"; fi
|
if [ "$VTS" = 1 ]; then BUILD_MODULES="${BUILD_MODULES} --add-module=./lib/nginx-module-vts"; fi
|
||||||
|
|
||||||
auto/configure \
|
auto/configure \
|
||||||
--with-cc-opt="-DTCP_FASTOPEN=23 ${BUILD_BIT}${BUILD_LTO} ${TEMP_OPT} -g -O3 -march=native -fstack-protector-strong -fuse-ld=gold -fuse-linker-plugin --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-strict-aliasing -Wp,-D_FORTIFY_SOURCE=2 -gsplit-dwarf -DNGX_HTTP_HEADERS" \
|
--with-cc-opt="-Wno-stringop-truncation -DTCP_FASTOPEN=23 ${BUILD_BIT}${BUILD_LTO} ${TEMP_OPT} -g -O3 -march=native -fstack-protector-strong -fuse-ld=gold -fuse-linker-plugin --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-strict-aliasing -Wp,-D_FORTIFY_SOURCE=2 -gsplit-dwarf -DNGX_HTTP_HEADERS" \
|
||||||
--with-ld-opt="${BUILD_LD} ${BUILD_LTO}" \
|
--with-ld-opt="${BUILD_LD} ${BUILD_LTO}" \
|
||||||
--with-openssl-opt="enable-weak-ssl-ciphers no-ssl3-method -march=native -ljemalloc ${BUILD_OPENSSL_LTO}" \
|
--with-openssl-opt="no-cmp enable-weak-ssl-ciphers no-ssl3-method -march=native -ljemalloc ${BUILD_OPENSSL_LTO}" \
|
||||||
--builddir=objs --prefix=${NGX_PREFIX} \
|
--builddir=objs --prefix=${NGX_PREFIX} \
|
||||||
--conf-path=${NGX_CONF} \
|
--conf-path=${NGX_CONF} \
|
||||||
--pid-path=${NGX_PID} \
|
--pid-path=${NGX_PID} \
|
||||||
|
|||||||
@@ -943,6 +943,18 @@ ngx_feature_test="int i = FIONBIO; printf(\"%d\", i)"
|
|||||||
. auto/feature
|
. auto/feature
|
||||||
|
|
||||||
|
|
||||||
|
ngx_feature="ioctl(FIONREAD)"
|
||||||
|
ngx_feature_name="NGX_HAVE_FIONREAD"
|
||||||
|
ngx_feature_run=no
|
||||||
|
ngx_feature_incs="#include <sys/ioctl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
$NGX_INCLUDE_SYS_FILIO_H"
|
||||||
|
ngx_feature_path=
|
||||||
|
ngx_feature_libs=
|
||||||
|
ngx_feature_test="int i = FIONREAD; printf(\"%d\", i)"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
|
||||||
ngx_feature="struct tm.tm_gmtoff"
|
ngx_feature="struct tm.tm_gmtoff"
|
||||||
ngx_feature_name="NGX_HAVE_GMTOFF"
|
ngx_feature_name="NGX_HAVE_GMTOFF"
|
||||||
ngx_feature_run=no
|
ngx_feature_run=no
|
||||||
|
|||||||
+6
-1
@@ -31,7 +31,7 @@ http {
|
|||||||
variables_hash_max_size 2048;
|
variables_hash_max_size 2048;
|
||||||
|
|
||||||
# Cloudflare CDN
|
# Cloudflare CDN
|
||||||
set_real_ip_from 199.27.128.0/21;
|
# IPv4
|
||||||
set_real_ip_from 173.245.48.0/20;
|
set_real_ip_from 173.245.48.0/20;
|
||||||
set_real_ip_from 103.21.244.0/22;
|
set_real_ip_from 103.21.244.0/22;
|
||||||
set_real_ip_from 103.22.200.0/22;
|
set_real_ip_from 103.22.200.0/22;
|
||||||
@@ -44,11 +44,16 @@ http {
|
|||||||
set_real_ip_from 198.41.128.0/17;
|
set_real_ip_from 198.41.128.0/17;
|
||||||
set_real_ip_from 162.158.0.0/15;
|
set_real_ip_from 162.158.0.0/15;
|
||||||
set_real_ip_from 104.16.0.0/12;
|
set_real_ip_from 104.16.0.0/12;
|
||||||
|
set_real_ip_from 172.64.0.0/13;
|
||||||
|
set_real_ip_from 131.0.72.0/22;
|
||||||
|
# IPv6
|
||||||
#set_real_ip_from 2400:cb00::/32;
|
#set_real_ip_from 2400:cb00::/32;
|
||||||
#set_real_ip_from 2606:4700::/32;
|
#set_real_ip_from 2606:4700::/32;
|
||||||
#set_real_ip_from 2803:f800::/32;
|
#set_real_ip_from 2803:f800::/32;
|
||||||
#set_real_ip_from 2405:b500::/32;
|
#set_real_ip_from 2405:b500::/32;
|
||||||
#set_real_ip_from 2405:8100::/32;
|
#set_real_ip_from 2405:8100::/32;
|
||||||
|
#set_real_ip_from 2a06:98c0::/29;
|
||||||
|
#set_real_ip_from 2c0f:f248::/32;
|
||||||
real_ip_header CF-Connecting-IP;
|
real_ip_header CF-Connecting-IP;
|
||||||
|
|
||||||
# SSL Config
|
# SSL Config
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ BUILD_MTS="-j$(expr $(nproc) \+ 1)"
|
|||||||
|
|
||||||
### LTO build
|
### LTO build
|
||||||
### View : https://gcc.gnu.org/wiki/LinkTimeOptimization#Using_LTO
|
### View : https://gcc.gnu.org/wiki/LinkTimeOptimization#Using_LTO
|
||||||
LTO=1
|
LTO=0
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
### Select add module ###
|
### Select add module ###
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ syn keyword ngxDirective contained ancient_browser_value
|
|||||||
syn keyword ngxDirective contained api
|
syn keyword ngxDirective contained api
|
||||||
syn keyword ngxDirective contained auth_basic
|
syn keyword ngxDirective contained auth_basic
|
||||||
syn keyword ngxDirective contained auth_basic_user_file
|
syn keyword ngxDirective contained auth_basic_user_file
|
||||||
|
syn keyword ngxDirective contained auth_delay
|
||||||
syn keyword ngxDirective contained auth_http
|
syn keyword ngxDirective contained auth_http
|
||||||
syn keyword ngxDirective contained auth_http_header
|
syn keyword ngxDirective contained auth_http_header
|
||||||
syn keyword ngxDirective contained auth_http_pass_client_cert
|
syn keyword ngxDirective contained auth_http_pass_client_cert
|
||||||
@@ -332,6 +333,7 @@ syn keyword ngxDirective contained ip_hash
|
|||||||
syn keyword ngxDirective contained js_access
|
syn keyword ngxDirective contained js_access
|
||||||
syn keyword ngxDirective contained js_content
|
syn keyword ngxDirective contained js_content
|
||||||
syn keyword ngxDirective contained js_filter
|
syn keyword ngxDirective contained js_filter
|
||||||
|
syn keyword ngxDirective contained js_import
|
||||||
syn keyword ngxDirective contained js_include
|
syn keyword ngxDirective contained js_include
|
||||||
syn keyword ngxDirective contained js_path
|
syn keyword ngxDirective contained js_path
|
||||||
syn keyword ngxDirective contained js_preread
|
syn keyword ngxDirective contained js_preread
|
||||||
@@ -348,6 +350,7 @@ syn keyword ngxDirective contained large_client_header_buffers
|
|||||||
syn keyword ngxDirective contained least_conn
|
syn keyword ngxDirective contained least_conn
|
||||||
syn keyword ngxDirective contained least_time
|
syn keyword ngxDirective contained least_time
|
||||||
syn keyword ngxDirective contained limit_conn
|
syn keyword ngxDirective contained limit_conn
|
||||||
|
syn keyword ngxDirective contained limit_conn_dry_run
|
||||||
syn keyword ngxDirective contained limit_conn_log_level
|
syn keyword ngxDirective contained limit_conn_log_level
|
||||||
syn keyword ngxDirective contained limit_conn_status
|
syn keyword ngxDirective contained limit_conn_status
|
||||||
syn keyword ngxDirective contained limit_conn_zone
|
syn keyword ngxDirective contained limit_conn_zone
|
||||||
@@ -595,6 +598,9 @@ syn keyword ngxDirective contained ssl_early_data
|
|||||||
syn keyword ngxDirective contained ssl_ecdh_curve
|
syn keyword ngxDirective contained ssl_ecdh_curve
|
||||||
syn keyword ngxDirective contained ssl_engine
|
syn keyword ngxDirective contained ssl_engine
|
||||||
syn keyword ngxDirective contained ssl_handshake_timeout
|
syn keyword ngxDirective contained ssl_handshake_timeout
|
||||||
|
syn keyword ngxDirective contained ssl_ocsp
|
||||||
|
syn keyword ngxDirective contained ssl_ocsp_cache
|
||||||
|
syn keyword ngxDirective contained ssl_ocsp_responder
|
||||||
syn keyword ngxDirective contained ssl_password_file
|
syn keyword ngxDirective contained ssl_password_file
|
||||||
syn keyword ngxDirective contained ssl_prefer_server_ciphers
|
syn keyword ngxDirective contained ssl_prefer_server_ciphers
|
||||||
syn keyword ngxDirective contained ssl_preread
|
syn keyword ngxDirective contained ssl_preread
|
||||||
@@ -770,6 +776,7 @@ syn keyword ngxDirectiveThirdParty contained auth_gss_authorized_principal
|
|||||||
syn keyword ngxDirectiveThirdParty contained auth_gss_force_realm
|
syn keyword ngxDirectiveThirdParty contained auth_gss_force_realm
|
||||||
syn keyword ngxDirectiveThirdParty contained auth_gss_format_full
|
syn keyword ngxDirectiveThirdParty contained auth_gss_format_full
|
||||||
syn keyword ngxDirectiveThirdParty contained auth_gss_keytab
|
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_realm
|
||||||
syn keyword ngxDirectiveThirdParty contained auth_gss_service_name
|
syn keyword ngxDirectiveThirdParty contained auth_gss_service_name
|
||||||
|
|
||||||
@@ -791,8 +798,8 @@ syn keyword ngxDirectiveThirdParty contained auth_pam_set_pam_env
|
|||||||
|
|
||||||
" AJP protocol proxy
|
" AJP protocol proxy
|
||||||
" https://github.com/yaoweibin/nginx_ajp_module
|
" https://github.com/yaoweibin/nginx_ajp_module
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_buffer_size
|
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_buffers
|
syn keyword ngxDirectiveThirdParty contained ajp_buffers
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ajp_buffer_size
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_busy_buffers_size
|
syn keyword ngxDirectiveThirdParty contained ajp_busy_buffers_size
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_cache
|
syn keyword ngxDirectiveThirdParty contained ajp_cache
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_cache_key
|
syn keyword ngxDirectiveThirdParty contained ajp_cache_key
|
||||||
@@ -818,6 +825,7 @@ syn keyword ngxDirectiveThirdParty contained ajp_pass_header
|
|||||||
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_body
|
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_body
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_headers
|
syn keyword ngxDirectiveThirdParty contained ajp_pass_request_headers
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_read_timeout
|
syn keyword ngxDirectiveThirdParty contained ajp_read_timeout
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ajp_secret
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_send_lowat
|
syn keyword ngxDirectiveThirdParty contained ajp_send_lowat
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_send_timeout
|
syn keyword ngxDirectiveThirdParty contained ajp_send_timeout
|
||||||
syn keyword ngxDirectiveThirdParty contained ajp_store
|
syn keyword ngxDirectiveThirdParty contained ajp_store
|
||||||
@@ -854,8 +862,8 @@ syn keyword ngxDirectiveThirdParty contained content_handler_property
|
|||||||
syn keyword ngxDirectiveThirdParty contained content_handler_type
|
syn keyword ngxDirectiveThirdParty contained content_handler_type
|
||||||
syn keyword ngxDirectiveThirdParty contained handler_code
|
syn keyword ngxDirectiveThirdParty contained handler_code
|
||||||
syn keyword ngxDirectiveThirdParty contained handler_name
|
syn keyword ngxDirectiveThirdParty contained handler_name
|
||||||
syn keyword ngxDirectiveThirdParty contained handler_type
|
|
||||||
syn keyword ngxDirectiveThirdParty contained handlers_lazy_init
|
syn keyword ngxDirectiveThirdParty contained handlers_lazy_init
|
||||||
|
syn keyword ngxDirectiveThirdParty contained handler_type
|
||||||
syn keyword ngxDirectiveThirdParty contained header_filter_code
|
syn keyword ngxDirectiveThirdParty contained header_filter_code
|
||||||
syn keyword ngxDirectiveThirdParty contained header_filter_name
|
syn keyword ngxDirectiveThirdParty contained header_filter_name
|
||||||
syn keyword ngxDirectiveThirdParty contained header_filter_property
|
syn keyword ngxDirectiveThirdParty contained header_filter_property
|
||||||
@@ -871,6 +879,10 @@ syn keyword ngxDirectiveThirdParty contained jvm_options
|
|||||||
syn keyword ngxDirectiveThirdParty contained jvm_path
|
syn keyword ngxDirectiveThirdParty contained jvm_path
|
||||||
syn keyword ngxDirectiveThirdParty contained jvm_var
|
syn keyword ngxDirectiveThirdParty contained jvm_var
|
||||||
syn keyword ngxDirectiveThirdParty contained jvm_workers
|
syn keyword ngxDirectiveThirdParty contained jvm_workers
|
||||||
|
syn keyword ngxDirectiveThirdParty contained log_handler_code
|
||||||
|
syn keyword ngxDirectiveThirdParty contained log_handler_name
|
||||||
|
syn keyword ngxDirectiveThirdParty contained log_handler_property
|
||||||
|
syn keyword ngxDirectiveThirdParty contained log_handler_type
|
||||||
syn keyword ngxDirectiveThirdParty contained max_balanced_tcp_connections
|
syn keyword ngxDirectiveThirdParty contained max_balanced_tcp_connections
|
||||||
syn keyword ngxDirectiveThirdParty contained rewrite_handler_code
|
syn keyword ngxDirectiveThirdParty contained rewrite_handler_code
|
||||||
syn keyword ngxDirectiveThirdParty contained rewrite_handler_name
|
syn keyword ngxDirectiveThirdParty contained rewrite_handler_name
|
||||||
@@ -879,6 +891,7 @@ syn keyword ngxDirectiveThirdParty contained rewrite_handler_type
|
|||||||
syn keyword ngxDirectiveThirdParty contained shared_map
|
syn keyword ngxDirectiveThirdParty contained shared_map
|
||||||
syn keyword ngxDirectiveThirdParty contained write_page_size
|
syn keyword ngxDirectiveThirdParty contained write_page_size
|
||||||
|
|
||||||
|
|
||||||
" Certificate Transparency
|
" Certificate Transparency
|
||||||
" https://github.com/grahamedgecombe/nginx-ct
|
" https://github.com/grahamedgecombe/nginx-ct
|
||||||
syn keyword ngxDirectiveThirdParty contained ssl_ct
|
syn keyword ngxDirectiveThirdParty contained ssl_ct
|
||||||
@@ -942,6 +955,7 @@ syn keyword ngxDirectiveThirdParty contained fancyindex_hide_symlinks
|
|||||||
syn keyword ngxDirectiveThirdParty contained fancyindex_ignore
|
syn keyword ngxDirectiveThirdParty contained fancyindex_ignore
|
||||||
syn keyword ngxDirectiveThirdParty contained fancyindex_localtime
|
syn keyword ngxDirectiveThirdParty contained fancyindex_localtime
|
||||||
syn keyword ngxDirectiveThirdParty contained fancyindex_name_length
|
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_show_path
|
||||||
syn keyword ngxDirectiveThirdParty contained fancyindex_time_format
|
syn keyword ngxDirectiveThirdParty contained fancyindex_time_format
|
||||||
|
|
||||||
@@ -991,8 +1005,8 @@ syn keyword ngxDirectiveThirdParty contained nchan_benchmark_publisher_distribut
|
|||||||
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscriber_distribution
|
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscriber_distribution
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscribers_per_channel
|
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_subscribers_per_channel
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_time
|
syn keyword ngxDirectiveThirdParty contained nchan_benchmark_time
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string
|
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_channel_events_channel_id
|
syn keyword ngxDirectiveThirdParty contained nchan_channel_events_channel_id
|
||||||
|
syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_channel_group
|
syn keyword ngxDirectiveThirdParty contained nchan_channel_group
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting
|
syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_channel_id
|
syn keyword ngxDirectiveThirdParty contained nchan_channel_id
|
||||||
@@ -1000,6 +1014,10 @@ syn keyword ngxDirectiveThirdParty contained nchan_channel_id_split_delimiter
|
|||||||
syn keyword ngxDirectiveThirdParty contained nchan_channel_timeout
|
syn keyword ngxDirectiveThirdParty contained nchan_channel_timeout
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_deflate_message_for_websocket
|
syn keyword ngxDirectiveThirdParty contained nchan_deflate_message_for_websocket
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_event
|
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_event
|
||||||
|
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_comment
|
||||||
|
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_data
|
||||||
|
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_event
|
||||||
|
syn keyword ngxDirectiveThirdParty contained nchan_eventsource_ping_interval
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_group_location
|
syn keyword ngxDirectiveThirdParty contained nchan_group_location
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_group_max_channels
|
syn keyword ngxDirectiveThirdParty contained nchan_group_max_channels
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages
|
syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages
|
||||||
@@ -1047,10 +1065,10 @@ syn keyword ngxDirectiveThirdParty contained nchan_store_messages
|
|||||||
syn keyword ngxDirectiveThirdParty contained nchan_stub_status
|
syn keyword ngxDirectiveThirdParty contained nchan_stub_status
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_sub_channel_id
|
syn keyword ngxDirectiveThirdParty contained nchan_sub_channel_id
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_existing_channels_only
|
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_existing_channels_only
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
|
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber
|
syn keyword ngxDirectiveThirdParty contained nchan_subscriber
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_channel_id
|
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_channel_id
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_message_id
|
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_message_id
|
||||||
|
syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message
|
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator
|
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator
|
||||||
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id
|
syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id
|
||||||
@@ -1987,11 +2005,7 @@ syn keyword ngxDirectiveThirdParty contained concat_unique
|
|||||||
" update upstreams' config by restful interface
|
" update upstreams' config by restful interface
|
||||||
" https://github.com/yzprofile/ngx_http_dyups_module
|
" https://github.com/yzprofile/ngx_http_dyups_module
|
||||||
syn keyword ngxDirectiveThirdParty contained dyups_interface
|
syn keyword ngxDirectiveThirdParty contained dyups_interface
|
||||||
syn keyword ngxDirectiveThirdParty contained dyups_read_msg_log
|
|
||||||
syn keyword ngxDirectiveThirdParty contained dyups_read_msg_timeout
|
|
||||||
syn keyword ngxDirectiveThirdParty contained dyups_shm_zone_size
|
syn keyword ngxDirectiveThirdParty contained dyups_shm_zone_size
|
||||||
syn keyword ngxDirectiveThirdParty contained dyups_trylock
|
|
||||||
syn keyword ngxDirectiveThirdParty contained dyups_upstream_conf
|
|
||||||
|
|
||||||
" add given content to the end of the response according to the condition specified
|
" add given content to the end of the response according to the condition specified
|
||||||
" https://github.com/flygoast/ngx_http_footer_if_filter
|
" https://github.com/flygoast/ngx_http_footer_if_filter
|
||||||
@@ -2308,6 +2322,62 @@ syn keyword ngxDirectiveThirdParty contained user_agent
|
|||||||
" https://github.com/flygoast/ngx_http_upstream_ketama_chash
|
" https://github.com/flygoast/ngx_http_upstream_ketama_chash
|
||||||
syn keyword ngxDirectiveThirdParty contained ketama_chash
|
syn keyword ngxDirectiveThirdParty contained ketama_chash
|
||||||
|
|
||||||
|
" nginx-sticky-module-ng
|
||||||
|
" https://github.com/ayty-adrianomartins/nginx-sticky-module-ng
|
||||||
|
syn keyword ngxDirectiveThirdParty contained sticky_no_fallback
|
||||||
|
|
||||||
|
" dynamic linking and call the function of your application
|
||||||
|
" https://github.com/Taymindis/nginx-link-function
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_add_prop
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_add_req_header
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_ca_cert
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_call
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_download_link_lib
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_lib
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_shm_size
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ngx_link_func_subrequest
|
||||||
|
|
||||||
|
" purge content from FastCGI, proxy, SCGI and uWSGI caches
|
||||||
|
" https://github.com/torden/ngx_cache_purge
|
||||||
|
syn keyword ngxDirectiveThirdParty contained cache_purge_response_type
|
||||||
|
|
||||||
|
" set the flags "HttpOnly", "secure" and "SameSite" for cookies
|
||||||
|
" https://github.com/AirisX/nginx_cookie_flag_module
|
||||||
|
syn keyword ngxDirectiveThirdParty contained set_cookie_flag
|
||||||
|
|
||||||
|
" Embed websockify into Nginx (convert any tcp connection into websocket)
|
||||||
|
" https://github.com/tg123/websockify-nginx-module
|
||||||
|
syn keyword ngxDirectiveThirdParty contained websockify_buffer_size
|
||||||
|
syn keyword ngxDirectiveThirdParty contained websockify_connect_timeout
|
||||||
|
syn keyword ngxDirectiveThirdParty contained websockify_pass
|
||||||
|
syn keyword ngxDirectiveThirdParty contained websockify_read_timeout
|
||||||
|
syn keyword ngxDirectiveThirdParty contained websockify_send_timeout
|
||||||
|
|
||||||
|
" IP2Location Nginx
|
||||||
|
" https://github.com/ip2location/ip2location-nginx
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2location
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2location_access_type
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2location_proxy
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive
|
||||||
|
|
||||||
|
" IP2Proxy module for Nginx
|
||||||
|
" https://github.com/ip2location/ip2proxy-nginx
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_access_type
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_as
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_asn
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_city
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_country_long
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_country_short
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_database
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_domain
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_is_proxy
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_isp
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_last_seen
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_type
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_region
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_reverse_proxy
|
||||||
|
syn keyword ngxDirectiveThirdParty contained ip2proxy_usage_type
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
-7
@@ -1,5 +1,5 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" Copyright (C) 2010 Sergey A. Osokin
|
.\" Copyright (C) 2010, 2019 Sergey A. Osokin
|
||||||
.\" Copyright (C) Nginx, Inc.
|
.\" Copyright (C) Nginx, Inc.
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\"
|
.\"
|
||||||
.Dd June 16, 2015
|
.Dd December 5, 2019
|
||||||
.Dt NGINX 8
|
.Dt NGINX 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -42,7 +42,8 @@
|
|||||||
.Nm
|
.Nm
|
||||||
(pronounced
|
(pronounced
|
||||||
.Dq engine x )
|
.Dq engine x )
|
||||||
is an HTTP and reverse proxy server, as well as a mail proxy server.
|
is an HTTP and reverse proxy server, a mail proxy server, and a generic
|
||||||
|
TCP/UDP proxy server.
|
||||||
It is known for its high performance, stability, rich feature set, simple
|
It is known for its high performance, stability, rich feature set, simple
|
||||||
configuration, and low resource consumption.
|
configuration, and low resource consumption.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -82,15 +83,15 @@ The following table shows the corresponding system signals:
|
|||||||
.It Cm reload
|
.It Cm reload
|
||||||
.Dv SIGHUP
|
.Dv SIGHUP
|
||||||
.El
|
.El
|
||||||
|
.It Fl T
|
||||||
|
Same as
|
||||||
|
.Fl t ,
|
||||||
|
but additionally dump configuration files to standard output.
|
||||||
.It Fl t
|
.It Fl t
|
||||||
Do not run, just test the configuration file.
|
Do not run, just test the configuration file.
|
||||||
.Nm
|
.Nm
|
||||||
checks the configuration file syntax and then tries to open files
|
checks the configuration file syntax and then tries to open files
|
||||||
referenced in the configuration file.
|
referenced in the configuration file.
|
||||||
.It Fl T
|
|
||||||
Same as
|
|
||||||
.Fl t ,
|
|
||||||
but additionally dump configuration files to standard output.
|
|
||||||
.It Fl V
|
.It Fl V
|
||||||
Print the
|
Print the
|
||||||
.Nm
|
.Nm
|
||||||
|
|||||||
@@ -5,6 +5,800 @@
|
|||||||
<change_log title="nginx">
|
<change_log title="nginx">
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.19.2" date="2020-08-11">
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь nginx начинает закрывать keepalive-соединения,
|
||||||
|
не дожидаясь исчерпания всех свободных соединений,
|
||||||
|
а также пишет об этом предупреждение в лог ошибок.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now nginx starts closing keepalive connections
|
||||||
|
before all free worker connections are exhausted,
|
||||||
|
and logs a warning about this to the error log.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
оптимизация чтения тела запроса
|
||||||
|
при использовании chunked transfer encoding.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
optimization of client request body reading
|
||||||
|
when using chunked transfer encoding.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
утечки памяти при использовании директивы ssl_ocsp.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
memory leak if the "ssl_ocsp" directive was used.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в логах могли появляться сообщения "zero size buf in output",
|
||||||
|
если FastCGI-сервер возвращал некорректный ответ;
|
||||||
|
ошибка появилась в 1.19.1.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
"zero size buf in output" alerts might appear in logs
|
||||||
|
if a FastCGI server returned an incorrect response;
|
||||||
|
the bug had appeared in 1.19.1.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в рабочем процессе мог произойти segmentation fault,
|
||||||
|
если размеры large_client_header_buffers отличались
|
||||||
|
в разных виртуальных серверах.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur in a worker process
|
||||||
|
if different large_client_header_buffers sizes were used
|
||||||
|
in different virtual servers.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
SSL shutdown мог не работать.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
SSL shutdown might not work.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в логах могли появляться сообщения
|
||||||
|
"SSL_shutdown() failed (SSL: ... bad write retry)".
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
"SSL_shutdown() failed (SSL: ... bad write retry)"
|
||||||
|
messages might appear in logs.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в модуле ngx_http_slice_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the ngx_http_slice_module.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в модуле ngx_http_xslt_filter_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the ngx_http_xslt_filter_module.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.19.1" date="2020-07-07">
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
директивы lingering_close, lingering_time и lingering_timeout
|
||||||
|
теперь работают при использовании HTTP/2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "lingering_close", "lingering_time", and "lingering_timeout" directives
|
||||||
|
now work when using HTTP/2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь лишние данные, присланные бэкендом, всегда отбрасываются.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now extra data sent by a backend are always discarded.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь при получении слишком короткого ответа от FastCGI-сервера
|
||||||
|
nginx пытается отправить клиенту доступную часть ответа,
|
||||||
|
после чего закрывает соединение с клиентом.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now after receiving a too short response from a FastCGI server
|
||||||
|
nginx tries to send the available part of the response to the client,
|
||||||
|
and then closes the client connection.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь при получении ответа некорректной длины от gRPC-бэкенда
|
||||||
|
nginx прекращает обработку ответа с ошибкой.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now after receiving a response with incorrect length from a gRPC backend
|
||||||
|
nginx stops response processing with an error.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
параметр min_free в директивах proxy_cache_path, fastcgi_cache_path,
|
||||||
|
scgi_cache_path и uwsgi_cache_path.<br/>
|
||||||
|
Спасибо Adam Bambuch.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "min_free" parameter of the "proxy_cache_path", "fastcgi_cache_path",
|
||||||
|
"scgi_cache_path", and "uwsgi_cache_path" directives.<br/>
|
||||||
|
Thanks to Adam Bambuch.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx не удалял unix domain listen-сокеты
|
||||||
|
при плавном завершении по сигналу SIGQUIT.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx did not delete unix domain listen sockets
|
||||||
|
during graceful shutdown on the SIGQUIT signal.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
UDP-пакеты нулевого размера не проксировались.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
zero length UDP datagrams were not proxied.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
проксирование на uwsgi-бэкенды с использованием SSL могло не работать.<br/>
|
||||||
|
Спасибо Guanzhong Chen.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
proxying to uwsgi backends using SSL might not work.<br/>
|
||||||
|
Thanks to Guanzhong Chen.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в обработке ошибок при использовании директивы ssl_ocsp.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in error handling when using the "ssl_ocsp" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании файловых систем XFS и NFS
|
||||||
|
размер кэша на диске мог считаться некорректно.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
on XFS and NFS file systems
|
||||||
|
disk cache size might be calculated incorrectly.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
если сервер memcached возвращал некорректный ответ,
|
||||||
|
в логах могли появляться сообщения "negative size buf in writer".
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
"negative size buf in writer" alerts might appear in logs
|
||||||
|
if a memcached server returned a malformed response.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.19.0" date="2020-05-26">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
проверка клиентских сертификатов с помощью OCSP.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
client certificate validation with OCSP.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при работе с gRPC-бэкендами
|
||||||
|
могли возникать ошибки "upstream sent frame for closed stream".
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
"upstream sent frame for closed stream" errors might occur
|
||||||
|
when working with gRPC backends.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
OCSP stapling мог не работать,
|
||||||
|
если не была указана директива resolver.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
OCSP stapling might not work
|
||||||
|
if the "resolver" directive was not specified.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
соединения с некорректным HTTP/2 preface не логгировались.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
connections with incorrect HTTP/2 preface were not logged.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.10" date="2020-04-14">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
директива auth_delay.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "auth_delay" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.9" date="2020-03-03">
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь nginx не разрешает
|
||||||
|
несколько строк "Host" в заголовке запроса.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now nginx does not allow
|
||||||
|
several "Host" request header lines.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx игнорировал дополнительные
|
||||||
|
строки "Transfer-Encoding" в заголовке запроса.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx ignored additional
|
||||||
|
"Transfer-Encoding" request header lines.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
утечки сокетов при использовании HTTP/2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
socket leak when using HTTP/2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в рабочем процессе мог произойти segmentation fault,
|
||||||
|
если использовался OCSP stapling.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur in a worker process
|
||||||
|
if OCSP stapling was used.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в модуле ngx_http_mp4_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the ngx_http_mp4_module.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при перенаправлении ошибок с кодом 494 с помощью директивы error_page
|
||||||
|
nginx возвращал ответ с кодом 494 вместо 400.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx used status code 494 instead of 400
|
||||||
|
if errors with code 494 were redirected with the "error_page" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
утечки сокетов при использовании подзапросов в модуле njs и директивы aio.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
socket leak when using subrequests in the njs module and the "aio" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.8" date="2020-01-21">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
директива grpc_pass поддерживает переменные.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
variables support in the "grpc_pass" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при обработке pipelined-запросов по SSL-соединению мог произойти таймаут;
|
||||||
|
ошибка появилась в 1.17.5.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a timeout might occur while handling pipelined requests in an SSL connection;
|
||||||
|
the bug had appeared in 1.17.5.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в директиве debug_points при использовании HTTP/2.<br/>
|
||||||
|
Спасибо Даниилу Бондареву.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the "debug_points" directive when using HTTP/2.<br/>
|
||||||
|
Thanks to Daniil Bondarev.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.7" date="2019-12-24">
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
на старте или во время переконфигурации мог произойти segmentation fault,
|
||||||
|
если в конфигурации использовалась
|
||||||
|
директива rewrite с пустой строкой замены.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur on start or during reconfiguration
|
||||||
|
if the "rewrite" directive with an empty replacement string
|
||||||
|
was used in the configuration.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в рабочем процессе мог произойти segmentation fault,
|
||||||
|
если директива break использовалась совместно с директивой alias
|
||||||
|
или директивой proxy_pass с URI.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur in a worker process
|
||||||
|
if the "break" directive was used with the "alias" directive
|
||||||
|
or with the "proxy_pass" directive with a URI.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
строка Location заголовка ответа могла содержать мусор,
|
||||||
|
если URI запроса был изменён на URI, содержащий нулевой символ.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "Location" response header line might contain garbage
|
||||||
|
if the request URI was rewritten to the one containing a null character.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при возврате перенаправлений с помощью директивы error_page
|
||||||
|
запросы с телом обрабатывались некорректно;
|
||||||
|
ошибка появилась в 0.7.12.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
requests with bodies were handled incorrectly
|
||||||
|
when returning redirections with the "error_page" directive;
|
||||||
|
the bug had appeared in 0.7.12.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
утечки сокетов при использовании HTTP/2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
socket leak when using HTTP/2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при обработке pipelined-запросов по SSL-соединению мог произойти таймаут;
|
||||||
|
ошибка появилась в 1.17.5.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a timeout might occur while handling pipelined requests in an SSL connection;
|
||||||
|
the bug had appeared in 1.17.5.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в модуле ngx_http_dav_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the ngx_http_dav_module.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.6" date="2019-11-19">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
переменные $proxy_protocol_server_addr и $proxy_protocol_server_port.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the $proxy_protocol_server_addr and $proxy_protocol_server_port variables.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
директива limit_conn_dry_run.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "limit_conn_dry_run" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
переменные $limit_req_status и $limit_conn_status.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the $limit_req_status and $limit_conn_status variables.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.5" date="2019-10-22">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь nginx использует вызов ioctl(FIONREAD), если он доступен,
|
||||||
|
чтобы избежать чтения из быстрого соединения в течение долгого времени.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now nginx uses ioctl(FIONREAD), if available,
|
||||||
|
to avoid reading from a fast connection for a long time.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
неполные закодированные символы в конце URI запроса игнорировались.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
incomplete escaped characters at the end of the request URI were ignored.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
"/." и "/.." в конце URI запроса не нормализовывались.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
"/." and "/.." at the end of the request URI were not normalized.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в директиве merge_slashes.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the "merge_slashes" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в директиве ignore_invalid_headers.<br/>
|
||||||
|
Спасибо Alan Kemp.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the "ignore_invalid_headers" directive.<br/>
|
||||||
|
Thanks to Alan Kemp.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx не собирался с MinGW-w64 gcc 8.1 и новее.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx could not be built with MinGW-w64 gcc 8.1 or newer.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.4" date="2019-09-24">
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
улучшено детектирование некорректного поведения клиентов в HTTP/2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
better detection of incorrect client behavior in HTTP/2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
в обработке непрочитанного тела запроса
|
||||||
|
при возврате ошибок в HTTP/2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in handling of not fully read client request body
|
||||||
|
when returning errors in HTTP/2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
директива worker_shutdown_timeout могла не работать
|
||||||
|
при использовании HTTP/2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "worker_shutdown_timeout" directive might not work
|
||||||
|
when using HTTP/2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании HTTP/2 и директивы proxy_request_buffering
|
||||||
|
в рабочем процессе мог произойти segmentation fault.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur in a worker process
|
||||||
|
when using HTTP/2 and the "proxy_request_buffering" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
на Windows при использовании SSL
|
||||||
|
уровень записи в лог ошибки ECONNABORTED был "crit" вместо "error".
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the ECONNABORTED error log level was "crit" instead of "error"
|
||||||
|
on Windows when using SSL.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx игнорировал лишние данные при использовании chunked transfer encoding.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx ignored extra data when using chunked transfer encoding.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
если использовалась директива return и
|
||||||
|
при чтении тела запроса возникала ошибка,
|
||||||
|
nginx всегда возвращал ошибку 500.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx always returned the 500 error
|
||||||
|
if the "return" directive was used
|
||||||
|
and an error occurred during reading client request body.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в обработке ошибок выделения памяти.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in memory allocation error handling.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.3" date="2019-08-13">
|
||||||
|
|
||||||
|
<change type="security">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании HTTP/2 клиент мог вызвать
|
||||||
|
чрезмерное потребление памяти и ресурсов процессора
|
||||||
|
(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516).
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
when using HTTP/2 a client might cause
|
||||||
|
excessive memory consumption and CPU usage
|
||||||
|
(CVE-2019-9511, CVE-2019-9513, CVE-2019-9516).
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании сжатия в логах могли появляться сообщения "zero size buf";
|
||||||
|
ошибка появилась в 1.17.2.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
"zero size buf" alerts might appear in logs when using gzipping;
|
||||||
|
the bug had appeared in 1.17.2.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании директивы resolver в SMTP прокси-сервере
|
||||||
|
в рабочем процессе мог произойти segmentation fault.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur in a worker process
|
||||||
|
if the "resolver" directive was used in SMTP proxy.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.17.2" date="2019-07-23">
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
минимальная поддерживаемая версия zlib—1.2.0.4.<br/>
|
||||||
|
Спасибо Илье Леошкевичу.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
minimum supported zlib version is 1.2.0.4.<br/>
|
||||||
|
Thanks to Ilya Leoshkevich.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
метод $r->internal_redirect() встроенного перла
|
||||||
|
теперь ожидает закодированный URI.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the $r->internal_redirect() embedded perl method
|
||||||
|
now expects escaped URIs.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь с помощью метода $r->internal_redirect() встроенного перла
|
||||||
|
можно перейти в именованный location.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
it is now possible to switch to a named location
|
||||||
|
using the $r->internal_redirect() embedded perl method.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в обработке ошибок во встроенном перле.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in error handling in embedded perl.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
на старте или во время переконфигурации мог произойти segmentation fault,
|
||||||
|
если в конфигурации использовалось значение hash bucket size больше 64 килобайт.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
a segmentation fault might occur on start or during reconfiguration
|
||||||
|
if hash bucket size larger than 64 kilobytes was used in the configuration.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании методов обработки соединений select, poll и /dev/poll
|
||||||
|
nginx мог нагружать процессор во время небуферизованного проксирования
|
||||||
|
и при проксировании WebSocket-соединений.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx might hog CPU during unbuffered proxying
|
||||||
|
and when proxying WebSocket connections
|
||||||
|
if the select, poll, or /dev/poll methods were used.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в модуле ngx_http_xslt_filter_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the ngx_http_xslt_filter_module.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в модуле ngx_http_ssi_filter_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the ngx_http_ssi_filter_module.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
<changes ver="1.17.1" date="2019-06-25">
|
<changes ver="1.17.1" date="2019-06-25">
|
||||||
|
|
||||||
<change type="feature">
|
<change type="feature">
|
||||||
|
|||||||
Submodule lib/headers-more-nginx-module updated: ab40f34464...d6d7ebab3c
+1
-1
Submodule lib/naxsi updated: d3cbf8a5b0...312f912797
Submodule lib/nginx-http-flv-module updated: 3f73b4d0f0...13be96d72d
+1
-1
Submodule lib/ngx-fancyindex updated: fa13aef31b...56934db14c
+1
-1
Submodule lib/ngx_brotli updated: 8104036af9...25f86f0bac
Submodule lib/ngx_http_geoip2_module updated: a28ceffdef...1cabd8a1f6
+1
-1
Submodule lib/openssl updated: 2e57f602ae...e85ee33eee
+1
-1
Submodule lib/zlib updated: af9ef2e94c...ab50ae879a
+2
-2
@@ -6,9 +6,9 @@ TEMP = tmp
|
|||||||
|
|
||||||
CC = cl
|
CC = cl
|
||||||
OBJS = objs.msvc8
|
OBJS = objs.msvc8
|
||||||
OPENSSL = openssl-1.1.1c
|
OPENSSL = openssl-1.1.1g
|
||||||
ZLIB = zlib-1.2.11
|
ZLIB = zlib-1.2.11
|
||||||
PCRE = pcre-8.43
|
PCRE = pcre-8.44
|
||||||
|
|
||||||
|
|
||||||
release: export
|
release: export
|
||||||
|
|||||||
@@ -492,6 +492,7 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle)
|
|||||||
ngx_memzero(ls, sizeof(ngx_listening_t));
|
ngx_memzero(ls, sizeof(ngx_listening_t));
|
||||||
|
|
||||||
ls->fd = (ngx_socket_t) s;
|
ls->fd = (ngx_socket_t) s;
|
||||||
|
ls->inherited = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@
|
|||||||
#define _NGINX_H_INCLUDED_
|
#define _NGINX_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
#define nginx_version 1017002
|
#define nginx_version 1019003
|
||||||
#define NGINX_VERSION "1.17.2"
|
#define NGINX_VERSION "1.19.3"
|
||||||
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
|
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
|
||||||
|
|
||||||
#ifndef NGINX_SERVER
|
#ifndef NGINX_SERVER
|
||||||
|
|||||||
+10
-10
@@ -125,20 +125,20 @@ typedef struct {
|
|||||||
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR
|
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR
|
||||||
|
|
||||||
|
|
||||||
#define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap)
|
#define ngx_buf_in_memory(b) ((b)->temporary || (b)->memory || (b)->mmap)
|
||||||
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file)
|
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !(b)->in_file)
|
||||||
|
|
||||||
#define ngx_buf_special(b) \
|
#define ngx_buf_special(b) \
|
||||||
((b->flush || b->last_buf || b->sync) \
|
(((b)->flush || (b)->last_buf || (b)->sync) \
|
||||||
&& !ngx_buf_in_memory(b) && !b->in_file)
|
&& !ngx_buf_in_memory(b) && !(b)->in_file)
|
||||||
|
|
||||||
#define ngx_buf_sync_only(b) \
|
#define ngx_buf_sync_only(b) \
|
||||||
(b->sync \
|
((b)->sync && !ngx_buf_in_memory(b) \
|
||||||
&& !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)
|
&& !(b)->in_file && !(b)->flush && !(b)->last_buf)
|
||||||
|
|
||||||
#define ngx_buf_size(b) \
|
#define ngx_buf_size(b) \
|
||||||
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \
|
(ngx_buf_in_memory(b) ? (off_t) ((b)->last - (b)->pos): \
|
||||||
(b->file_last - b->file_pos))
|
((b)->file_last - (b)->file_pos))
|
||||||
|
|
||||||
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
|
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
|
||||||
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
|
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
|
||||||
@@ -149,8 +149,8 @@ ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
|
|||||||
|
|
||||||
ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
|
ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
|
||||||
#define ngx_free_chain(pool, cl) \
|
#define ngx_free_chain(pool, cl) \
|
||||||
cl->next = pool->chain; \
|
(cl)->next = (pool)->chain; \
|
||||||
pool->chain = cl
|
(pool)->chain = (cl)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1070,7 +1070,8 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
|
|||||||
|
|
||||||
if (ls[i].sockaddr->sa_family == AF_UNIX
|
if (ls[i].sockaddr->sa_family == AF_UNIX
|
||||||
&& ngx_process <= NGX_PROCESS_MASTER
|
&& ngx_process <= NGX_PROCESS_MASTER
|
||||||
&& ngx_new_binary == 0)
|
&& ngx_new_binary == 0
|
||||||
|
&& (!ls[i].inherited || ngx_getppid() != ngx_parent))
|
||||||
{
|
{
|
||||||
u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
|
u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
|
||||||
|
|
||||||
@@ -1106,12 +1107,9 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = ngx_cycle->free_connections;
|
|
||||||
|
|
||||||
if (c == NULL) {
|
|
||||||
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
|
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
|
||||||
|
|
||||||
c = ngx_cycle->free_connections;
|
c = ngx_cycle->free_connections;
|
||||||
}
|
|
||||||
|
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
ngx_log_error(NGX_LOG_ALERT, log, 0,
|
ngx_log_error(NGX_LOG_ALERT, log, 0,
|
||||||
@@ -1297,6 +1295,21 @@ ngx_drain_connections(ngx_cycle_t *cycle)
|
|||||||
ngx_queue_t *q;
|
ngx_queue_t *q;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
|
|
||||||
|
if (cycle->free_connection_n > cycle->connection_n / 16
|
||||||
|
|| cycle->reusable_connections_n == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycle->connections_reuse_time != ngx_time()) {
|
||||||
|
cycle->connections_reuse_time = ngx_time();
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
|
||||||
|
"%ui worker_connections are not enough, "
|
||||||
|
"reusing connections",
|
||||||
|
cycle->connection_n);
|
||||||
|
}
|
||||||
|
|
||||||
n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
|
n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
|||||||
@@ -147,8 +147,7 @@ struct ngx_connection_s {
|
|||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
ngx_str_t addr_text;
|
ngx_str_t addr_text;
|
||||||
|
|
||||||
ngx_str_t proxy_protocol_addr;
|
ngx_proxy_protocol_t *proxy_protocol;
|
||||||
in_port_t proxy_protocol_port;
|
|
||||||
|
|
||||||
#if (NGX_SSL || NGX_COMPAT)
|
#if (NGX_SSL || NGX_COMPAT)
|
||||||
ngx_ssl_connection_t *ssl;
|
ngx_ssl_connection_t *ssl;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ typedef struct ngx_event_aio_s ngx_event_aio_t;
|
|||||||
typedef struct ngx_connection_s ngx_connection_t;
|
typedef struct ngx_connection_s ngx_connection_t;
|
||||||
typedef struct ngx_thread_task_s ngx_thread_task_t;
|
typedef struct ngx_thread_task_s ngx_thread_task_t;
|
||||||
typedef struct ngx_ssl_s ngx_ssl_t;
|
typedef struct ngx_ssl_s ngx_ssl_t;
|
||||||
|
typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t;
|
||||||
typedef struct ngx_ssl_connection_s ngx_ssl_connection_t;
|
typedef struct ngx_ssl_connection_s ngx_ssl_connection_t;
|
||||||
typedef struct ngx_udp_connection_s ngx_udp_connection_t;
|
typedef struct ngx_udp_connection_s ngx_udp_connection_t;
|
||||||
|
|
||||||
|
|||||||
@@ -520,6 +520,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
|
|||||||
== NGX_OK)
|
== NGX_OK)
|
||||||
{
|
{
|
||||||
nls[n].fd = ls[i].fd;
|
nls[n].fd = ls[i].fd;
|
||||||
|
nls[n].inherited = ls[i].inherited;
|
||||||
nls[n].previous = &ls[i];
|
nls[n].previous = &ls[i];
|
||||||
ls[i].remain = 1;
|
ls[i].remain = 1;
|
||||||
|
|
||||||
@@ -1008,6 +1009,7 @@ ngx_int_t
|
|||||||
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
|
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
ngx_int_t rc;
|
||||||
ngx_uint_t create;
|
ngx_uint_t create;
|
||||||
ngx_file_t file;
|
ngx_file_t file;
|
||||||
u_char pid[NGX_INT64_LEN + 2];
|
u_char pid[NGX_INT64_LEN + 2];
|
||||||
@@ -1032,11 +1034,13 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = NGX_OK;
|
||||||
|
|
||||||
if (!ngx_test_config) {
|
if (!ngx_test_config) {
|
||||||
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
|
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
|
||||||
|
|
||||||
if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
|
if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
|
||||||
return NGX_ERROR;
|
rc = NGX_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,7 +1049,7 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
|
|||||||
ngx_close_file_n " \"%s\" failed", file.name.data);
|
ngx_close_file_n " \"%s\" failed", file.name.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ struct ngx_cycle_s {
|
|||||||
|
|
||||||
ngx_queue_t reusable_connections_queue;
|
ngx_queue_t reusable_connections_queue;
|
||||||
ngx_uint_t reusable_connections_n;
|
ngx_uint_t reusable_connections_n;
|
||||||
|
time_t connections_reuse_time;
|
||||||
|
|
||||||
ngx_array_t listening;
|
ngx_array_t listening;
|
||||||
ngx_array_t paths;
|
ngx_array_t paths;
|
||||||
|
|||||||
+151
-72
@@ -40,6 +40,10 @@ typedef struct {
|
|||||||
} ngx_proxy_protocol_inet6_addrs_t;
|
} ngx_proxy_protocol_inet6_addrs_t;
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
|
||||||
|
u_char *last, ngx_str_t *addr);
|
||||||
|
static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
|
||||||
|
in_port_t *port, u_char sep);
|
||||||
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
|
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
|
||||||
u_char *last);
|
u_char *last);
|
||||||
|
|
||||||
@@ -48,8 +52,8 @@ u_char *
|
|||||||
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
u_char ch, *p, *addr, *port;
|
u_char *p;
|
||||||
ngx_int_t n;
|
ngx_proxy_protocol_t *pp;
|
||||||
|
|
||||||
static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
|
static const u_char signature[] = "\r\n\r\n\0\r\nQUIT\n";
|
||||||
|
|
||||||
@@ -83,73 +87,47 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p += 5;
|
p += 5;
|
||||||
addr = p;
|
|
||||||
|
|
||||||
for ( ;; ) {
|
pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
|
||||||
if (p == last) {
|
if (pp == NULL) {
|
||||||
goto invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
ch = *p++;
|
|
||||||
|
|
||||||
if (ch == ' ') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch != ':' && ch != '.'
|
|
||||||
&& (ch < 'a' || ch > 'f')
|
|
||||||
&& (ch < 'A' || ch > 'F')
|
|
||||||
&& (ch < '0' || ch > '9'))
|
|
||||||
{
|
|
||||||
goto invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len = p - addr - 1;
|
|
||||||
c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
|
|
||||||
|
|
||||||
if (c->proxy_protocol_addr.data == NULL) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
|
p = ngx_proxy_protocol_read_addr(c, p, last, &pp->src_addr);
|
||||||
c->proxy_protocol_addr.len = len;
|
if (p == NULL) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_proxy_protocol_read_addr(c, p, last, &pp->dst_addr);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_proxy_protocol_read_port(p, last, &pp->src_port, ' ');
|
||||||
|
if (p == NULL) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_proxy_protocol_read_port(p, last, &pp->dst_port, CR);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
for ( ;; ) {
|
|
||||||
if (p == last) {
|
if (p == last) {
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p++ == ' ') {
|
if (*p++ != LF) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
port = p;
|
|
||||||
|
|
||||||
for ( ;; ) {
|
|
||||||
if (p == last) {
|
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p++ == ' ') {
|
ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
break;
|
"PROXY protocol src: %V %d, dst: %V %d",
|
||||||
}
|
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
|
||||||
}
|
|
||||||
|
|
||||||
len = p - port - 1;
|
c->proxy_protocol = pp;
|
||||||
|
|
||||||
n = ngx_atoi(port, len);
|
return p;
|
||||||
|
|
||||||
if (n < 0 || n > 65535) {
|
|
||||||
goto invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->proxy_protocol_port = (in_port_t) n;
|
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
|
|
||||||
"PROXY protocol address: %V %d", &c->proxy_protocol_addr,
|
|
||||||
c->proxy_protocol_port);
|
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
|
|
||||||
@@ -168,6 +146,82 @@ invalid:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *
|
||||||
|
ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last,
|
||||||
|
ngx_str_t *addr)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
u_char ch, *pos;
|
||||||
|
|
||||||
|
pos = p;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
if (p == last) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = *p++;
|
||||||
|
|
||||||
|
if (ch == ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch != ':' && ch != '.'
|
||||||
|
&& (ch < 'a' || ch > 'f')
|
||||||
|
&& (ch < 'A' || ch > 'F')
|
||||||
|
&& (ch < '0' || ch > '9'))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len = p - pos - 1;
|
||||||
|
|
||||||
|
addr->data = ngx_pnalloc(c->pool, len);
|
||||||
|
if (addr->data == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(addr->data, pos, len);
|
||||||
|
addr->len = len;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *
|
||||||
|
ngx_proxy_protocol_read_port(u_char *p, u_char *last, in_port_t *port,
|
||||||
|
u_char sep)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
u_char *pos;
|
||||||
|
ngx_int_t n;
|
||||||
|
|
||||||
|
pos = p;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
if (p == last) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p++ == sep) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len = p - pos - 1;
|
||||||
|
|
||||||
|
n = ngx_atoi(pos, len);
|
||||||
|
if (n < 0 || n > 65535) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*port = (in_port_t) n;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u_char *
|
u_char *
|
||||||
ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
|
ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
|
||||||
{
|
{
|
||||||
@@ -219,7 +273,8 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
size_t len;
|
size_t len;
|
||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
ngx_uint_t version, command, family, transport;
|
ngx_uint_t version, command, family, transport;
|
||||||
ngx_sockaddr_t sockaddr;
|
ngx_sockaddr_t src_sockaddr, dst_sockaddr;
|
||||||
|
ngx_proxy_protocol_t *pp;
|
||||||
ngx_proxy_protocol_header_t *header;
|
ngx_proxy_protocol_header_t *header;
|
||||||
ngx_proxy_protocol_inet_addrs_t *in;
|
ngx_proxy_protocol_inet_addrs_t *in;
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
@@ -266,6 +321,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp = ngx_pcalloc(c->pool, sizeof(ngx_proxy_protocol_t));
|
||||||
|
if (pp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
family = header->family_transport >> 4;
|
family = header->family_transport >> 4;
|
||||||
|
|
||||||
switch (family) {
|
switch (family) {
|
||||||
@@ -278,11 +338,16 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
|
|
||||||
in = (ngx_proxy_protocol_inet_addrs_t *) buf;
|
in = (ngx_proxy_protocol_inet_addrs_t *) buf;
|
||||||
|
|
||||||
sockaddr.sockaddr_in.sin_family = AF_INET;
|
src_sockaddr.sockaddr_in.sin_family = AF_INET;
|
||||||
sockaddr.sockaddr_in.sin_port = 0;
|
src_sockaddr.sockaddr_in.sin_port = 0;
|
||||||
memcpy(&sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
|
memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
|
||||||
|
|
||||||
c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in->src_port);
|
dst_sockaddr.sockaddr_in.sin_family = AF_INET;
|
||||||
|
dst_sockaddr.sockaddr_in.sin_port = 0;
|
||||||
|
memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
|
||||||
|
|
||||||
|
pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
|
||||||
|
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
|
||||||
|
|
||||||
socklen = sizeof(struct sockaddr_in);
|
socklen = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
@@ -300,11 +365,16 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
|
|
||||||
in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
|
in6 = (ngx_proxy_protocol_inet6_addrs_t *) buf;
|
||||||
|
|
||||||
sockaddr.sockaddr_in6.sin6_family = AF_INET6;
|
src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
|
||||||
sockaddr.sockaddr_in6.sin6_port = 0;
|
src_sockaddr.sockaddr_in6.sin6_port = 0;
|
||||||
memcpy(&sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
|
memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
|
||||||
|
|
||||||
c->proxy_protocol_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
|
dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
|
||||||
|
dst_sockaddr.sockaddr_in6.sin6_port = 0;
|
||||||
|
memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
|
||||||
|
|
||||||
|
pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
|
||||||
|
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
|
||||||
|
|
||||||
socklen = sizeof(struct sockaddr_in6);
|
socklen = sizeof(struct sockaddr_in6);
|
||||||
|
|
||||||
@@ -321,23 +391,32 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
|||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
|
pp->src_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
|
||||||
if (c->proxy_protocol_addr.data == NULL) {
|
if (pp->src_addr.data == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->proxy_protocol_addr.len = ngx_sock_ntop(&sockaddr.sockaddr, socklen,
|
pp->src_addr.len = ngx_sock_ntop(&src_sockaddr.sockaddr, socklen,
|
||||||
c->proxy_protocol_addr.data,
|
pp->src_addr.data, NGX_SOCKADDR_STRLEN, 0);
|
||||||
NGX_SOCKADDR_STRLEN, 0);
|
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
|
pp->dst_addr.data = ngx_pnalloc(c->pool, NGX_SOCKADDR_STRLEN);
|
||||||
"PROXY protocol v2 address: %V %d", &c->proxy_protocol_addr,
|
if (pp->dst_addr.data == NULL) {
|
||||||
c->proxy_protocol_port);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp->dst_addr.len = ngx_sock_ntop(&dst_sockaddr.sockaddr, socklen,
|
||||||
|
pp->dst_addr.data, NGX_SOCKADDR_STRLEN, 0);
|
||||||
|
|
||||||
|
ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
|
"PROXY protocol v2 src: %V %d, dst: %V %d",
|
||||||
|
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
|
||||||
|
|
||||||
if (buf < end) {
|
if (buf < end) {
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
|
||||||
"PROXY protocol v2 %z bytes of tlv ignored", end - buf);
|
"PROXY protocol v2 %z bytes of tlv ignored", end - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->proxy_protocol = pp;
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,14 @@
|
|||||||
#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
|
#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
|
||||||
|
|
||||||
|
|
||||||
|
struct ngx_proxy_protocol_s {
|
||||||
|
ngx_str_t src_addr;
|
||||||
|
ngx_str_t dst_addr;
|
||||||
|
in_port_t src_port;
|
||||||
|
in_port_t dst_port;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
|
u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
|
||||||
u_char *last);
|
u_char *last);
|
||||||
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
|
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
|
||||||
|
|||||||
@@ -174,13 +174,8 @@ ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
subst = ngx_rbtree_min(node->right, sentinel);
|
subst = ngx_rbtree_min(node->right, sentinel);
|
||||||
|
|
||||||
if (subst->left != sentinel) {
|
|
||||||
temp = subst->left;
|
|
||||||
} else {
|
|
||||||
temp = subst->right;
|
temp = subst->right;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (subst == *root) {
|
if (subst == *root) {
|
||||||
*root = temp;
|
*root = temp;
|
||||||
|
|||||||
@@ -972,7 +972,8 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
|||||||
|
|
||||||
name = ngx_resolver_dup(r, rn->name, rn->nlen);
|
name = ngx_resolver_dup(r, rn->name, rn->nlen);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
goto failed;
|
ngx_resolver_free(r, ctx);
|
||||||
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->name.len = rn->nlen;
|
ctx->name.len = rn->nlen;
|
||||||
|
|||||||
@@ -495,6 +495,7 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
|||||||
|
|
||||||
if ((revents & POLLIN) && rev->active) {
|
if ((revents & POLLIN) && rev->active) {
|
||||||
rev->ready = 1;
|
rev->ready = 1;
|
||||||
|
rev->available = -1;
|
||||||
|
|
||||||
if (flags & NGX_POST_EVENTS) {
|
if (flags & NGX_POST_EVENTS) {
|
||||||
queue = rev->accept ? &ngx_posted_accept_events
|
queue = rev->accept ? &ngx_posted_accept_events
|
||||||
|
|||||||
@@ -886,11 +886,10 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
|
|||||||
if (revents & EPOLLRDHUP) {
|
if (revents & EPOLLRDHUP) {
|
||||||
rev->pending_eof = 1;
|
rev->pending_eof = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rev->available = 1;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rev->ready = 1;
|
rev->ready = 1;
|
||||||
|
rev->available = -1;
|
||||||
|
|
||||||
if (flags & NGX_POST_EVENTS) {
|
if (flags & NGX_POST_EVENTS) {
|
||||||
queue = rev->accept ? &ngx_posted_accept_events
|
queue = rev->accept ? &ngx_posted_accept_events
|
||||||
|
|||||||
@@ -559,6 +559,7 @@ ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
|||||||
|
|
||||||
if (revents & POLLIN) {
|
if (revents & POLLIN) {
|
||||||
rev->ready = 1;
|
rev->ready = 1;
|
||||||
|
rev->available = -1;
|
||||||
|
|
||||||
if (flags & NGX_POST_EVENTS) {
|
if (flags & NGX_POST_EVENTS) {
|
||||||
queue = rev->accept ? &ngx_posted_accept_events
|
queue = rev->accept ? &ngx_posted_accept_events
|
||||||
|
|||||||
@@ -370,6 +370,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
|
|||||||
|
|
||||||
ev = c->read;
|
ev = c->read;
|
||||||
ev->ready = 1;
|
ev->ready = 1;
|
||||||
|
ev->available = -1;
|
||||||
|
|
||||||
queue = ev->accept ? &ngx_posted_accept_events
|
queue = ev->accept ? &ngx_posted_accept_events
|
||||||
: &ngx_posted_events;
|
: &ngx_posted_events;
|
||||||
|
|||||||
@@ -330,6 +330,7 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
|||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
ev->ready = 1;
|
ev->ready = 1;
|
||||||
|
ev->available = -1;
|
||||||
|
|
||||||
queue = ev->accept ? &ngx_posted_accept_events
|
queue = ev->accept ? &ngx_posted_accept_events
|
||||||
: &ngx_posted_events;
|
: &ngx_posted_events;
|
||||||
|
|||||||
@@ -380,6 +380,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
|
|||||||
|
|
||||||
ev = c->read;
|
ev = c->read;
|
||||||
ev->ready = 1;
|
ev->ready = 1;
|
||||||
|
ev->available = -1;
|
||||||
|
|
||||||
queue = ev->accept ? &ngx_posted_accept_events
|
queue = ev->accept ? &ngx_posted_accept_events
|
||||||
: &ngx_posted_events;
|
: &ngx_posted_events;
|
||||||
|
|||||||
@@ -330,6 +330,7 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
|
|||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
ev->ready = 1;
|
ev->ready = 1;
|
||||||
|
ev->available = -1;
|
||||||
|
|
||||||
queue = ev->accept ? &ngx_posted_accept_events
|
queue = ev->accept ? &ngx_posted_accept_events
|
||||||
: &ngx_posted_events;
|
: &ngx_posted_events;
|
||||||
|
|||||||
@@ -237,6 +237,11 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ngx_queue_empty(&ngx_posted_next_events)) {
|
||||||
|
ngx_event_move_posted_next(cycle);
|
||||||
|
timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
delta = ngx_current_msec;
|
delta = ngx_current_msec;
|
||||||
|
|
||||||
(void) ngx_process_events(cycle, timer, flags);
|
(void) ngx_process_events(cycle, timer, flags);
|
||||||
@@ -639,6 +644,7 @@ ngx_event_process_init(ngx_cycle_t *cycle)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ngx_queue_init(&ngx_posted_accept_events);
|
ngx_queue_init(&ngx_posted_accept_events);
|
||||||
|
ngx_queue_init(&ngx_posted_next_events);
|
||||||
ngx_queue_init(&ngx_posted_events);
|
ngx_queue_init(&ngx_posted_events);
|
||||||
|
|
||||||
if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
|
if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
|
||||||
|
|||||||
@@ -91,21 +91,14 @@ struct ngx_event_s {
|
|||||||
* write: available space in buffer when event is ready
|
* write: available space in buffer when event is ready
|
||||||
* or lowat when event is set with NGX_LOWAT_EVENT flag
|
* or lowat when event is set with NGX_LOWAT_EVENT flag
|
||||||
*
|
*
|
||||||
* epoll with EPOLLRDHUP:
|
|
||||||
* accept: 1 if accept many, 0 otherwise
|
|
||||||
* read: 1 if there can be data to read, 0 otherwise
|
|
||||||
*
|
|
||||||
* iocp: TODO
|
* iocp: TODO
|
||||||
*
|
*
|
||||||
* otherwise:
|
* otherwise:
|
||||||
* accept: 1 if accept many, 0 otherwise
|
* accept: 1 if accept many, 0 otherwise
|
||||||
|
* read: bytes to read when event is ready, -1 if not known
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP)
|
|
||||||
int available;
|
int available;
|
||||||
#else
|
|
||||||
unsigned available:1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ngx_event_handler_pt handler;
|
ngx_event_handler_pt handler;
|
||||||
|
|
||||||
|
|||||||
+130
-18
@@ -130,6 +130,7 @@ int ngx_ssl_connection_index;
|
|||||||
int ngx_ssl_server_conf_index;
|
int ngx_ssl_server_conf_index;
|
||||||
int ngx_ssl_session_cache_index;
|
int ngx_ssl_session_cache_index;
|
||||||
int ngx_ssl_session_ticket_keys_index;
|
int ngx_ssl_session_ticket_keys_index;
|
||||||
|
int ngx_ssl_ocsp_index;
|
||||||
int ngx_ssl_certificate_index;
|
int ngx_ssl_certificate_index;
|
||||||
int ngx_ssl_next_certificate_index;
|
int ngx_ssl_next_certificate_index;
|
||||||
int ngx_ssl_certificate_name_index;
|
int ngx_ssl_certificate_name_index;
|
||||||
@@ -213,6 +214,13 @@ ngx_ssl_init(ngx_log_t *log)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
||||||
|
if (ngx_ssl_ocsp_index == -1) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ALERT, log, 0,
|
||||||
|
"SSL_CTX_get_ex_new_index() failed");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
|
ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (ngx_ssl_certificate_index == -1) {
|
if (ngx_ssl_certificate_index == -1) {
|
||||||
@@ -920,6 +928,9 @@ ngx_int_t
|
|||||||
ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
|
||||||
ngx_int_t depth)
|
ngx_int_t depth)
|
||||||
{
|
{
|
||||||
|
SSL_CTX_set_verify(ssl->ctx, SSL_CTX_get_verify_mode(ssl->ctx),
|
||||||
|
ngx_ssl_verify_callback);
|
||||||
|
|
||||||
SSL_CTX_set_verify_depth(ssl->ctx, depth);
|
SSL_CTX_set_verify_depth(ssl->ctx, depth);
|
||||||
|
|
||||||
if (cert->len == 0) {
|
if (cert->len == 0) {
|
||||||
@@ -1603,6 +1614,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
|
|||||||
{
|
{
|
||||||
int n, sslerr;
|
int n, sslerr;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
|
ngx_int_t rc;
|
||||||
|
|
||||||
#ifdef SSL_READ_EARLY_DATA_SUCCESS
|
#ifdef SSL_READ_EARLY_DATA_SUCCESS
|
||||||
if (c->ssl->try_early_data) {
|
if (c->ssl->try_early_data) {
|
||||||
@@ -1610,6 +1622,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (c->ssl->in_ocsp) {
|
||||||
|
return ngx_ssl_ocsp_validate(c);
|
||||||
|
}
|
||||||
|
|
||||||
ngx_ssl_clear_error(c->log);
|
ngx_ssl_clear_error(c->log);
|
||||||
|
|
||||||
n = SSL_do_handshake(c->ssl->connection);
|
n = SSL_do_handshake(c->ssl->connection);
|
||||||
@@ -1630,8 +1646,6 @@ ngx_ssl_handshake(ngx_connection_t *c)
|
|||||||
ngx_ssl_handshake_log(c);
|
ngx_ssl_handshake_log(c);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
c->ssl->handshaked = 1;
|
|
||||||
|
|
||||||
c->recv = ngx_ssl_recv;
|
c->recv = ngx_ssl_recv;
|
||||||
c->send = ngx_ssl_write;
|
c->send = ngx_ssl_write;
|
||||||
c->recv_chain = ngx_ssl_recv_chain;
|
c->recv_chain = ngx_ssl_recv_chain;
|
||||||
@@ -1650,6 +1664,20 @@ ngx_ssl_handshake(ngx_connection_t *c)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
rc = ngx_ssl_ocsp_validate(c);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_AGAIN) {
|
||||||
|
c->read->handler = ngx_ssl_handshake_handler;
|
||||||
|
c->write->handler = ngx_ssl_handshake_handler;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->ssl->handshaked = 1;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1719,6 +1747,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
|
|||||||
u_char buf;
|
u_char buf;
|
||||||
size_t readbytes;
|
size_t readbytes;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
|
ngx_int_t rc;
|
||||||
|
|
||||||
ngx_ssl_clear_error(c->log);
|
ngx_ssl_clear_error(c->log);
|
||||||
|
|
||||||
@@ -1753,7 +1782,6 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
|
|||||||
c->ssl->early_buf = buf;
|
c->ssl->early_buf = buf;
|
||||||
c->ssl->early_preread = 1;
|
c->ssl->early_preread = 1;
|
||||||
|
|
||||||
c->ssl->handshaked = 1;
|
|
||||||
c->ssl->in_early = 1;
|
c->ssl->in_early = 1;
|
||||||
|
|
||||||
c->recv = ngx_ssl_recv;
|
c->recv = ngx_ssl_recv;
|
||||||
@@ -1761,6 +1789,20 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
|
|||||||
c->recv_chain = ngx_ssl_recv_chain;
|
c->recv_chain = ngx_ssl_recv_chain;
|
||||||
c->send_chain = ngx_ssl_send_chain;
|
c->send_chain = ngx_ssl_send_chain;
|
||||||
|
|
||||||
|
rc = ngx_ssl_ocsp_validate(c);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_AGAIN) {
|
||||||
|
c->read->handler = ngx_ssl_handshake_handler;
|
||||||
|
c->write->handler = ngx_ssl_handshake_handler;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->ssl->handshaked = 1;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1931,6 +1973,10 @@ ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit)
|
|||||||
last += n;
|
last += n;
|
||||||
bytes += n;
|
bytes += n;
|
||||||
|
|
||||||
|
if (!c->read->ready) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
if (last == b->end) {
|
if (last == b->end) {
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
|
|
||||||
@@ -2008,6 +2054,47 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
c->read->ready = 1;
|
c->read->ready = 1;
|
||||||
|
|
||||||
|
if (c->read->available >= 0) {
|
||||||
|
c->read->available -= bytes;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* there can be data buffered at SSL layer,
|
||||||
|
* so we post an event to continue reading on the next
|
||||||
|
* iteration of the event loop
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (c->read->available < 0) {
|
||||||
|
c->read->available = 0;
|
||||||
|
c->read->ready = 0;
|
||||||
|
|
||||||
|
if (c->read->posted) {
|
||||||
|
ngx_delete_posted_event(c->read);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_post_event(c->read, &ngx_posted_next_events);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"SSL_read: avail:%d", c->read->available);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_FIONREAD)
|
||||||
|
|
||||||
|
if (ngx_socket_nread(c->fd, &c->read->available) == -1) {
|
||||||
|
c->read->error = 1;
|
||||||
|
ngx_connection_error(c, ngx_socket_errno,
|
||||||
|
ngx_socket_nread_n " failed");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"SSL_read: avail:%d", c->read->available);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2736,6 +2823,9 @@ ngx_ssl_shutdown(ngx_connection_t *c)
|
|||||||
{
|
{
|
||||||
int n, sslerr, mode;
|
int n, sslerr, mode;
|
||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
|
ngx_uint_t tries;
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_cleanup(c);
|
||||||
|
|
||||||
if (SSL_in_init(c->ssl->connection)) {
|
if (SSL_in_init(c->ssl->connection)) {
|
||||||
/*
|
/*
|
||||||
@@ -2774,28 +2864,38 @@ ngx_ssl_shutdown(ngx_connection_t *c)
|
|||||||
|
|
||||||
ngx_ssl_clear_error(c->log);
|
ngx_ssl_clear_error(c->log);
|
||||||
|
|
||||||
|
tries = 2;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For bidirectional shutdown, SSL_shutdown() needs to be called
|
||||||
|
* twice: first call sends the "close notify" alert and returns 0,
|
||||||
|
* second call waits for the peer's "close notify" alert.
|
||||||
|
*/
|
||||||
|
|
||||||
n = SSL_shutdown(c->ssl->connection);
|
n = SSL_shutdown(c->ssl->connection);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
|
||||||
|
|
||||||
sslerr = 0;
|
if (n == 1) {
|
||||||
|
|
||||||
/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
|
|
||||||
|
|
||||||
if (n != 1 && ERR_peek_error()) {
|
|
||||||
sslerr = SSL_get_error(c->ssl->connection, n);
|
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"SSL_get_error: %d", sslerr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
|
|
||||||
SSL_free(c->ssl->connection);
|
SSL_free(c->ssl->connection);
|
||||||
c->ssl = NULL;
|
c->ssl = NULL;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n == 0 && tries-- > 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
|
||||||
|
|
||||||
|
sslerr = SSL_get_error(c->ssl->connection, n);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"SSL_get_error: %d", sslerr);
|
||||||
|
|
||||||
if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
|
if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
|
||||||
c->read->handler = ngx_ssl_shutdown_handler;
|
c->read->handler = ngx_ssl_shutdown_handler;
|
||||||
c->write->handler = ngx_ssl_shutdown_handler;
|
c->write->handler = ngx_ssl_shutdown_handler;
|
||||||
@@ -2808,13 +2908,18 @@ ngx_ssl_shutdown(ngx_connection_t *c)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sslerr == SSL_ERROR_WANT_READ) {
|
ngx_add_timer(c->read, 3000);
|
||||||
ngx_add_timer(c->read, 30000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
|
||||||
|
SSL_free(c->ssl->connection);
|
||||||
|
c->ssl = NULL;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
|
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
|
||||||
|
|
||||||
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
|
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
|
||||||
@@ -2824,6 +2929,7 @@ ngx_ssl_shutdown(ngx_connection_t *c)
|
|||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2864,6 +2970,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|
|||||||
if (sslerr == SSL_ERROR_SYSCALL) {
|
if (sslerr == SSL_ERROR_SYSCALL) {
|
||||||
|
|
||||||
if (err == NGX_ECONNRESET
|
if (err == NGX_ECONNRESET
|
||||||
|
#if (NGX_WIN32)
|
||||||
|
|| err == NGX_ECONNABORTED
|
||||||
|
#endif
|
||||||
|| err == NGX_EPIPE
|
|| err == NGX_EPIPE
|
||||||
|| err == NGX_ENOTCONN
|
|| err == NGX_ENOTCONN
|
||||||
|| err == NGX_ETIMEDOUT
|
|| err == NGX_ETIMEDOUT
|
||||||
@@ -4915,11 +5024,14 @@ ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
|||||||
rc = SSL_get_verify_result(c->ssl->connection);
|
rc = SSL_get_verify_result(c->ssl->connection);
|
||||||
|
|
||||||
if (rc == X509_V_OK) {
|
if (rc == X509_V_OK) {
|
||||||
|
if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) {
|
||||||
ngx_str_set(s, "SUCCESS");
|
ngx_str_set(s, "SUCCESS");
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
str = X509_verify_cert_error_string(rc);
|
str = X509_verify_cert_error_string(rc);
|
||||||
|
}
|
||||||
|
|
||||||
s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
|
s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str));
|
||||||
if (s->data == NULL) {
|
if (s->data == NULL) {
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ typedef struct {
|
|||||||
} ngx_ssl_dyn_rec_t;
|
} ngx_ssl_dyn_rec_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
|
||||||
|
|
||||||
|
|
||||||
struct ngx_ssl_s {
|
struct ngx_ssl_s {
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
ngx_log_t *log;
|
ngx_log_t *log;
|
||||||
@@ -96,6 +99,8 @@ struct ngx_ssl_connection_s {
|
|||||||
ngx_event_handler_pt saved_read_handler;
|
ngx_event_handler_pt saved_read_handler;
|
||||||
ngx_event_handler_pt saved_write_handler;
|
ngx_event_handler_pt saved_write_handler;
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_t *ocsp;
|
||||||
|
|
||||||
u_char early_buf;
|
u_char early_buf;
|
||||||
|
|
||||||
unsigned handshaked:1;
|
unsigned handshaked:1;
|
||||||
@@ -106,6 +111,7 @@ struct ngx_ssl_connection_s {
|
|||||||
unsigned handshake_buffer_set:1;
|
unsigned handshake_buffer_set:1;
|
||||||
unsigned try_early_data:1;
|
unsigned try_early_data:1;
|
||||||
unsigned in_early:1;
|
unsigned in_early:1;
|
||||||
|
unsigned in_ocsp:1;
|
||||||
unsigned early_preread:1;
|
unsigned early_preread:1;
|
||||||
unsigned write_blocked:1;
|
unsigned write_blocked:1;
|
||||||
|
|
||||||
@@ -193,6 +199,14 @@ ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
|||||||
ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
|
ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
|
||||||
ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
|
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
|
||||||
|
ngx_int_t ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
|
||||||
|
ngx_uint_t depth, ngx_shm_zone_t *shm_zone);
|
||||||
|
ngx_int_t ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
|
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
|
||||||
|
ngx_int_t ngx_ssl_ocsp_validate(ngx_connection_t *c);
|
||||||
|
ngx_int_t ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s);
|
||||||
|
void ngx_ssl_ocsp_cleanup(ngx_connection_t *c);
|
||||||
|
ngx_int_t ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data);
|
||||||
RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
|
RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
|
||||||
int key_length);
|
int key_length);
|
||||||
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
|
ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
|
||||||
@@ -294,6 +308,7 @@ extern int ngx_ssl_connection_index;
|
|||||||
extern int ngx_ssl_server_conf_index;
|
extern int ngx_ssl_server_conf_index;
|
||||||
extern int ngx_ssl_session_cache_index;
|
extern int ngx_ssl_session_cache_index;
|
||||||
extern int ngx_ssl_session_ticket_keys_index;
|
extern int ngx_ssl_session_ticket_keys_index;
|
||||||
|
extern int ngx_ssl_ocsp_index;
|
||||||
extern int ngx_ssl_certificate_index;
|
extern int ngx_ssl_certificate_index;
|
||||||
extern int ngx_ssl_next_certificate_index;
|
extern int ngx_ssl_next_certificate_index;
|
||||||
extern int ngx_ssl_certificate_name_index;
|
extern int ngx_ssl_certificate_name_index;
|
||||||
|
|||||||
+1060
-168
@@ -22,6 +22,7 @@ typedef struct {
|
|||||||
ngx_msec_t resolver_timeout;
|
ngx_msec_t resolver_timeout;
|
||||||
|
|
||||||
ngx_addr_t *addrs;
|
ngx_addr_t *addrs;
|
||||||
|
ngx_uint_t naddrs;
|
||||||
ngx_str_t host;
|
ngx_str_t host;
|
||||||
ngx_str_t uri;
|
ngx_str_t uri;
|
||||||
in_port_t port;
|
in_port_t port;
|
||||||
@@ -30,6 +31,7 @@ typedef struct {
|
|||||||
|
|
||||||
X509 *cert;
|
X509 *cert;
|
||||||
X509 *issuer;
|
X509 *issuer;
|
||||||
|
STACK_OF(X509) *chain;
|
||||||
|
|
||||||
u_char *name;
|
u_char *name;
|
||||||
|
|
||||||
@@ -41,15 +43,66 @@ typedef struct {
|
|||||||
} ngx_ssl_stapling_t;
|
} ngx_ssl_stapling_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_addr_t *addrs;
|
||||||
|
ngx_uint_t naddrs;
|
||||||
|
|
||||||
|
ngx_str_t host;
|
||||||
|
ngx_str_t uri;
|
||||||
|
in_port_t port;
|
||||||
|
ngx_uint_t depth;
|
||||||
|
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
|
||||||
|
ngx_resolver_t *resolver;
|
||||||
|
ngx_msec_t resolver_timeout;
|
||||||
|
} ngx_ssl_ocsp_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_rbtree_t rbtree;
|
||||||
|
ngx_rbtree_node_t sentinel;
|
||||||
|
ngx_queue_t expire_queue;
|
||||||
|
} ngx_ssl_ocsp_cache_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_str_node_t node;
|
||||||
|
ngx_queue_t queue;
|
||||||
|
int status;
|
||||||
|
time_t valid;
|
||||||
|
} ngx_ssl_ocsp_cache_node_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
|
typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct ngx_ssl_ocsp_s {
|
||||||
|
STACK_OF(X509) *certs;
|
||||||
|
ngx_uint_t ncert;
|
||||||
|
|
||||||
|
int cert_status;
|
||||||
|
ngx_int_t status;
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_conf_t *conf;
|
||||||
|
ngx_ssl_ocsp_ctx_t *ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ngx_ssl_ocsp_ctx_s {
|
struct ngx_ssl_ocsp_ctx_s {
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
|
||||||
X509 *cert;
|
X509 *cert;
|
||||||
X509 *issuer;
|
X509 *issuer;
|
||||||
|
STACK_OF(X509) *chain;
|
||||||
|
|
||||||
|
int status;
|
||||||
|
time_t valid;
|
||||||
|
|
||||||
u_char *name;
|
u_char *name;
|
||||||
|
|
||||||
ngx_uint_t naddrs;
|
ngx_uint_t naddrs;
|
||||||
|
ngx_uint_t naddr;
|
||||||
|
|
||||||
ngx_addr_t *addrs;
|
ngx_addr_t *addrs;
|
||||||
ngx_str_t host;
|
ngx_str_t host;
|
||||||
@@ -64,17 +117,20 @@ struct ngx_ssl_ocsp_ctx_s {
|
|||||||
void (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
|
void (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
|
ngx_str_t key;
|
||||||
ngx_buf_t *request;
|
ngx_buf_t *request;
|
||||||
ngx_buf_t *response;
|
ngx_buf_t *response;
|
||||||
ngx_peer_connection_t peer;
|
ngx_peer_connection_t peer;
|
||||||
|
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
|
||||||
ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx);
|
ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
|
||||||
ngx_uint_t state;
|
ngx_uint_t state;
|
||||||
|
|
||||||
ngx_uint_t code;
|
ngx_uint_t code;
|
||||||
ngx_uint_t count;
|
ngx_uint_t count;
|
||||||
|
ngx_uint_t flags;
|
||||||
ngx_uint_t done;
|
ngx_uint_t done;
|
||||||
|
|
||||||
u_char *header_name_start;
|
u_char *header_name_start;
|
||||||
@@ -105,8 +161,14 @@ static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
|
|||||||
|
|
||||||
static void ngx_ssl_stapling_cleanup(void *data);
|
static void ngx_ssl_stapling_cleanup(void *data);
|
||||||
|
|
||||||
static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
|
static void ngx_ssl_ocsp_validate_next(ngx_connection_t *c);
|
||||||
|
static void ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
static ngx_int_t ngx_ssl_ocsp_responder(ngx_connection_t *c,
|
||||||
|
ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
|
||||||
|
static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(ngx_log_t *log);
|
||||||
static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
|
static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
static void ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
|
static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
|
static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
|
||||||
static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
|
static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
@@ -120,6 +182,11 @@ static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
|
|||||||
static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
|
static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
|
static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
|
static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
static ngx_int_t ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
static ngx_int_t ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
static ngx_int_t ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx);
|
||||||
|
|
||||||
static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
||||||
|
|
||||||
@@ -173,6 +240,18 @@ ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_CTRL_SELECT_CURRENT_CERT
|
||||||
|
/* OpenSSL 1.0.2+ */
|
||||||
|
SSL_CTX_select_current_cert(ssl->ctx, cert);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
|
||||||
|
/* OpenSSL 1.0.1+ */
|
||||||
|
SSL_CTX_get_extra_chain_certs(ssl->ctx, &staple->chain);
|
||||||
|
#else
|
||||||
|
staple->chain = ssl->ctx->extra_certs;
|
||||||
|
#endif
|
||||||
|
|
||||||
staple->ssl_ctx = ssl->ctx;
|
staple->ssl_ctx = ssl->ctx;
|
||||||
staple->timeout = 60000;
|
staple->timeout = 60000;
|
||||||
staple->verify = verify;
|
staple->verify = verify;
|
||||||
@@ -289,29 +368,16 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
|||||||
X509 *cert, *issuer;
|
X509 *cert, *issuer;
|
||||||
X509_STORE *store;
|
X509_STORE *store;
|
||||||
X509_STORE_CTX *store_ctx;
|
X509_STORE_CTX *store_ctx;
|
||||||
STACK_OF(X509) *chain;
|
|
||||||
|
|
||||||
cert = staple->cert;
|
cert = staple->cert;
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SELECT_CURRENT_CERT
|
n = sk_X509_num(staple->chain);
|
||||||
/* OpenSSL 1.0.2+ */
|
|
||||||
SSL_CTX_select_current_cert(ssl->ctx, cert);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
|
|
||||||
/* OpenSSL 1.0.1+ */
|
|
||||||
SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
|
|
||||||
#else
|
|
||||||
chain = ssl->ctx->extra_certs;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
n = sk_X509_num(chain);
|
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
|
||||||
"SSL get issuer: %d extra certs", n);
|
"SSL get issuer: %d extra certs", n);
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
issuer = sk_X509_value(chain, i);
|
issuer = sk_X509_value(staple->chain, i);
|
||||||
if (X509_check_issued(issuer, cert) == X509_V_OK) {
|
if (X509_check_issued(issuer, cert) == X509_V_OK) {
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100001L
|
#if OPENSSL_VERSION_NUMBER >= 0x10100001L
|
||||||
X509_up_ref(issuer);
|
X509_up_ref(issuer);
|
||||||
@@ -462,6 +528,7 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
staple->addrs = u.addrs;
|
staple->addrs = u.addrs;
|
||||||
|
staple->naddrs = u.naddrs;
|
||||||
staple->host = u.host;
|
staple->host = u.host;
|
||||||
staple->uri = u.uri;
|
staple->uri = u.uri;
|
||||||
staple->port = u.port;
|
staple->port = u.port;
|
||||||
@@ -559,16 +626,20 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
|
|||||||
|
|
||||||
staple->loading = 1;
|
staple->loading = 1;
|
||||||
|
|
||||||
ctx = ngx_ssl_ocsp_start();
|
ctx = ngx_ssl_ocsp_start(ngx_cycle->log);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->ssl_ctx = staple->ssl_ctx;
|
||||||
ctx->cert = staple->cert;
|
ctx->cert = staple->cert;
|
||||||
ctx->issuer = staple->issuer;
|
ctx->issuer = staple->issuer;
|
||||||
|
ctx->chain = staple->chain;
|
||||||
ctx->name = staple->name;
|
ctx->name = staple->name;
|
||||||
|
ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
|
||||||
|
|
||||||
ctx->addrs = staple->addrs;
|
ctx->addrs = staple->addrs;
|
||||||
|
ctx->naddrs = staple->naddrs;
|
||||||
ctx->host = staple->host;
|
ctx->host = staple->host;
|
||||||
ctx->uri = staple->uri;
|
ctx->uri = staple->uri;
|
||||||
ctx->port = staple->port;
|
ctx->port = staple->port;
|
||||||
@@ -589,137 +660,27 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
|
|||||||
static void
|
static void
|
||||||
ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
|
ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
int n;
|
time_t now;
|
||||||
size_t len;
|
|
||||||
time_t now, valid;
|
|
||||||
ngx_str_t response;
|
ngx_str_t response;
|
||||||
X509_STORE *store;
|
|
||||||
const u_char *p;
|
|
||||||
STACK_OF(X509) *chain;
|
|
||||||
OCSP_CERTID *id;
|
|
||||||
OCSP_RESPONSE *ocsp;
|
|
||||||
OCSP_BASICRESP *basic;
|
|
||||||
ngx_ssl_stapling_t *staple;
|
ngx_ssl_stapling_t *staple;
|
||||||
ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
|
|
||||||
|
|
||||||
staple = ctx->data;
|
staple = ctx->data;
|
||||||
now = ngx_time();
|
now = ngx_time();
|
||||||
ocsp = NULL;
|
|
||||||
basic = NULL;
|
|
||||||
id = NULL;
|
|
||||||
|
|
||||||
if (ctx->code != 200) {
|
if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check the response */
|
if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
|
||||||
|
|
||||||
len = ctx->response->last - ctx->response->pos;
|
|
||||||
p = ctx->response->pos;
|
|
||||||
|
|
||||||
ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
|
||||||
if (ocsp == NULL) {
|
|
||||||
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"d2i_OCSP_RESPONSE() failed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = OCSP_response_status(ocsp);
|
|
||||||
|
|
||||||
if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
|
||||||
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"OCSP response not successful (%d: %s)",
|
|
||||||
n, OCSP_response_status_str(n));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
basic = OCSP_response_get1_basic(ocsp);
|
|
||||||
if (basic == NULL) {
|
|
||||||
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"OCSP_response_get1_basic() failed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
store = SSL_CTX_get_cert_store(staple->ssl_ctx);
|
|
||||||
if (store == NULL) {
|
|
||||||
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
|
|
||||||
"SSL_CTX_get_cert_store() failed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SELECT_CURRENT_CERT
|
|
||||||
/* OpenSSL 1.0.2+ */
|
|
||||||
SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
|
|
||||||
/* OpenSSL 1.0.1+ */
|
|
||||||
SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
|
|
||||||
#else
|
|
||||||
chain = staple->ssl_ctx->extra_certs;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (OCSP_basic_verify(basic, chain, store,
|
|
||||||
staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
|
|
||||||
!= 1)
|
|
||||||
{
|
|
||||||
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"OCSP_basic_verify() failed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
|
|
||||||
if (id == NULL) {
|
|
||||||
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
|
|
||||||
"OCSP_cert_to_id() failed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
|
|
||||||
&thisupdate, &nextupdate)
|
|
||||||
!= 1)
|
|
||||||
{
|
|
||||||
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"certificate status not found in the OCSP response");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n != V_OCSP_CERTSTATUS_GOOD) {
|
|
||||||
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
"certificate status \"%s\" in the OCSP response",
|
"certificate status \"%s\" in the OCSP response",
|
||||||
OCSP_cert_status_str(n));
|
OCSP_cert_status_str(ctx->status));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
|
|
||||||
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"OCSP_check_validity() failed");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextupdate) {
|
|
||||||
valid = ngx_ssl_stapling_time(nextupdate);
|
|
||||||
if (valid == (time_t) NGX_ERROR) {
|
|
||||||
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
|
||||||
"invalid nextUpdate time in certificate status");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
valid = NGX_MAX_TIME_T_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
OCSP_CERTID_free(id);
|
|
||||||
OCSP_BASICRESP_free(basic);
|
|
||||||
OCSP_RESPONSE_free(ocsp);
|
|
||||||
|
|
||||||
id = NULL;
|
|
||||||
basic = NULL;
|
|
||||||
ocsp = NULL;
|
|
||||||
|
|
||||||
/* copy the response to memory not in ctx->pool */
|
/* copy the response to memory not in ctx->pool */
|
||||||
|
|
||||||
response.len = len;
|
response.len = ctx->response->last - ctx->response->pos;
|
||||||
response.data = ngx_alloc(response.len, ctx->log);
|
response.data = ngx_alloc(response.len, ctx->log);
|
||||||
|
|
||||||
if (response.data == NULL) {
|
if (response.data == NULL) {
|
||||||
@@ -728,16 +689,12 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
|
|
||||||
ngx_memcpy(response.data, ctx->response->pos, response.len);
|
ngx_memcpy(response.data, ctx->response->pos, response.len);
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
|
||||||
"ssl ocsp response, %s, %uz",
|
|
||||||
OCSP_cert_status_str(n), response.len);
|
|
||||||
|
|
||||||
if (staple->staple.data) {
|
if (staple->staple.data) {
|
||||||
ngx_free(staple->staple.data);
|
ngx_free(staple->staple.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
staple->staple = response;
|
staple->staple = response;
|
||||||
staple->valid = valid;
|
staple->valid = ctx->valid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* refresh before the response expires,
|
* refresh before the response expires,
|
||||||
@@ -745,7 +702,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
staple->loading = 0;
|
staple->loading = 0;
|
||||||
staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
|
staple->refresh = ngx_max(ngx_min(ctx->valid - 300, now + 3600), now + 300);
|
||||||
|
|
||||||
ngx_ssl_ocsp_done(ctx);
|
ngx_ssl_ocsp_done(ctx);
|
||||||
return;
|
return;
|
||||||
@@ -755,18 +712,6 @@ error:
|
|||||||
staple->loading = 0;
|
staple->loading = 0;
|
||||||
staple->refresh = now + 300;
|
staple->refresh = now + 300;
|
||||||
|
|
||||||
if (id) {
|
|
||||||
OCSP_CERTID_free(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basic) {
|
|
||||||
OCSP_BASICRESP_free(basic);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ocsp) {
|
|
||||||
OCSP_RESPONSE_free(ocsp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_ssl_ocsp_done(ctx);
|
ngx_ssl_ocsp_done(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,14 +765,507 @@ ngx_ssl_stapling_cleanup(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_ssl_ocsp_ctx_t *
|
ngx_int_t
|
||||||
ngx_ssl_ocsp_start(void)
|
ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
|
||||||
|
ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
|
||||||
|
{
|
||||||
|
ngx_url_t u;
|
||||||
|
ngx_ssl_ocsp_conf_t *ocf;
|
||||||
|
|
||||||
|
ocf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_ocsp_conf_t));
|
||||||
|
if (ocf == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocf->depth = depth;
|
||||||
|
ocf->shm_zone = shm_zone;
|
||||||
|
|
||||||
|
if (responder->len) {
|
||||||
|
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
u.url = *responder;
|
||||||
|
u.default_port = 80;
|
||||||
|
u.uri_part = 1;
|
||||||
|
|
||||||
|
if (u.url.len > 7
|
||||||
|
&& ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
|
||||||
|
{
|
||||||
|
u.url.len -= 7;
|
||||||
|
u.url.data += 7;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"invalid URL prefix in OCSP responder \"%V\" "
|
||||||
|
"in \"ssl_ocsp_responder\"", &u.url);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
|
||||||
|
if (u.err) {
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"%s in OCSP responder \"%V\" "
|
||||||
|
"in \"ssl_ocsp_responder\"", u.err, &u.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocf->addrs = u.addrs;
|
||||||
|
ocf->naddrs = u.naddrs;
|
||||||
|
ocf->host = u.host;
|
||||||
|
ocf->uri = u.uri;
|
||||||
|
ocf->port = u.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ocsp_index, ocf) == 0) {
|
||||||
|
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||||
|
"SSL_CTX_set_ex_data() failed");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
|
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
|
||||||
|
{
|
||||||
|
ngx_ssl_ocsp_conf_t *ocf;
|
||||||
|
|
||||||
|
ocf = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_ocsp_index);
|
||||||
|
ocf->resolver = resolver;
|
||||||
|
ocf->resolver_timeout = resolver_timeout;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_validate(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
X509 *cert;
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
ngx_int_t rc;
|
||||||
|
X509_STORE *store;
|
||||||
|
X509_STORE_CTX *store_ctx;
|
||||||
|
STACK_OF(X509) *chain;
|
||||||
|
ngx_ssl_ocsp_t *ocsp;
|
||||||
|
ngx_ssl_ocsp_conf_t *ocf;
|
||||||
|
|
||||||
|
if (c->ssl->in_ocsp) {
|
||||||
|
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
|
||||||
|
|
||||||
|
ocf = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ocsp_index);
|
||||||
|
if (ocf == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cert = SSL_get_peer_certificate(c->ssl->connection);
|
||||||
|
if (cert == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocsp = ngx_pcalloc(c->pool, sizeof(ngx_ssl_ocsp_t));
|
||||||
|
if (ocsp == NULL) {
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->ssl->ocsp = ocsp;
|
||||||
|
|
||||||
|
ocsp->status = NGX_AGAIN;
|
||||||
|
ocsp->cert_status = V_OCSP_CERTSTATUS_GOOD;
|
||||||
|
ocsp->conf = ocf;
|
||||||
|
|
||||||
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined LIBRESSL_VERSION_NUMBER)
|
||||||
|
|
||||||
|
ocsp->certs = SSL_get0_verified_chain(c->ssl->connection);
|
||||||
|
|
||||||
|
if (ocsp->certs) {
|
||||||
|
ocsp->certs = X509_chain_up_ref(ocsp->certs);
|
||||||
|
if (ocsp->certs == NULL) {
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ocsp->certs == NULL) {
|
||||||
|
store = SSL_CTX_get_cert_store(ssl_ctx);
|
||||||
|
if (store == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"SSL_CTX_get_cert_store() failed");
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
store_ctx = X509_STORE_CTX_new();
|
||||||
|
if (store_ctx == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"X509_STORE_CTX_new() failed");
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
chain = SSL_get_peer_cert_chain(c->ssl->connection);
|
||||||
|
|
||||||
|
if (X509_STORE_CTX_init(store_ctx, store, cert, chain) == 0) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"X509_STORE_CTX_init() failed");
|
||||||
|
X509_STORE_CTX_free(store_ctx);
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = X509_verify_cert(store_ctx);
|
||||||
|
if (rc <= 0) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_verify_cert() failed");
|
||||||
|
X509_STORE_CTX_free(store_ctx);
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocsp->certs = X509_STORE_CTX_get1_chain(store_ctx);
|
||||||
|
if (ocsp->certs == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"X509_STORE_CTX_get1_chain() failed");
|
||||||
|
X509_STORE_CTX_free(store_ctx);
|
||||||
|
X509_free(cert);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_STORE_CTX_free(store_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_free(cert);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"ssl ocsp validate, certs:%d", sk_X509_num(ocsp->certs));
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_validate_next(c);
|
||||||
|
|
||||||
|
if (ocsp->status == NGX_AGAIN) {
|
||||||
|
c->ssl->in_ocsp = 1;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_ssl_ocsp_validate_next(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_uint_t n;
|
||||||
|
ngx_ssl_ocsp_t *ocsp;
|
||||||
|
ngx_ssl_ocsp_ctx_t *ctx;
|
||||||
|
ngx_ssl_ocsp_conf_t *ocf;
|
||||||
|
|
||||||
|
ocsp = c->ssl->ocsp;
|
||||||
|
ocf = ocsp->conf;
|
||||||
|
|
||||||
|
n = sk_X509_num(ocsp->certs);
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
|
||||||
|
if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) {
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"ssl ocsp validated, certs:%ui", ocsp->ncert);
|
||||||
|
rc = NGX_OK;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"ssl ocsp validate cert:%ui", ocsp->ncert);
|
||||||
|
|
||||||
|
ctx = ngx_ssl_ocsp_start(c->log);
|
||||||
|
if (ctx == NULL) {
|
||||||
|
rc = NGX_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocsp->ctx = ctx;
|
||||||
|
|
||||||
|
ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
|
||||||
|
ctx->cert = sk_X509_value(ocsp->certs, ocsp->ncert);
|
||||||
|
ctx->issuer = sk_X509_value(ocsp->certs, ocsp->ncert + 1);
|
||||||
|
ctx->chain = ocsp->certs;
|
||||||
|
|
||||||
|
ctx->resolver = ocf->resolver;
|
||||||
|
ctx->resolver_timeout = ocf->resolver_timeout;
|
||||||
|
|
||||||
|
ctx->handler = ngx_ssl_ocsp_handler;
|
||||||
|
ctx->data = c;
|
||||||
|
|
||||||
|
ctx->shm_zone = ocf->shm_zone;
|
||||||
|
|
||||||
|
ctx->addrs = ocf->addrs;
|
||||||
|
ctx->naddrs = ocf->naddrs;
|
||||||
|
ctx->host = ocf->host;
|
||||||
|
ctx->uri = ocf->uri;
|
||||||
|
ctx->port = ocf->port;
|
||||||
|
|
||||||
|
rc = ngx_ssl_ocsp_responder(c, ctx);
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->uri.len == 0) {
|
||||||
|
ngx_str_set(&ctx->uri, "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
ocsp->ncert++;
|
||||||
|
|
||||||
|
rc = ngx_ssl_ocsp_cache_lookup(ctx);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rc == NGX_OK */
|
||||||
|
|
||||||
|
if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp cached status \"%s\"",
|
||||||
|
OCSP_cert_status_str(ctx->status));
|
||||||
|
ocsp->cert_status = ctx->status;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocsp->ctx = NULL;
|
||||||
|
ngx_ssl_ocsp_done(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_request(ctx);
|
||||||
|
return;
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
ocsp->status = rc;
|
||||||
|
|
||||||
|
if (c->ssl->in_ocsp) {
|
||||||
|
c->ssl->handshaked = 1;
|
||||||
|
c->ssl->handler(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_ssl_ocsp_t *ocsp;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
|
||||||
|
c = ctx->data;
|
||||||
|
ocsp = c->ssl->ocsp;
|
||||||
|
ocsp->ctx = NULL;
|
||||||
|
|
||||||
|
rc = ngx_ssl_ocsp_verify(ctx);
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_ssl_ocsp_cache_store(ctx);
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
|
||||||
|
ocsp->cert_status = ctx->status;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_done(ctx);
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_validate_next(c);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
ocsp->status = rc;
|
||||||
|
ngx_ssl_ocsp_done(ctx);
|
||||||
|
|
||||||
|
if (c->ssl->in_ocsp) {
|
||||||
|
c->ssl->handshaked = 1;
|
||||||
|
c->ssl->handler(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
ngx_str_t responder;
|
||||||
|
ngx_url_t u;
|
||||||
|
STACK_OF(OPENSSL_STRING) *aia;
|
||||||
|
|
||||||
|
if (ctx->host.len) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract OCSP responder URL from certificate */
|
||||||
|
|
||||||
|
aia = X509_get1_ocsp(ctx->cert);
|
||||||
|
if (aia == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"no OCSP responder URL in certificate");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||||
|
s = sk_OPENSSL_STRING_value(aia, 0);
|
||||||
|
#else
|
||||||
|
s = sk_value(aia, 0);
|
||||||
|
#endif
|
||||||
|
if (s == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"no OCSP responder URL in certificate");
|
||||||
|
X509_email_free(aia);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
responder.len = ngx_strlen(s);
|
||||||
|
responder.data = ngx_palloc(ctx->pool, responder.len);
|
||||||
|
if (responder.data == NULL) {
|
||||||
|
X509_email_free(aia);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(responder.data, s, responder.len);
|
||||||
|
X509_email_free(aia);
|
||||||
|
|
||||||
|
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
u.url = responder;
|
||||||
|
u.default_port = 80;
|
||||||
|
u.uri_part = 1;
|
||||||
|
u.no_resolve = 1;
|
||||||
|
|
||||||
|
if (u.url.len > 7
|
||||||
|
&& ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
|
||||||
|
{
|
||||||
|
u.url.len -= 7;
|
||||||
|
u.url.data += 7;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"invalid URL prefix in OCSP responder \"%V\" "
|
||||||
|
"in certificate", &u.url);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_parse_url(ctx->pool, &u) != NGX_OK) {
|
||||||
|
if (u.err) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"%s in OCSP responder \"%V\" in certificate",
|
||||||
|
u.err, &u.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.host.len == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"empty host in OCSP responder in certificate");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->addrs = u.addrs;
|
||||||
|
ctx->naddrs = u.naddrs;
|
||||||
|
ctx->host = u.host;
|
||||||
|
ctx->uri = u.uri;
|
||||||
|
ctx->port = u.port;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
|
||||||
|
{
|
||||||
|
ngx_ssl_ocsp_t *ocsp;
|
||||||
|
|
||||||
|
ocsp = c->ssl->ocsp;
|
||||||
|
if (ocsp == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocsp->status == NGX_ERROR) {
|
||||||
|
*s = "certificate status request failed";
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ocsp->cert_status) {
|
||||||
|
|
||||||
|
case V_OCSP_CERTSTATUS_GOOD:
|
||||||
|
return NGX_OK;
|
||||||
|
|
||||||
|
case V_OCSP_CERTSTATUS_REVOKED:
|
||||||
|
*s = "certificate revoked";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* V_OCSP_CERTSTATUS_UNKNOWN */
|
||||||
|
*s = "certificate status unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
ngx_ssl_ocsp_t *ocsp;
|
||||||
|
|
||||||
|
ocsp = c->ssl->ocsp;
|
||||||
|
if (ocsp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocsp->ctx) {
|
||||||
|
ngx_ssl_ocsp_done(ocsp->ctx);
|
||||||
|
ocsp->ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocsp->certs) {
|
||||||
|
sk_X509_pop_free(ocsp->certs, X509_free);
|
||||||
|
ocsp->certs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_ssl_ocsp_ctx_t *
|
||||||
|
ngx_ssl_ocsp_start(ngx_log_t *log)
|
||||||
{
|
{
|
||||||
ngx_log_t *log;
|
|
||||||
ngx_pool_t *pool;
|
ngx_pool_t *pool;
|
||||||
ngx_ssl_ocsp_ctx_t *ctx;
|
ngx_ssl_ocsp_ctx_t *ctx;
|
||||||
|
|
||||||
pool = ngx_create_pool(2048, ngx_cycle->log);
|
pool = ngx_create_pool(2048, log);
|
||||||
if (pool == NULL) {
|
if (pool == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -884,6 +1322,36 @@ ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp next");
|
||||||
|
|
||||||
|
if (++ctx->naddr >= ctx->naddrs) {
|
||||||
|
ngx_ssl_ocsp_error(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->request->pos = ctx->request->start;
|
||||||
|
|
||||||
|
if (ctx->response) {
|
||||||
|
ctx->response->last = ctx->response->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->peer.connection) {
|
||||||
|
ngx_close_connection(ctx->peer.connection);
|
||||||
|
ctx->peer.connection = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->state = 0;
|
||||||
|
ctx->count = 0;
|
||||||
|
ctx->done = 0;
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_connect(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
|
ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
@@ -909,6 +1377,14 @@ ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (resolve == NGX_NO_RESOLVER) {
|
if (resolve == NGX_NO_RESOLVER) {
|
||||||
|
if (ctx->naddrs == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"no resolver defined to resolve %V", &ctx->host);
|
||||||
|
|
||||||
|
ngx_ssl_ocsp_error(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
|
ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
|
||||||
"no resolver defined to resolve %V", &ctx->host);
|
"no resolver defined to resolve %V", &ctx->host);
|
||||||
goto connect;
|
goto connect;
|
||||||
@@ -1023,15 +1499,16 @@ static void
|
|||||||
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
|
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
|
ngx_addr_t *addr;
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
"ssl ocsp connect");
|
"ssl ocsp connect %ui/%ui", ctx->naddr, ctx->naddrs);
|
||||||
|
|
||||||
/* TODO: use all ip addresses */
|
addr = &ctx->addrs[ctx->naddr];
|
||||||
|
|
||||||
ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
|
ctx->peer.sockaddr = addr->sockaddr;
|
||||||
ctx->peer.socklen = ctx->addrs[0].socklen;
|
ctx->peer.socklen = addr->socklen;
|
||||||
ctx->peer.name = &ctx->addrs[0].name;
|
ctx->peer.name = &addr->name;
|
||||||
ctx->peer.get = ngx_event_get_peer;
|
ctx->peer.get = ngx_event_get_peer;
|
||||||
ctx->peer.log = ctx->log;
|
ctx->peer.log = ctx->log;
|
||||||
ctx->peer.log_error = NGX_ERROR_ERR;
|
ctx->peer.log_error = NGX_ERROR_ERR;
|
||||||
@@ -1041,11 +1518,16 @@ ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
"ssl ocsp connect peer done");
|
"ssl ocsp connect peer done");
|
||||||
|
|
||||||
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
|
if (rc == NGX_ERROR) {
|
||||||
ngx_ssl_ocsp_error(ctx);
|
ngx_ssl_ocsp_error(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_BUSY || rc == NGX_DECLINED) {
|
||||||
|
ngx_ssl_ocsp_next(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->peer.connection->data = ctx;
|
ctx->peer.connection->data = ctx;
|
||||||
ctx->peer.connection->pool = ctx->pool;
|
ctx->peer.connection->pool = ctx->pool;
|
||||||
|
|
||||||
@@ -1054,8 +1536,10 @@ ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
|
|
||||||
ctx->process = ngx_ssl_ocsp_process_status_line;
|
ctx->process = ngx_ssl_ocsp_process_status_line;
|
||||||
|
|
||||||
|
if (ctx->timeout) {
|
||||||
ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
|
ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
|
||||||
ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
|
ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == NGX_OK) {
|
if (rc == NGX_OK) {
|
||||||
ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
|
ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
|
||||||
@@ -1080,7 +1564,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
|
|||||||
if (wev->timedout) {
|
if (wev->timedout) {
|
||||||
ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
|
ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
|
||||||
"OCSP responder timed out");
|
"OCSP responder timed out");
|
||||||
ngx_ssl_ocsp_error(ctx);
|
ngx_ssl_ocsp_next(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1089,7 +1573,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
|
|||||||
n = ngx_send(c, ctx->request->pos, size);
|
n = ngx_send(c, ctx->request->pos, size);
|
||||||
|
|
||||||
if (n == NGX_ERROR) {
|
if (n == NGX_ERROR) {
|
||||||
ngx_ssl_ocsp_error(ctx);
|
ngx_ssl_ocsp_next(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1111,7 +1595,7 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wev->timer_set) {
|
if (!wev->timer_set && ctx->timeout) {
|
||||||
ngx_add_timer(wev, ctx->timeout);
|
ngx_add_timer(wev, ctx->timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1134,7 +1618,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
|
|||||||
if (rev->timedout) {
|
if (rev->timedout) {
|
||||||
ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
|
ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
|
||||||
"OCSP responder timed out");
|
"OCSP responder timed out");
|
||||||
ngx_ssl_ocsp_error(ctx);
|
ngx_ssl_ocsp_next(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,7 +1642,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
|
|||||||
rc = ctx->process(ctx);
|
rc = ctx->process(ctx);
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
if (rc == NGX_ERROR) {
|
||||||
ngx_ssl_ocsp_error(ctx);
|
ngx_ssl_ocsp_next(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,7 +1673,7 @@ ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
|
|||||||
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
"OCSP responder prematurely closed connection");
|
"OCSP responder prematurely closed connection");
|
||||||
|
|
||||||
ngx_ssl_ocsp_error(ctx);
|
ngx_ssl_ocsp_next(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1831,6 +2315,368 @@ ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
size_t len;
|
||||||
|
X509_STORE *store;
|
||||||
|
const u_char *p;
|
||||||
|
OCSP_CERTID *id;
|
||||||
|
OCSP_RESPONSE *ocsp;
|
||||||
|
OCSP_BASICRESP *basic;
|
||||||
|
ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
|
||||||
|
|
||||||
|
ocsp = NULL;
|
||||||
|
basic = NULL;
|
||||||
|
id = NULL;
|
||||||
|
|
||||||
|
if (ctx->code != 200) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the response */
|
||||||
|
|
||||||
|
len = ctx->response->last - ctx->response->pos;
|
||||||
|
p = ctx->response->pos;
|
||||||
|
|
||||||
|
ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
||||||
|
if (ocsp == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"d2i_OCSP_RESPONSE() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = OCSP_response_status(ocsp);
|
||||||
|
|
||||||
|
if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"OCSP response not successful (%d: %s)",
|
||||||
|
n, OCSP_response_status_str(n));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
basic = OCSP_response_get1_basic(ocsp);
|
||||||
|
if (basic == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"OCSP_response_get1_basic() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
|
||||||
|
if (store == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
|
||||||
|
"SSL_CTX_get_cert_store() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"OCSP_basic_verify() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
|
||||||
|
if (id == NULL) {
|
||||||
|
ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
|
||||||
|
"OCSP_cert_to_id() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OCSP_resp_find_status(basic, id, &ctx->status, NULL, NULL,
|
||||||
|
&thisupdate, &nextupdate)
|
||||||
|
!= 1)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"certificate status not found in the OCSP response");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
|
||||||
|
ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"OCSP_check_validity() failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextupdate) {
|
||||||
|
ctx->valid = ngx_ssl_stapling_time(nextupdate);
|
||||||
|
if (ctx->valid == (time_t) NGX_ERROR) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
|
||||||
|
"invalid nextUpdate time in certificate status");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx->valid = NGX_MAX_TIME_T_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OCSP_CERTID_free(id);
|
||||||
|
OCSP_BASICRESP_free(basic);
|
||||||
|
OCSP_RESPONSE_free(ocsp);
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp response, %s, %uz",
|
||||||
|
OCSP_cert_status_str(ctx->status), len);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
OCSP_CERTID_free(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basic) {
|
||||||
|
OCSP_BASICRESP_free(basic);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocsp) {
|
||||||
|
OCSP_RESPONSE_free(ocsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_ssl_ocsp_cache_t *cache;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
shm_zone->data = data;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
|
||||||
|
if (shm_zone->shm.exists) {
|
||||||
|
shm_zone->data = shpool->data;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_ocsp_cache_t));
|
||||||
|
if (cache == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
shpool->data = cache;
|
||||||
|
shm_zone->data = cache;
|
||||||
|
|
||||||
|
ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
|
||||||
|
ngx_str_rbtree_insert_value);
|
||||||
|
|
||||||
|
ngx_queue_init(&cache->expire_queue);
|
||||||
|
|
||||||
|
len = sizeof(" in OCSP cache \"\"") + shm_zone->shm.name.len;
|
||||||
|
|
||||||
|
shpool->log_ctx = ngx_slab_alloc(shpool, len);
|
||||||
|
if (shpool->log_ctx == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_sprintf(shpool->log_ctx, " in OCSP cache \"%V\"%Z",
|
||||||
|
&shm_zone->shm.name);
|
||||||
|
|
||||||
|
shpool->log_nomem = 0;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
uint32_t hash;
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_ssl_ocsp_cache_t *cache;
|
||||||
|
ngx_ssl_ocsp_cache_node_t *node;
|
||||||
|
|
||||||
|
shm_zone = ctx->shm_zone;
|
||||||
|
|
||||||
|
if (shm_zone == NULL) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_ssl_ocsp_create_key(ctx) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache lookup");
|
||||||
|
|
||||||
|
cache = shm_zone->data;
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
hash = ngx_hash_key(ctx->key.data, ctx->key.len);
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&shpool->mutex);
|
||||||
|
|
||||||
|
node = (ngx_ssl_ocsp_cache_node_t *)
|
||||||
|
ngx_str_rbtree_lookup(&cache->rbtree, &ctx->key, hash);
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
if (node->valid > ngx_time()) {
|
||||||
|
ctx->status = node->status;
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp cache hit, %s",
|
||||||
|
OCSP_cert_status_str(ctx->status));
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_queue_remove(&node->queue);
|
||||||
|
ngx_rbtree_delete(&cache->rbtree, &node->node.node);
|
||||||
|
ngx_slab_free_locked(shpool, node);
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp cache expired");
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache miss");
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
time_t now, valid;
|
||||||
|
uint32_t hash;
|
||||||
|
ngx_queue_t *q;
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
|
ngx_ssl_ocsp_cache_t *cache;
|
||||||
|
ngx_ssl_ocsp_cache_node_t *node;
|
||||||
|
|
||||||
|
shm_zone = ctx->shm_zone;
|
||||||
|
|
||||||
|
if (shm_zone == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
valid = ctx->valid;
|
||||||
|
|
||||||
|
now = ngx_time();
|
||||||
|
|
||||||
|
if (valid < now) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid == NGX_MAX_TIME_T_VALUE) {
|
||||||
|
valid = now + 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp cache store, valid:%T", valid - now);
|
||||||
|
|
||||||
|
cache = shm_zone->data;
|
||||||
|
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
hash = ngx_hash_key(ctx->key.data, ctx->key.len);
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&shpool->mutex);
|
||||||
|
|
||||||
|
node = ngx_slab_calloc_locked(shpool,
|
||||||
|
sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
|
||||||
|
if (node == NULL) {
|
||||||
|
|
||||||
|
if (!ngx_queue_empty(&cache->expire_queue)) {
|
||||||
|
q = ngx_queue_last(&cache->expire_queue);
|
||||||
|
node = ngx_queue_data(q, ngx_ssl_ocsp_cache_node_t, queue);
|
||||||
|
|
||||||
|
ngx_rbtree_delete(&cache->rbtree, &node->node.node);
|
||||||
|
ngx_queue_remove(q);
|
||||||
|
ngx_slab_free_locked(shpool, node);
|
||||||
|
|
||||||
|
node = ngx_slab_alloc_locked(shpool,
|
||||||
|
sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
|
||||||
|
"could not allocate new entry%s", shpool->log_ctx);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node->node.str.len = ctx->key.len;
|
||||||
|
node->node.str.data = (u_char *) node + sizeof(ngx_ssl_ocsp_cache_node_t);
|
||||||
|
ngx_memcpy(node->node.str.data, ctx->key.data, ctx->key.len);
|
||||||
|
node->node.node.key = hash;
|
||||||
|
node->status = ctx->status;
|
||||||
|
node->valid = valid;
|
||||||
|
|
||||||
|
ngx_rbtree_insert(&cache->rbtree, &node->node.node);
|
||||||
|
ngx_queue_insert_head(&cache->expire_queue, &node->queue);
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
X509_NAME *name;
|
||||||
|
ASN1_INTEGER *serial;
|
||||||
|
|
||||||
|
p = ngx_pnalloc(ctx->pool, 60);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->key.data = p;
|
||||||
|
ctx->key.len = 60;
|
||||||
|
|
||||||
|
name = X509_get_subject_name(ctx->issuer);
|
||||||
|
if (X509_NAME_digest(name, EVP_sha1(), p, NULL) == 0) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 20;
|
||||||
|
|
||||||
|
if (X509_pubkey_digest(ctx->issuer, EVP_sha1(), p, NULL) == 0) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 20;
|
||||||
|
|
||||||
|
serial = X509_get_serialNumber(ctx->cert);
|
||||||
|
if (serial->length > 20) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_cpymem(p, serial->data, serial->length);
|
||||||
|
ngx_memzero(p, 20 - serial->length);
|
||||||
|
|
||||||
|
#if (NGX_DEBUG)
|
||||||
|
{
|
||||||
|
u_char buf[120];
|
||||||
|
|
||||||
|
ngx_hex_dump(buf, ctx->key.data, ctx->key.len);
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
|
||||||
|
"ssl ocsp key %*s", sizeof(buf), buf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u_char *
|
static u_char *
|
||||||
ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
||||||
{
|
{
|
||||||
@@ -1891,4 +2737,50 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
|
||||||
|
ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||||
|
"\"ssl_ocsp\" is not supported on this platform");
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
|
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_validate(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -172,7 +172,11 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (p->upstream->read->available == 0
|
if (p->upstream->read->available == 0
|
||||||
&& p->upstream->read->pending_eof)
|
&& p->upstream->read->pending_eof
|
||||||
|
#if (NGX_SSL)
|
||||||
|
&& !p->upstream->ssl
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
p->upstream->read->ready = 0;
|
p->upstream->read->ready = 0;
|
||||||
p->upstream->read->eof = 1;
|
p->upstream->read->eof = 1;
|
||||||
@@ -956,6 +960,22 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->upstream_done) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
|
||||||
|
"input data after close");
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->length == 0) {
|
||||||
|
p->upstream_done = 1;
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
||||||
if (cl == NULL) {
|
if (cl == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@@ -983,6 +1003,18 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b->last - b->pos > p->length) {
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
b->last = b->pos + p->length;
|
||||||
|
p->upstream_done = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
p->length -= b->last - b->pos;
|
p->length -= b->last - b->pos;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
ngx_queue_t ngx_posted_accept_events;
|
ngx_queue_t ngx_posted_accept_events;
|
||||||
|
ngx_queue_t ngx_posted_next_events;
|
||||||
ngx_queue_t ngx_posted_events;
|
ngx_queue_t ngx_posted_events;
|
||||||
|
|
||||||
|
|
||||||
@@ -33,3 +34,27 @@ ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted)
|
|||||||
ev->handler(ev);
|
ev->handler(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ngx_event_move_posted_next(ngx_cycle_t *cycle)
|
||||||
|
{
|
||||||
|
ngx_queue_t *q;
|
||||||
|
ngx_event_t *ev;
|
||||||
|
|
||||||
|
for (q = ngx_queue_head(&ngx_posted_next_events);
|
||||||
|
q != ngx_queue_sentinel(&ngx_posted_next_events);
|
||||||
|
q = ngx_queue_next(q))
|
||||||
|
{
|
||||||
|
ev = ngx_queue_data(q, ngx_event_t, queue);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
||||||
|
"posted next event %p", ev);
|
||||||
|
|
||||||
|
ev->ready = 1;
|
||||||
|
ev->available = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_queue_add(&ngx_posted_events, &ngx_posted_next_events);
|
||||||
|
ngx_queue_init(&ngx_posted_next_events);
|
||||||
|
}
|
||||||
@@ -39,9 +39,11 @@
|
|||||||
|
|
||||||
|
|
||||||
void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted);
|
void ngx_event_process_posted(ngx_cycle_t *cycle, ngx_queue_t *posted);
|
||||||
|
void ngx_event_move_posted_next(ngx_cycle_t *cycle);
|
||||||
|
|
||||||
|
|
||||||
extern ngx_queue_t ngx_posted_accept_events;
|
extern ngx_queue_t ngx_posted_accept_events;
|
||||||
|
extern ngx_queue_t ngx_posted_next_events;
|
||||||
extern ngx_queue_t ngx_posted_events;
|
extern ngx_queue_t ngx_posted_events;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
|
|||||||
ngx_str_t *passwd, ngx_str_t *realm);
|
ngx_str_t *passwd, ngx_str_t *realm);
|
||||||
static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
|
||||||
ngx_str_t *realm);
|
ngx_str_t *realm);
|
||||||
static void ngx_http_auth_basic_close(ngx_file_t *file);
|
|
||||||
static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
|
static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
|
static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
|
||||||
void *parent, void *child);
|
void *parent, void *child);
|
||||||
@@ -177,8 +176,8 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||||||
offset);
|
offset);
|
||||||
|
|
||||||
if (n == NGX_ERROR) {
|
if (n == NGX_ERROR) {
|
||||||
ngx_http_auth_basic_close(&file);
|
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
@@ -219,12 +218,11 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||||||
if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
|
if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
|
||||||
buf[i] = '\0';
|
buf[i] = '\0';
|
||||||
|
|
||||||
ngx_http_auth_basic_close(&file);
|
|
||||||
|
|
||||||
pwd.len = i - passwd;
|
pwd.len = i - passwd;
|
||||||
pwd.data = &buf[passwd];
|
pwd.data = &buf[passwd];
|
||||||
|
|
||||||
return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
|
rc = ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -251,8 +249,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||||||
offset += n;
|
offset += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_http_auth_basic_close(&file);
|
|
||||||
|
|
||||||
if (state == sw_passwd) {
|
if (state == sw_passwd) {
|
||||||
pwd.len = i - passwd;
|
pwd.len = i - passwd;
|
||||||
pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
|
pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
|
||||||
@@ -262,14 +258,26 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
|
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
|
||||||
|
|
||||||
return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
|
rc = ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"user \"%V\" was not found in \"%s\"",
|
"user \"%V\" was not found in \"%s\"",
|
||||||
&r->headers_in.user, user_file.data);
|
&r->headers_in.user, user_file.data);
|
||||||
|
|
||||||
return ngx_http_auth_basic_set_realm(r, &realm);
|
rc = ngx_http_auth_basic_set_realm(r, &realm);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
|
||||||
|
ngx_close_file_n " \"%s\" failed", user_file.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_explicit_memzero(buf, NGX_HTTP_AUTH_BUF_SIZE);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -338,15 +346,6 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
|
|||||||
return NGX_HTTP_UNAUTHORIZED;
|
return NGX_HTTP_UNAUTHORIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_http_auth_basic_close(ngx_file_t *file)
|
|
||||||
{
|
|
||||||
if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, file->log, ngx_errno,
|
|
||||||
ngx_close_file_n " \"%s\" failed", file->name.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
|
ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx,
|
|||||||
static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
|
static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
|
||||||
static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
|
static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
|
||||||
ngx_int_t not_found, char *failed, u_char *path);
|
ngx_int_t not_found, char *failed, u_char *path);
|
||||||
static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path);
|
static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r);
|
||||||
static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf);
|
static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
|
static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
|
||||||
void *parent, void *child);
|
void *parent, void *child);
|
||||||
@@ -285,7 +285,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == NGX_HTTP_CREATED) {
|
if (status == NGX_HTTP_CREATED) {
|
||||||
if (ngx_http_dav_location(r, path.data) != NGX_OK) {
|
if (ngx_http_dav_location(r) != NGX_OK) {
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ ngx_http_dav_delete_handler(ngx_http_request_t *r)
|
|||||||
ngx_file_info_t fi;
|
ngx_file_info_t fi;
|
||||||
ngx_http_dav_loc_conf_t *dlcf;
|
ngx_http_dav_loc_conf_t *dlcf;
|
||||||
|
|
||||||
if (r->headers_in.content_length_n > 0) {
|
if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"DELETE with body is unsupported");
|
"DELETE with body is unsupported");
|
||||||
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
||||||
@@ -495,7 +495,7 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
|
|||||||
size_t root;
|
size_t root;
|
||||||
ngx_str_t path;
|
ngx_str_t path;
|
||||||
|
|
||||||
if (r->headers_in.content_length_n > 0) {
|
if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"MKCOL with body is unsupported");
|
"MKCOL with body is unsupported");
|
||||||
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
||||||
@@ -513,7 +513,6 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*(p - 1) = '\0';
|
*(p - 1) = '\0';
|
||||||
r->uri.len--;
|
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"http mkcol path: \"%s\"", path.data);
|
"http mkcol path: \"%s\"", path.data);
|
||||||
@@ -521,7 +520,7 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
|
|||||||
if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access))
|
if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access))
|
||||||
!= NGX_FILE_ERROR)
|
!= NGX_FILE_ERROR)
|
||||||
{
|
{
|
||||||
if (ngx_http_dav_location(r, path.data) != NGX_OK) {
|
if (ngx_http_dav_location(r) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +549,9 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_dav_copy_ctx_t copy;
|
ngx_http_dav_copy_ctx_t copy;
|
||||||
ngx_http_dav_loc_conf_t *dlcf;
|
ngx_http_dav_loc_conf_t *dlcf;
|
||||||
|
|
||||||
if (r->headers_in.content_length_n > 0) {
|
if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"COPY and MOVE with body are unsupported");
|
||||||
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,35 +1070,16 @@ ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found,
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_dav_location(ngx_http_request_t *r, u_char *path)
|
ngx_http_dav_location(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
u_char *location;
|
|
||||||
ngx_http_core_loc_conf_t *clcf;
|
|
||||||
|
|
||||||
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
|
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
|
||||||
if (r->headers_out.location == NULL) {
|
if (r->headers_out.location == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
|
||||||
|
|
||||||
if (!clcf->alias && clcf->root_lengths == NULL) {
|
|
||||||
location = path + clcf->root.len;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
location = ngx_pnalloc(r->pool, r->uri.len);
|
|
||||||
if (location == NULL) {
|
|
||||||
ngx_http_clear_location(r);
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memcpy(location, r->uri.data, r->uri.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
r->headers_out.location->hash = 1;
|
r->headers_out.location->hash = 1;
|
||||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||||
r->headers_out.location->value.len = r->uri.len;
|
r->headers_out.location->value = r->uri;
|
||||||
r->headers_out.location->value.data = location;
|
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,12 +81,15 @@ typedef struct {
|
|||||||
size_t length;
|
size_t length;
|
||||||
size_t padding;
|
size_t padding;
|
||||||
|
|
||||||
|
off_t rest;
|
||||||
|
|
||||||
ngx_chain_t *free;
|
ngx_chain_t *free;
|
||||||
ngx_chain_t *busy;
|
ngx_chain_t *busy;
|
||||||
|
|
||||||
unsigned fastcgi_stdout:1;
|
unsigned fastcgi_stdout:1;
|
||||||
unsigned large_stderr:1;
|
unsigned large_stderr:1;
|
||||||
unsigned header_sent:1;
|
unsigned header_sent:1;
|
||||||
|
unsigned closed:1;
|
||||||
|
|
||||||
ngx_array_t *split_parts;
|
ngx_array_t *split_parts;
|
||||||
|
|
||||||
@@ -2076,13 +2079,31 @@ static ngx_int_t
|
|||||||
ngx_http_fastcgi_input_filter_init(void *data)
|
ngx_http_fastcgi_input_filter_init(void *data)
|
||||||
{
|
{
|
||||||
ngx_http_request_t *r = data;
|
ngx_http_request_t *r = data;
|
||||||
|
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
ngx_http_fastcgi_ctx_t *f;
|
||||||
ngx_http_fastcgi_loc_conf_t *flcf;
|
ngx_http_fastcgi_loc_conf_t *flcf;
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
|
||||||
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
|
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
|
||||||
|
|
||||||
r->upstream->pipe->length = flcf->keep_conn ?
|
u->pipe->length = flcf->keep_conn ?
|
||||||
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
|
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
|
||||||
|
|
||||||
|
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||||
|
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
|
||||||
|
{
|
||||||
|
f->rest = 0;
|
||||||
|
|
||||||
|
} else if (r->method == NGX_HTTP_HEAD) {
|
||||||
|
f->rest = -2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
f->rest = u->headers_in.content_length_n;
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2106,6 +2127,15 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
|
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
|
||||||
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
|
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
|
||||||
|
|
||||||
|
if (p->upstream_done || f->closed) {
|
||||||
|
r->upstream->keepalive = 0;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||||
|
"http fastcgi data after close");
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
prev = &buf->shadow;
|
prev = &buf->shadow;
|
||||||
|
|
||||||
@@ -2128,13 +2158,25 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
|
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
|
||||||
f->state = ngx_http_fastcgi_st_padding;
|
f->state = ngx_http_fastcgi_st_padding;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||||
|
"http fastcgi closed stdout");
|
||||||
|
|
||||||
|
if (f->rest > 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, p->log, 0,
|
||||||
|
"upstream prematurely closed "
|
||||||
|
"FastCGI stdout");
|
||||||
|
|
||||||
|
p->upstream_error = 1;
|
||||||
|
p->upstream_eof = 0;
|
||||||
|
f->closed = 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!flcf->keep_conn) {
|
if (!flcf->keep_conn) {
|
||||||
p->upstream_done = 1;
|
p->upstream_done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
|
||||||
"http fastcgi closed stdout");
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2143,6 +2185,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||||
"http fastcgi sent end request");
|
"http fastcgi sent end request");
|
||||||
|
|
||||||
|
if (f->rest > 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, p->log, 0,
|
||||||
|
"upstream prematurely closed "
|
||||||
|
"FastCGI request");
|
||||||
|
|
||||||
|
p->upstream_error = 1;
|
||||||
|
p->upstream_eof = 0;
|
||||||
|
f->closed = 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!flcf->keep_conn) {
|
if (!flcf->keep_conn) {
|
||||||
p->upstream_done = 1;
|
p->upstream_done = 1;
|
||||||
break;
|
break;
|
||||||
@@ -2252,6 +2306,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->rest == -2) {
|
||||||
|
f->rest = r->upstream->headers_in.content_length_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->rest == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
p->upstream_done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
||||||
if (cl == NULL) {
|
if (cl == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@@ -2289,15 +2355,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
f->pos += f->length;
|
f->pos += f->length;
|
||||||
b->last = f->pos;
|
b->last = f->pos;
|
||||||
|
|
||||||
continue;
|
} else {
|
||||||
|
f->length -= f->last - f->pos;
|
||||||
|
f->pos = f->last;
|
||||||
|
b->last = f->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->length -= f->last - f->pos;
|
if (f->rest > 0) {
|
||||||
|
|
||||||
b->last = f->last;
|
if (b->last - b->pos > f->rest) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
b->last = b->pos + f->rest;
|
||||||
|
p->upstream_done = 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->rest -= b->last - b->pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flcf->keep_conn) {
|
if (flcf->keep_conn) {
|
||||||
@@ -2391,6 +2469,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
|
|||||||
|
|
||||||
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
|
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
|
||||||
|
|
||||||
|
if (f->rest > 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream prematurely closed "
|
||||||
|
"FastCGI request");
|
||||||
|
u->error = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (f->pos + f->padding < f->last) {
|
if (f->pos + f->padding < f->last) {
|
||||||
u->length = 0;
|
u->length = 0;
|
||||||
break;
|
break;
|
||||||
@@ -2486,6 +2572,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->rest == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
u->length = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
|
cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
|
||||||
if (cl == NULL) {
|
if (cl == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@@ -2510,15 +2604,29 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
|
|||||||
f->pos += f->length;
|
f->pos += f->length;
|
||||||
b->last = f->pos;
|
b->last = f->pos;
|
||||||
|
|
||||||
continue;
|
} else {
|
||||||
|
f->length -= f->last - f->pos;
|
||||||
|
f->pos = f->last;
|
||||||
|
b->last = f->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->length -= f->last - f->pos;
|
if (f->rest > 0) {
|
||||||
b->last = f->last;
|
|
||||||
|
if (b->last - b->pos > f->rest) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
b->last = b->pos + f->rest;
|
||||||
|
u->length = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f->rest -= b->last - b->pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ typedef struct {
|
|||||||
ngx_str_t host;
|
ngx_str_t host;
|
||||||
ngx_uint_t host_set;
|
ngx_uint_t host_set;
|
||||||
|
|
||||||
|
ngx_array_t *grpc_lengths;
|
||||||
|
ngx_array_t *grpc_values;
|
||||||
|
|
||||||
#if (NGX_HTTP_SSL)
|
#if (NGX_HTTP_SSL)
|
||||||
ngx_uint_t ssl;
|
ngx_uint_t ssl;
|
||||||
ngx_uint_t ssl_protocols;
|
ngx_uint_t ssl_protocols;
|
||||||
@@ -81,6 +84,8 @@ typedef struct {
|
|||||||
ngx_uint_t pings;
|
ngx_uint_t pings;
|
||||||
ngx_uint_t settings;
|
ngx_uint_t settings;
|
||||||
|
|
||||||
|
off_t length;
|
||||||
|
|
||||||
ssize_t send_window;
|
ssize_t send_window;
|
||||||
size_t recv_window;
|
size_t recv_window;
|
||||||
|
|
||||||
@@ -117,8 +122,11 @@ typedef struct {
|
|||||||
unsigned end_stream:1;
|
unsigned end_stream:1;
|
||||||
unsigned done:1;
|
unsigned done:1;
|
||||||
unsigned status:1;
|
unsigned status:1;
|
||||||
|
unsigned rst:1;
|
||||||
|
|
||||||
ngx_http_request_t *request;
|
ngx_http_request_t *request;
|
||||||
|
|
||||||
|
ngx_str_t host;
|
||||||
} ngx_http_grpc_ctx_t;
|
} ngx_http_grpc_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -135,6 +143,8 @@ typedef struct {
|
|||||||
} ngx_http_grpc_frame_t;
|
} ngx_http_grpc_frame_t;
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_grpc_eval(ngx_http_request_t *r,
|
||||||
|
ngx_http_grpc_ctx_t *ctx, ngx_http_grpc_loc_conf_t *glcf);
|
||||||
static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in);
|
static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in);
|
||||||
@@ -524,10 +534,22 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
|
|||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->request = r;
|
||||||
|
|
||||||
|
ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);
|
||||||
|
|
||||||
glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
|
glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
|
||||||
|
|
||||||
u = r->upstream;
|
u = r->upstream;
|
||||||
|
|
||||||
|
if (glcf->grpc_lengths == NULL) {
|
||||||
|
ctx->host = glcf->host;
|
||||||
|
|
||||||
#if (NGX_HTTP_SSL)
|
#if (NGX_HTTP_SSL)
|
||||||
u->ssl = (glcf->upstream.ssl != NULL);
|
u->ssl = (glcf->upstream.ssl != NULL);
|
||||||
|
|
||||||
@@ -541,6 +563,12 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
|
|||||||
ngx_str_set(&u->schema, "grpc://");
|
ngx_str_set(&u->schema, "grpc://");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (ngx_http_grpc_eval(r, ctx, glcf) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module;
|
u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module;
|
||||||
|
|
||||||
u->conf = &glcf->upstream;
|
u->conf = &glcf->upstream;
|
||||||
@@ -551,15 +579,6 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
|
|||||||
u->abort_request = ngx_http_grpc_abort_request;
|
u->abort_request = ngx_http_grpc_abort_request;
|
||||||
u->finalize_request = ngx_http_grpc_finalize_request;
|
u->finalize_request = ngx_http_grpc_finalize_request;
|
||||||
|
|
||||||
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
|
|
||||||
if (ctx == NULL) {
|
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->request = r;
|
|
||||||
|
|
||||||
ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);
|
|
||||||
|
|
||||||
u->input_filter_init = ngx_http_grpc_filter_init;
|
u->input_filter_init = ngx_http_grpc_filter_init;
|
||||||
u->input_filter = ngx_http_grpc_filter;
|
u->input_filter = ngx_http_grpc_filter;
|
||||||
u->input_filter_ctx = ctx;
|
u->input_filter_ctx = ctx;
|
||||||
@@ -576,6 +595,103 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_grpc_eval(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
|
||||||
|
ngx_http_grpc_loc_conf_t *glcf)
|
||||||
|
{
|
||||||
|
size_t add;
|
||||||
|
ngx_url_t url;
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
|
||||||
|
ngx_memzero(&url, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
if (ngx_http_script_run(r, &url.url, glcf->grpc_lengths->elts, 0,
|
||||||
|
glcf->grpc_values->elts)
|
||||||
|
== NULL)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.url.len > 7
|
||||||
|
&& ngx_strncasecmp(url.url.data, (u_char *) "grpc://", 7) == 0)
|
||||||
|
{
|
||||||
|
add = 7;
|
||||||
|
|
||||||
|
} else if (url.url.len > 8
|
||||||
|
&& ngx_strncasecmp(url.url.data, (u_char *) "grpcs://", 8) == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (NGX_HTTP_SSL)
|
||||||
|
add = 8;
|
||||||
|
r->upstream->ssl = 1;
|
||||||
|
#else
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"grpcs protocol requires SSL support");
|
||||||
|
return NGX_ERROR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else {
|
||||||
|
add = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
u->schema.len = add;
|
||||||
|
u->schema.data = url.url.data;
|
||||||
|
|
||||||
|
url.url.data += add;
|
||||||
|
url.url.len -= add;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_str_set(&u->schema, "grpc://");
|
||||||
|
}
|
||||||
|
|
||||||
|
url.no_resolve = 1;
|
||||||
|
|
||||||
|
if (ngx_parse_url(r->pool, &url) != NGX_OK) {
|
||||||
|
if (url.err) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"%s in upstream \"%V\"", url.err, &url.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
|
||||||
|
if (u->resolved == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.addrs) {
|
||||||
|
u->resolved->sockaddr = url.addrs[0].sockaddr;
|
||||||
|
u->resolved->socklen = url.addrs[0].socklen;
|
||||||
|
u->resolved->name = url.addrs[0].name;
|
||||||
|
u->resolved->naddrs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->resolved->host = url.host;
|
||||||
|
u->resolved->port = url.port;
|
||||||
|
u->resolved->no_port = url.no_port;
|
||||||
|
|
||||||
|
if (url.family != AF_UNIX) {
|
||||||
|
|
||||||
|
if (url.no_port) {
|
||||||
|
ctx->host = url.host;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx->host.len = url.host.len + 1 + url.port_text.len;
|
||||||
|
ctx->host.data = url.host.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_str_set(&ctx->host, "localhost");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_grpc_create_request(ngx_http_request_t *r)
|
ngx_http_grpc_create_request(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
@@ -587,6 +703,7 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
|
|||||||
ngx_chain_t *cl, *body;
|
ngx_chain_t *cl, *body;
|
||||||
ngx_list_part_t *part;
|
ngx_list_part_t *part;
|
||||||
ngx_table_elt_t *header;
|
ngx_table_elt_t *header;
|
||||||
|
ngx_http_grpc_ctx_t *ctx;
|
||||||
ngx_http_upstream_t *u;
|
ngx_http_upstream_t *u;
|
||||||
ngx_http_grpc_frame_t *f;
|
ngx_http_grpc_frame_t *f;
|
||||||
ngx_http_script_code_pt code;
|
ngx_http_script_code_pt code;
|
||||||
@@ -598,6 +715,8 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
|
|||||||
|
|
||||||
glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
|
glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
|
||||||
|
|
||||||
|
ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);
|
||||||
|
|
||||||
len = sizeof(ngx_http_grpc_connection_start) - 1
|
len = sizeof(ngx_http_grpc_connection_start) - 1
|
||||||
+ sizeof(ngx_http_grpc_frame_t); /* headers frame */
|
+ sizeof(ngx_http_grpc_frame_t); /* headers frame */
|
||||||
|
|
||||||
@@ -637,10 +756,10 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
|
|||||||
/* :authority header */
|
/* :authority header */
|
||||||
|
|
||||||
if (!glcf->host_set) {
|
if (!glcf->host_set) {
|
||||||
len += 1 + NGX_HTTP_V2_INT_OCTETS + glcf->host.len;
|
len += 1 + NGX_HTTP_V2_INT_OCTETS + ctx->host.len;
|
||||||
|
|
||||||
if (tmp_len < glcf->host.len) {
|
if (tmp_len < ctx->host.len) {
|
||||||
tmp_len = glcf->host.len;
|
tmp_len = ctx->host.len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,7 +904,7 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (NGX_HTTP_SSL)
|
#if (NGX_HTTP_SSL)
|
||||||
if (glcf->ssl) {
|
if (u->ssl) {
|
||||||
*b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);
|
*b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
@@ -846,11 +965,11 @@ ngx_http_grpc_create_request(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if (!glcf->host_set) {
|
if (!glcf->host_set) {
|
||||||
*b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
|
*b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
|
||||||
b->last = ngx_http_v2_write_value(b->last, glcf->host.data,
|
b->last = ngx_http_v2_write_value(b->last, ctx->host.data,
|
||||||
glcf->host.len, tmp);
|
ctx->host.len, tmp);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"grpc header: \":authority: %V\"", &glcf->host);
|
"grpc header: \":authority: %V\"", &ctx->host);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
|
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
|
||||||
@@ -1089,6 +1208,7 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
|
|||||||
ctx->end_stream = 0;
|
ctx->end_stream = 0;
|
||||||
ctx->done = 0;
|
ctx->done = 0;
|
||||||
ctx->status = 0;
|
ctx->status = 0;
|
||||||
|
ctx->rst = 0;
|
||||||
ctx->connection = NULL;
|
ctx->connection = NULL;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@@ -1835,10 +1955,28 @@ ngx_http_grpc_filter_init(void *data)
|
|||||||
r = ctx->request;
|
r = ctx->request;
|
||||||
u = r->upstream;
|
u = r->upstream;
|
||||||
|
|
||||||
u->length = 1;
|
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||||
|
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
|
||||||
|
|| r->method == NGX_HTTP_HEAD)
|
||||||
|
{
|
||||||
|
ctx->length = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx->length = u->headers_in.content_length_n;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->end_stream) {
|
if (ctx->end_stream) {
|
||||||
|
|
||||||
|
if (ctx->length > 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream prematurely closed stream");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
u->length = 0;
|
u->length = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
u->length = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@@ -1881,6 +2019,12 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
|||||||
|
|
||||||
if (ctx->done) {
|
if (ctx->done) {
|
||||||
|
|
||||||
|
if (ctx->length > 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream prematurely closed stream");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have finished parsing the response and the
|
* We have finished parsing the response and the
|
||||||
* remaining control frames. If there are unsent
|
* remaining control frames. If there are unsent
|
||||||
@@ -1934,6 +2078,17 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->length != -1) {
|
||||||
|
if ((off_t) ctx->rest > ctx->length) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream sent response body larger "
|
||||||
|
"than indicated content length");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->length -= ctx->rest;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->rest > ctx->recv_window) {
|
if (ctx->rest > ctx->recv_window) {
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"upstream violated stream flow control, "
|
"upstream violated stream flow control, "
|
||||||
@@ -1972,7 +2127,10 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->stream_id && ctx->done) {
|
if (ctx->stream_id && ctx->done
|
||||||
|
&& ctx->type != NGX_HTTP_V2_RST_STREAM_FRAME
|
||||||
|
&& ctx->type != NGX_HTTP_V2_WINDOW_UPDATE_FRAME)
|
||||||
|
{
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"upstream sent frame for closed stream %ui",
|
"upstream sent frame for closed stream %ui",
|
||||||
ctx->stream_id);
|
ctx->stream_id);
|
||||||
@@ -2015,13 +2173,23 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->error || !ctx->done) {
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"upstream rejected request with error %ui",
|
"upstream rejected request with error %ui",
|
||||||
ctx->error);
|
ctx->error);
|
||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->rst) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream sent frame for closed stream %ui",
|
||||||
|
ctx->stream_id);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->rst = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
||||||
|
|
||||||
rc = ngx_http_grpc_parse_goaway(r, ctx, b);
|
rc = ngx_http_grpc_parse_goaway(r, ctx, b);
|
||||||
@@ -4319,15 +4487,23 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
if (clcf->noname && conf->upstream.upstream == NULL) {
|
if (clcf->noname
|
||||||
|
&& conf->upstream.upstream == NULL && conf->grpc_lengths == NULL)
|
||||||
|
{
|
||||||
conf->upstream.upstream = prev->upstream.upstream;
|
conf->upstream.upstream = prev->upstream.upstream;
|
||||||
conf->host = prev->host;
|
conf->host = prev->host;
|
||||||
|
|
||||||
|
conf->grpc_lengths = prev->grpc_lengths;
|
||||||
|
conf->grpc_values = prev->grpc_values;
|
||||||
|
|
||||||
#if (NGX_HTTP_SSL)
|
#if (NGX_HTTP_SSL)
|
||||||
conf->upstream.ssl = prev->upstream.ssl;
|
conf->upstream.ssl = prev->upstream.ssl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clcf->lmt_excpt && clcf->handler == NULL && conf->upstream.upstream) {
|
if (clcf->lmt_excpt && clcf->handler == NULL
|
||||||
|
&& (conf->upstream.upstream || conf->grpc_lengths))
|
||||||
|
{
|
||||||
clcf->handler = ngx_http_grpc_handler;
|
clcf->handler = ngx_http_grpc_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4540,15 +4716,51 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
size_t add;
|
size_t add;
|
||||||
ngx_str_t *value, *url;
|
ngx_str_t *value, *url;
|
||||||
ngx_url_t u;
|
ngx_url_t u;
|
||||||
|
ngx_uint_t n;
|
||||||
ngx_http_core_loc_conf_t *clcf;
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
ngx_http_script_compile_t sc;
|
||||||
|
|
||||||
if (glcf->upstream.upstream) {
|
if (glcf->upstream.upstream || glcf->grpc_lengths) {
|
||||||
return "is duplicate";
|
return "is duplicate";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
|
clcf->handler = ngx_http_grpc_handler;
|
||||||
|
|
||||||
|
if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
|
||||||
|
clcf->auto_redirect = 1;
|
||||||
|
}
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
url = &value[1];
|
url = &value[1];
|
||||||
|
|
||||||
|
n = ngx_http_script_variables_count(url);
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
|
||||||
|
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
|
||||||
|
|
||||||
|
sc.cf = cf;
|
||||||
|
sc.source = url;
|
||||||
|
sc.lengths = &glcf->grpc_lengths;
|
||||||
|
sc.values = &glcf->grpc_values;
|
||||||
|
sc.variables = n;
|
||||||
|
sc.complete_lengths = 1;
|
||||||
|
sc.complete_values = 1;
|
||||||
|
|
||||||
|
if (ngx_http_script_compile(&sc) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_HTTP_SSL)
|
||||||
|
glcf->ssl = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) {
|
if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) {
|
||||||
add = 7;
|
add = 7;
|
||||||
|
|
||||||
@@ -4593,14 +4805,6 @@ ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
ngx_str_set(&glcf->host, "localhost");
|
ngx_str_set(&glcf->host, "localhost");
|
||||||
}
|
}
|
||||||
|
|
||||||
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
|
||||||
|
|
||||||
clcf->handler = ngx_http_grpc_handler;
|
|
||||||
|
|
||||||
if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
|
|
||||||
clcf->auto_redirect = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -778,7 +778,7 @@ ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
|
|||||||
|
|
||||||
ctx->out_buf->last = ctx->zstream.next_out;
|
ctx->out_buf->last = ctx->zstream.next_out;
|
||||||
|
|
||||||
if (ctx->zstream.avail_out == 0) {
|
if (ctx->zstream.avail_out == 0 && rc != Z_STREAM_END) {
|
||||||
|
|
||||||
/* zlib wants to output some more gzipped data */
|
/* zlib wants to output some more gzipped data */
|
||||||
|
|
||||||
@@ -868,6 +868,7 @@ ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
|
|||||||
ngx_http_gzip_ctx_t *ctx)
|
ngx_http_gzip_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
ngx_buf_t *b;
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *cl;
|
||||||
|
|
||||||
ctx->zin = ctx->zstream.total_in;
|
ctx->zin = ctx->zstream.total_in;
|
||||||
@@ -888,13 +889,19 @@ ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl->buf = ctx->out_buf;
|
b = ctx->out_buf;
|
||||||
|
|
||||||
|
if (ngx_buf_size(b) == 0) {
|
||||||
|
b->temporary = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->last_buf = 1;
|
||||||
|
|
||||||
|
cl->buf = b;
|
||||||
cl->next = NULL;
|
cl->next = NULL;
|
||||||
*ctx->last_out = cl;
|
*ctx->last_out = cl;
|
||||||
ctx->last_out = &cl->next;
|
ctx->last_out = &cl->next;
|
||||||
|
|
||||||
ctx->out_buf->last_buf = 1;
|
|
||||||
|
|
||||||
ctx->zstream.avail_in = 0;
|
ctx->zstream.avail_in = 0;
|
||||||
ctx->zstream.avail_out = 0;
|
ctx->zstream.avail_out = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
name = ngx_http_map_uri_to_path(r, &path, &root, reserve);
|
name = ngx_http_map_uri_to_path(r, &path, &root, reserve);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocated = path.data + path.len - name;
|
allocated = path.data + path.len - name;
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
#include <ngx_http.h>
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_HTTP_LIMIT_CONN_PASSED 1
|
||||||
|
#define NGX_HTTP_LIMIT_CONN_REJECTED 2
|
||||||
|
#define NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN 3
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_char color;
|
u_char color;
|
||||||
u_char len;
|
u_char len;
|
||||||
@@ -25,7 +30,14 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_rbtree_t *rbtree;
|
ngx_rbtree_t rbtree;
|
||||||
|
ngx_rbtree_node_t sentinel;
|
||||||
|
} ngx_http_limit_conn_shctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_http_limit_conn_shctx_t *sh;
|
||||||
|
ngx_slab_pool_t *shpool;
|
||||||
ngx_http_complex_value_t key;
|
ngx_http_complex_value_t key;
|
||||||
} ngx_http_limit_conn_ctx_t;
|
} ngx_http_limit_conn_ctx_t;
|
||||||
|
|
||||||
@@ -40,6 +52,7 @@ typedef struct {
|
|||||||
ngx_array_t limits;
|
ngx_array_t limits;
|
||||||
ngx_uint_t log_level;
|
ngx_uint_t log_level;
|
||||||
ngx_uint_t status_code;
|
ngx_uint_t status_code;
|
||||||
|
ngx_flag_t dry_run;
|
||||||
} ngx_http_limit_conn_conf_t;
|
} ngx_http_limit_conn_conf_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -48,6 +61,8 @@ static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree,
|
|||||||
static void ngx_http_limit_conn_cleanup(void *data);
|
static void ngx_http_limit_conn_cleanup(void *data);
|
||||||
static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
|
static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf);
|
static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
|
static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
|
||||||
void *child);
|
void *child);
|
||||||
@@ -55,6 +70,7 @@ static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||||||
void *conf);
|
void *conf);
|
||||||
static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
static ngx_int_t ngx_http_limit_conn_add_variables(ngx_conf_t *cf);
|
||||||
static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf);
|
static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
|
||||||
@@ -102,12 +118,19 @@ static ngx_command_t ngx_http_limit_conn_commands[] = {
|
|||||||
offsetof(ngx_http_limit_conn_conf_t, status_code),
|
offsetof(ngx_http_limit_conn_conf_t, status_code),
|
||||||
&ngx_http_limit_conn_status_bounds },
|
&ngx_http_limit_conn_status_bounds },
|
||||||
|
|
||||||
|
{ ngx_string("limit_conn_dry_run"),
|
||||||
|
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_limit_conn_conf_t, dry_run),
|
||||||
|
NULL },
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static ngx_http_module_t ngx_http_limit_conn_module_ctx = {
|
static ngx_http_module_t ngx_http_limit_conn_module_ctx = {
|
||||||
NULL, /* preconfiguration */
|
ngx_http_limit_conn_add_variables, /* preconfiguration */
|
||||||
ngx_http_limit_conn_init, /* postconfiguration */
|
ngx_http_limit_conn_init, /* postconfiguration */
|
||||||
|
|
||||||
NULL, /* create main configuration */
|
NULL, /* create main configuration */
|
||||||
@@ -137,6 +160,22 @@ ngx_module_t ngx_http_limit_conn_module = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_variable_t ngx_http_limit_conn_vars[] = {
|
||||||
|
|
||||||
|
{ ngx_string("limit_conn_status"), NULL,
|
||||||
|
ngx_http_limit_conn_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
|
||||||
|
|
||||||
|
ngx_http_null_variable
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_str_t ngx_http_limit_conn_status[] = {
|
||||||
|
ngx_string("PASSED"),
|
||||||
|
ngx_string("REJECTED"),
|
||||||
|
ngx_string("REJECTED_DRY_RUN")
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
@@ -144,7 +183,6 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
ngx_str_t key;
|
ngx_str_t key;
|
||||||
ngx_uint_t i;
|
ngx_uint_t i;
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_rbtree_node_t *node;
|
ngx_rbtree_node_t *node;
|
||||||
ngx_pool_cleanup_t *cln;
|
ngx_pool_cleanup_t *cln;
|
||||||
ngx_http_limit_conn_ctx_t *ctx;
|
ngx_http_limit_conn_ctx_t *ctx;
|
||||||
@@ -153,7 +191,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_limit_conn_limit_t *limits;
|
ngx_http_limit_conn_limit_t *limits;
|
||||||
ngx_http_limit_conn_cleanup_t *lccln;
|
ngx_http_limit_conn_cleanup_t *lccln;
|
||||||
|
|
||||||
if (r->main->limit_conn_set) {
|
if (r->main->limit_conn_status) {
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,15 +217,13 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->main->limit_conn_set = 1;
|
r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_PASSED;
|
||||||
|
|
||||||
hash = ngx_crc32_short(key.data, key.len);
|
hash = ngx_crc32_short(key.data, key.len);
|
||||||
|
|
||||||
shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
|
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
ngx_shmtx_lock(&shpool->mutex);
|
node = ngx_http_limit_conn_lookup(&ctx->sh->rbtree, &key, hash);
|
||||||
|
|
||||||
node = ngx_http_limit_conn_lookup(ctx->rbtree, &key, hash);
|
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
|
|
||||||
@@ -195,11 +231,20 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
+ offsetof(ngx_http_limit_conn_node_t, data)
|
+ offsetof(ngx_http_limit_conn_node_t, data)
|
||||||
+ key.len;
|
+ key.len;
|
||||||
|
|
||||||
node = ngx_slab_alloc_locked(shpool, n);
|
node = ngx_slab_alloc_locked(ctx->shpool, n);
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
ngx_http_limit_conn_cleanup_all(r->pool);
|
ngx_http_limit_conn_cleanup_all(r->pool);
|
||||||
|
|
||||||
|
if (lccf->dry_run) {
|
||||||
|
r->main->limit_conn_status =
|
||||||
|
NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN;
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED;
|
||||||
|
|
||||||
return lccf->status_code;
|
return lccf->status_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +255,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
lc->conn = 1;
|
lc->conn = 1;
|
||||||
ngx_memcpy(lc->data, key.data, key.len);
|
ngx_memcpy(lc->data, key.data, key.len);
|
||||||
|
|
||||||
ngx_rbtree_insert(ctx->rbtree, node);
|
ngx_rbtree_insert(&ctx->sh->rbtree, node);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -218,13 +263,23 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if ((ngx_uint_t) lc->conn >= limits[i].conn) {
|
if ((ngx_uint_t) lc->conn >= limits[i].conn) {
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
ngx_log_error(lccf->log_level, r->connection->log, 0,
|
ngx_log_error(lccf->log_level, r->connection->log, 0,
|
||||||
"limiting connections by zone \"%V\"",
|
"limiting connections%s by zone \"%V\"",
|
||||||
|
lccf->dry_run ? ", dry run," : "",
|
||||||
&limits[i].shm_zone->shm.name);
|
&limits[i].shm_zone->shm.name);
|
||||||
|
|
||||||
ngx_http_limit_conn_cleanup_all(r->pool);
|
ngx_http_limit_conn_cleanup_all(r->pool);
|
||||||
|
|
||||||
|
if (lccf->dry_run) {
|
||||||
|
r->main->limit_conn_status =
|
||||||
|
NGX_HTTP_LIMIT_CONN_REJECTED_DRY_RUN;
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->main->limit_conn_status = NGX_HTTP_LIMIT_CONN_REJECTED;
|
||||||
|
|
||||||
return lccf->status_code;
|
return lccf->status_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +289,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
|
|||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"limit conn: %08Xi %d", node->key, lc->conn);
|
"limit conn: %08Xi %d", node->key, lc->conn);
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
cln = ngx_pool_cleanup_add(r->pool,
|
cln = ngx_pool_cleanup_add(r->pool,
|
||||||
sizeof(ngx_http_limit_conn_cleanup_t));
|
sizeof(ngx_http_limit_conn_cleanup_t));
|
||||||
@@ -338,17 +393,15 @@ ngx_http_limit_conn_cleanup(void *data)
|
|||||||
{
|
{
|
||||||
ngx_http_limit_conn_cleanup_t *lccln = data;
|
ngx_http_limit_conn_cleanup_t *lccln = data;
|
||||||
|
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_rbtree_node_t *node;
|
ngx_rbtree_node_t *node;
|
||||||
ngx_http_limit_conn_ctx_t *ctx;
|
ngx_http_limit_conn_ctx_t *ctx;
|
||||||
ngx_http_limit_conn_node_t *lc;
|
ngx_http_limit_conn_node_t *lc;
|
||||||
|
|
||||||
ctx = lccln->shm_zone->data;
|
ctx = lccln->shm_zone->data;
|
||||||
shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
|
|
||||||
node = lccln->node;
|
node = lccln->node;
|
||||||
lc = (ngx_http_limit_conn_node_t *) &node->color;
|
lc = (ngx_http_limit_conn_node_t *) &node->color;
|
||||||
|
|
||||||
ngx_shmtx_lock(&shpool->mutex);
|
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
|
||||||
"limit conn cleanup: %08Xi %d", node->key, lc->conn);
|
"limit conn cleanup: %08Xi %d", node->key, lc->conn);
|
||||||
@@ -356,11 +409,11 @@ ngx_http_limit_conn_cleanup(void *data)
|
|||||||
lc->conn--;
|
lc->conn--;
|
||||||
|
|
||||||
if (lc->conn == 0) {
|
if (lc->conn == 0) {
|
||||||
ngx_rbtree_delete(ctx->rbtree, node);
|
ngx_rbtree_delete(&ctx->sh->rbtree, node);
|
||||||
ngx_slab_free_locked(shpool, node);
|
ngx_slab_free_locked(ctx->shpool, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -386,8 +439,6 @@ ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
|
|||||||
ngx_http_limit_conn_ctx_t *octx = data;
|
ngx_http_limit_conn_ctx_t *octx = data;
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
ngx_slab_pool_t *shpool;
|
|
||||||
ngx_rbtree_node_t *sentinel;
|
|
||||||
ngx_http_limit_conn_ctx_t *ctx;
|
ngx_http_limit_conn_ctx_t *ctx;
|
||||||
|
|
||||||
ctx = shm_zone->data;
|
ctx = shm_zone->data;
|
||||||
@@ -406,48 +457,63 @@ ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->rbtree = octx->rbtree;
|
ctx->sh = octx->sh;
|
||||||
|
ctx->shpool = octx->shpool;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
|
||||||
|
|
||||||
if (shm_zone->shm.exists) {
|
if (shm_zone->shm.exists) {
|
||||||
ctx->rbtree = shpool->data;
|
ctx->sh = ctx->shpool->data;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
|
ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_conn_shctx_t));
|
||||||
if (ctx->rbtree == NULL) {
|
if (ctx->sh == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
shpool->data = ctx->rbtree;
|
ctx->shpool->data = ctx->sh;
|
||||||
|
|
||||||
sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
|
ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
|
||||||
if (sentinel == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_rbtree_init(ctx->rbtree, sentinel,
|
|
||||||
ngx_http_limit_conn_rbtree_insert_value);
|
ngx_http_limit_conn_rbtree_insert_value);
|
||||||
|
|
||||||
len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
|
len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
|
||||||
|
|
||||||
shpool->log_ctx = ngx_slab_alloc(shpool, len);
|
ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
|
||||||
if (shpool->log_ctx == NULL) {
|
if (ctx->shpool->log_ctx == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
|
ngx_sprintf(ctx->shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
|
||||||
&shm_zone->shm.name);
|
&shm_zone->shm.name);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
if (r->main->limit_conn_status == 0) {
|
||||||
|
v->not_found = 1;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cacheable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->len = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].len;
|
||||||
|
v->data = ngx_http_limit_conn_status[r->main->limit_conn_status - 1].data;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
|
ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
@@ -466,6 +532,7 @@ ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
|
|||||||
|
|
||||||
conf->log_level = NGX_CONF_UNSET_UINT;
|
conf->log_level = NGX_CONF_UNSET_UINT;
|
||||||
conf->status_code = NGX_CONF_UNSET_UINT;
|
conf->status_code = NGX_CONF_UNSET_UINT;
|
||||||
|
conf->dry_run = NGX_CONF_UNSET;
|
||||||
|
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
@@ -485,6 +552,8 @@ ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
|
ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
|
||||||
NGX_HTTP_SERVICE_UNAVAILABLE);
|
NGX_HTTP_SERVICE_UNAVAILABLE);
|
||||||
|
|
||||||
|
ngx_conf_merge_value(conf->dry_run, prev->dry_run, 0);
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,6 +720,25 @@ ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_limit_conn_add_variables(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_variable_t *var, *v;
|
||||||
|
|
||||||
|
for (v = ngx_http_limit_conn_vars; v->name.len; v++) {
|
||||||
|
var = ngx_http_add_variable(cf, &v->name, v->flags);
|
||||||
|
if (var == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
var->get_handler = v->get_handler;
|
||||||
|
var->data = v->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_limit_conn_init(ngx_conf_t *cf)
|
ngx_http_limit_conn_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,13 @@
|
|||||||
#include <ngx_http.h>
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_HTTP_LIMIT_REQ_PASSED 1
|
||||||
|
#define NGX_HTTP_LIMIT_REQ_DELAYED 2
|
||||||
|
#define NGX_HTTP_LIMIT_REQ_REJECTED 3
|
||||||
|
#define NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN 4
|
||||||
|
#define NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN 5
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_char color;
|
u_char color;
|
||||||
u_char dummy;
|
u_char dummy;
|
||||||
@@ -65,6 +72,8 @@ static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,
|
|||||||
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
|
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
|
||||||
ngx_uint_t n);
|
ngx_uint_t n);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_limit_req_status_variable(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf);
|
static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,
|
static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,
|
||||||
void *child);
|
void *child);
|
||||||
@@ -72,6 +81,7 @@ static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||||||
void *conf);
|
void *conf);
|
||||||
static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
static ngx_int_t ngx_http_limit_req_add_variables(ngx_conf_t *cf);
|
||||||
static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
|
static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
|
||||||
@@ -131,7 +141,7 @@ static ngx_command_t ngx_http_limit_req_commands[] = {
|
|||||||
|
|
||||||
|
|
||||||
static ngx_http_module_t ngx_http_limit_req_module_ctx = {
|
static ngx_http_module_t ngx_http_limit_req_module_ctx = {
|
||||||
NULL, /* preconfiguration */
|
ngx_http_limit_req_add_variables, /* preconfiguration */
|
||||||
ngx_http_limit_req_init, /* postconfiguration */
|
ngx_http_limit_req_init, /* postconfiguration */
|
||||||
|
|
||||||
NULL, /* create main configuration */
|
NULL, /* create main configuration */
|
||||||
@@ -161,6 +171,24 @@ ngx_module_t ngx_http_limit_req_module = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_variable_t ngx_http_limit_req_vars[] = {
|
||||||
|
|
||||||
|
{ ngx_string("limit_req_status"), NULL,
|
||||||
|
ngx_http_limit_req_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
|
||||||
|
|
||||||
|
ngx_http_null_variable
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_str_t ngx_http_limit_req_status[] = {
|
||||||
|
ngx_string("PASSED"),
|
||||||
|
ngx_string("DELAYED"),
|
||||||
|
ngx_string("REJECTED"),
|
||||||
|
ngx_string("DELAYED_DRY_RUN"),
|
||||||
|
ngx_string("REJECTED_DRY_RUN")
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_limit_req_handler(ngx_http_request_t *r)
|
ngx_http_limit_req_handler(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
@@ -173,7 +201,7 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_limit_req_conf_t *lrcf;
|
ngx_http_limit_req_conf_t *lrcf;
|
||||||
ngx_http_limit_req_limit_t *limit, *limits;
|
ngx_http_limit_req_limit_t *limit, *limits;
|
||||||
|
|
||||||
if (r->main->limit_req_set) {
|
if (r->main->limit_req_status) {
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,8 +260,6 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->main->limit_req_set = 1;
|
|
||||||
|
|
||||||
if (rc == NGX_BUSY || rc == NGX_ERROR) {
|
if (rc == NGX_BUSY || rc == NGX_ERROR) {
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
if (rc == NGX_BUSY) {
|
||||||
@@ -261,9 +287,12 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lrcf->dry_run) {
|
if (lrcf->dry_run) {
|
||||||
|
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN;
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED;
|
||||||
|
|
||||||
return lrcf->status_code;
|
return lrcf->status_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +305,7 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
|
delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
|
||||||
|
|
||||||
if (!delay) {
|
if (!delay) {
|
||||||
|
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_PASSED;
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +315,12 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
excess / 1000, excess % 1000, &limit->shm_zone->shm.name);
|
excess / 1000, excess % 1000, &limit->shm_zone->shm.name);
|
||||||
|
|
||||||
if (lrcf->dry_run) {
|
if (lrcf->dry_run) {
|
||||||
|
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED_DRY_RUN;
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED;
|
||||||
|
|
||||||
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
@@ -711,6 +744,25 @@ ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_limit_req_status_variable(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
if (r->main->limit_req_status == 0) {
|
||||||
|
v->not_found = 1;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cacheable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->len = ngx_http_limit_req_status[r->main->limit_req_status - 1].len;
|
||||||
|
v->data = ngx_http_limit_req_status[r->main->limit_req_status - 1].data;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
ngx_http_limit_req_create_conf(ngx_conf_t *cf)
|
ngx_http_limit_req_create_conf(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
@@ -995,6 +1047,25 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_limit_req_add_variables(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_variable_t *var, *v;
|
||||||
|
|
||||||
|
for (v = ngx_http_limit_req_vars; v->name.len; v++) {
|
||||||
|
var = ngx_http_add_variable(cf, &v->name, v->flags);
|
||||||
|
if (var == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
var->get_handler = v->get_handler;
|
||||||
|
var->data = v->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_limit_req_init(ngx_conf_t *cf)
|
ngx_http_limit_req_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -485,7 +485,8 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
|
|||||||
|
|
||||||
if (u->length == (ssize_t) ctx->rest) {
|
if (u->length == (ssize_t) ctx->rest) {
|
||||||
|
|
||||||
if (ngx_strncmp(b->last,
|
if (bytes > u->length
|
||||||
|
|| ngx_strncmp(b->last,
|
||||||
ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
|
ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
|
||||||
bytes)
|
bytes)
|
||||||
!= 0)
|
!= 0)
|
||||||
@@ -540,7 +541,9 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
|
|||||||
|
|
||||||
last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
|
last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
|
||||||
|
|
||||||
if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
|
if (bytes > u->length
|
||||||
|
|| ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0)
|
||||||
|
{
|
||||||
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
|
||||||
"memcached sent invalid trailer");
|
"memcached sent invalid trailer");
|
||||||
|
|
||||||
|
|||||||
@@ -3116,6 +3116,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
"chunk samples sizes:%uL",
|
"chunk samples sizes:%uL",
|
||||||
trak->start_chunk_samples_size);
|
trak->start_chunk_samples_size);
|
||||||
|
|
||||||
|
if (trak->start_chunk_samples_size > (uint64_t) mp4->end) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"too large mp4 start samples size in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (mp4->length) {
|
if (mp4->length) {
|
||||||
if (trak->end_sample - trak->start_sample > entries) {
|
if (trak->end_sample - trak->start_sample > entries) {
|
||||||
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
@@ -3135,6 +3142,13 @@ ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"mp4 stsz end_chunk_samples_size:%uL",
|
"mp4 stsz end_chunk_samples_size:%uL",
|
||||||
trak->end_chunk_samples_size);
|
trak->end_chunk_samples_size);
|
||||||
|
|
||||||
|
if (trak->end_chunk_samples_size > (uint64_t) mp4->end) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"too large mp4 end samples size in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
|
atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
|
||||||
@@ -3226,6 +3240,7 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
{
|
{
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
uint32_t entries;
|
uint32_t entries;
|
||||||
|
uint64_t chunk_offset, samples_size;
|
||||||
ngx_buf_t *atom, *data;
|
ngx_buf_t *atom, *data;
|
||||||
ngx_mp4_stco_atom_t *stco_atom;
|
ngx_mp4_stco_atom_t *stco_atom;
|
||||||
|
|
||||||
@@ -3256,8 +3271,19 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
data->pos += trak->start_chunk * sizeof(uint32_t);
|
data->pos += trak->start_chunk * sizeof(uint32_t);
|
||||||
|
|
||||||
trak->start_offset = ngx_mp4_get_32value(data->pos);
|
chunk_offset = ngx_mp4_get_32value(data->pos);
|
||||||
trak->start_offset += trak->start_chunk_samples_size;
|
samples_size = trak->start_chunk_samples_size;
|
||||||
|
|
||||||
|
if (chunk_offset > (uint64_t) mp4->end - samples_size
|
||||||
|
|| chunk_offset + samples_size > NGX_MAX_UINT32_VALUE)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"too large chunk offset in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
trak->start_offset = chunk_offset + samples_size;
|
||||||
ngx_mp4_set_32value(data->pos, trak->start_offset);
|
ngx_mp4_set_32value(data->pos, trak->start_offset);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
@@ -3276,9 +3302,19 @@ ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
data->last = data->pos + entries * sizeof(uint32_t);
|
data->last = data->pos + entries * sizeof(uint32_t);
|
||||||
|
|
||||||
if (entries) {
|
if (entries) {
|
||||||
trak->end_offset =
|
chunk_offset = ngx_mp4_get_32value(data->last - sizeof(uint32_t));
|
||||||
ngx_mp4_get_32value(data->last - sizeof(uint32_t));
|
samples_size = trak->end_chunk_samples_size;
|
||||||
trak->end_offset += trak->end_chunk_samples_size;
|
|
||||||
|
if (chunk_offset > (uint64_t) mp4->end - samples_size
|
||||||
|
|| chunk_offset + samples_size > NGX_MAX_UINT32_VALUE)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"too large chunk offset in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
trak->end_offset = chunk_offset + samples_size;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"end chunk offset:%O", trak->end_offset);
|
"end chunk offset:%O", trak->end_offset);
|
||||||
@@ -3409,7 +3445,7 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
ngx_http_mp4_trak_t *trak)
|
ngx_http_mp4_trak_t *trak)
|
||||||
{
|
{
|
||||||
size_t atom_size;
|
size_t atom_size;
|
||||||
uint64_t entries;
|
uint64_t entries, chunk_offset, samples_size;
|
||||||
ngx_buf_t *atom, *data;
|
ngx_buf_t *atom, *data;
|
||||||
ngx_mp4_co64_atom_t *co64_atom;
|
ngx_mp4_co64_atom_t *co64_atom;
|
||||||
|
|
||||||
@@ -3440,8 +3476,17 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
|
|
||||||
data->pos += trak->start_chunk * sizeof(uint64_t);
|
data->pos += trak->start_chunk * sizeof(uint64_t);
|
||||||
|
|
||||||
trak->start_offset = ngx_mp4_get_64value(data->pos);
|
chunk_offset = ngx_mp4_get_64value(data->pos);
|
||||||
trak->start_offset += trak->start_chunk_samples_size;
|
samples_size = trak->start_chunk_samples_size;
|
||||||
|
|
||||||
|
if (chunk_offset > (uint64_t) mp4->end - samples_size) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"too large chunk offset in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
trak->start_offset = chunk_offset + samples_size;
|
||||||
ngx_mp4_set_64value(data->pos, trak->start_offset);
|
ngx_mp4_set_64value(data->pos, trak->start_offset);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
@@ -3460,9 +3505,17 @@ ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
|
|||||||
data->last = data->pos + entries * sizeof(uint64_t);
|
data->last = data->pos + entries * sizeof(uint64_t);
|
||||||
|
|
||||||
if (entries) {
|
if (entries) {
|
||||||
trak->end_offset =
|
chunk_offset = ngx_mp4_get_64value(data->last - sizeof(uint64_t));
|
||||||
ngx_mp4_get_64value(data->last - sizeof(uint64_t));
|
samples_size = trak->end_chunk_samples_size;
|
||||||
trak->end_offset += trak->end_chunk_samples_size;
|
|
||||||
|
if (chunk_offset > (uint64_t) mp4->end - samples_size) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
|
||||||
|
"too large chunk offset in \"%s\"",
|
||||||
|
mp4->file.name.data);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
trak->end_offset = chunk_offset + samples_size;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
|
||||||
"end chunk offset:%O", trak->end_offset);
|
"end chunk offset:%O", trak->end_offset);
|
||||||
|
|||||||
@@ -2015,6 +2015,25 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->upstream_done) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||||
|
"http proxy data after close");
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->length == 0) {
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
r = p->input_ctx;
|
||||||
|
r->upstream->keepalive = 0;
|
||||||
|
p->upstream_done = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
||||||
if (cl == NULL) {
|
if (cl == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@@ -2042,20 +2061,23 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b->last - b->pos > p->length) {
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
b->last = b->pos + p->length;
|
||||||
|
p->upstream_done = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
p->length -= b->last - b->pos;
|
p->length -= b->last - b->pos;
|
||||||
|
|
||||||
if (p->length == 0) {
|
if (p->length == 0) {
|
||||||
r = p->input_ctx;
|
r = p->input_ctx;
|
||||||
p->upstream_done = 1;
|
|
||||||
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
|
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
|
||||||
|
|
||||||
} else if (p->length < 0) {
|
|
||||||
r = p->input_ctx;
|
|
||||||
p->upstream_done = 1;
|
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
|
||||||
"upstream sent more data than specified in "
|
|
||||||
"\"Content-Length\" header");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@@ -2082,6 +2104,23 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->upstream_done) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||||
|
"http proxy data after close");
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->length == 0) {
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent data after final chunk");
|
||||||
|
|
||||||
|
r->upstream->keepalive = 0;
|
||||||
|
p->upstream_done = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
prev = &buf->shadow;
|
prev = &buf->shadow;
|
||||||
|
|
||||||
@@ -2144,9 +2183,15 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
|
|
||||||
/* a whole response has been parsed successfully */
|
/* a whole response has been parsed successfully */
|
||||||
|
|
||||||
p->upstream_done = 1;
|
p->length = 0;
|
||||||
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
|
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
|
||||||
|
|
||||||
|
if (buf->pos != buf->last) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||||
|
"upstream sent data after final chunk");
|
||||||
|
r->upstream->keepalive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2161,13 +2206,13 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
|||||||
|
|
||||||
/* invalid response */
|
/* invalid response */
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, p->log, 0,
|
||||||
"upstream sent invalid chunked response");
|
"upstream sent invalid chunked response");
|
||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||||
"http proxy chunked state %ui, length %O",
|
"http proxy chunked state %ui, length %O",
|
||||||
ctx->chunked.state, p->length);
|
ctx->chunked.state, p->length);
|
||||||
|
|
||||||
@@ -2227,6 +2272,18 @@ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bytes > u->length) {
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
cl->buf->last = cl->buf->pos + u->length;
|
||||||
|
u->length = 0;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
u->length -= bytes;
|
u->length -= bytes;
|
||||||
|
|
||||||
if (u->length == 0) {
|
if (u->length == 0) {
|
||||||
@@ -2313,6 +2370,12 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
|
|||||||
u->keepalive = !u->headers_in.connection_close;
|
u->keepalive = !u->headers_in.connection_close;
|
||||||
u->length = 0;
|
u->length = 0;
|
||||||
|
|
||||||
|
if (buf->pos != buf->last) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||||
|
"upstream sent data after final chunk");
|
||||||
|
u->keepalive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,12 +180,11 @@ ngx_http_realip_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
case NGX_HTTP_REALIP_PROXY:
|
case NGX_HTTP_REALIP_PROXY:
|
||||||
|
|
||||||
value = &r->connection->proxy_protocol_addr;
|
if (r->connection->proxy_protocol == NULL) {
|
||||||
|
|
||||||
if (value->len == 0) {
|
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value = &r->connection->proxy_protocol->src_addr;
|
||||||
xfwd = NULL;
|
xfwd = NULL;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -238,7 +237,7 @@ found:
|
|||||||
!= NGX_DECLINED)
|
!= NGX_DECLINED)
|
||||||
{
|
{
|
||||||
if (rlcf->type == NGX_HTTP_REALIP_PROXY) {
|
if (rlcf->type == NGX_HTTP_REALIP_PROXY) {
|
||||||
ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port);
|
ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ngx_http_realip_set_addr(r, &addr);
|
return ngx_http_realip_set_addr(r, &addr);
|
||||||
|
|||||||
@@ -318,6 +318,11 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
|
if (value[2].len == 0) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty replacement");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
|
ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
|
||||||
|
|
||||||
rc.pattern = value[1];
|
rc.pattern = value[1];
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
|
|||||||
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_scgi_input_filter_init(void *data);
|
||||||
static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
|
static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
|
||||||
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
|
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
|
||||||
|
|
||||||
@@ -534,6 +535,10 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
|
|||||||
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
||||||
u->pipe->input_ctx = r;
|
u->pipe->input_ctx = r;
|
||||||
|
|
||||||
|
u->input_filter_init = ngx_http_scgi_input_filter_init;
|
||||||
|
u->input_filter = ngx_http_upstream_non_buffered_filter;
|
||||||
|
u->input_filter_ctx = r;
|
||||||
|
|
||||||
if (!scf->upstream.request_buffering
|
if (!scf->upstream.request_buffering
|
||||||
&& scf->upstream.pass_request_body
|
&& scf->upstream.pass_request_body
|
||||||
&& !r->headers_in.chunked)
|
&& !r->headers_in.chunked)
|
||||||
@@ -1145,6 +1150,37 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_scgi_input_filter_init(void *data)
|
||||||
|
{
|
||||||
|
ngx_http_request_t *r = data;
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http scgi filter init s:%ui l:%O",
|
||||||
|
u->headers_in.status_n, u->headers_in.content_length_n);
|
||||||
|
|
||||||
|
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||||
|
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
|
||||||
|
{
|
||||||
|
u->pipe->length = 0;
|
||||||
|
u->length = 0;
|
||||||
|
|
||||||
|
} else if (r->method == NGX_HTTP_HEAD) {
|
||||||
|
u->pipe->length = -1;
|
||||||
|
u->length = -1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
u->pipe->length = u->headers_in.content_length_n;
|
||||||
|
u->length = u->headers_in.content_length_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_http_scgi_abort_request(ngx_http_request_t *r)
|
ngx_http_scgi_abort_request(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -180,6 +180,11 @@ ngx_http_slice_header_filter(ngx_http_request_t *r)
|
|||||||
r->headers_out.content_range->hash = 0;
|
r->headers_out.content_range->hash = 0;
|
||||||
r->headers_out.content_range = NULL;
|
r->headers_out.content_range = NULL;
|
||||||
|
|
||||||
|
if (r->headers_out.accept_ranges) {
|
||||||
|
r->headers_out.accept_ranges->hash = 0;
|
||||||
|
r->headers_out.accept_ranges = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
r->allow_ranges = 1;
|
r->allow_ranges = 1;
|
||||||
r->subrequest_ranges = 1;
|
r->subrequest_ranges = 1;
|
||||||
r->single_range = 1;
|
r->single_range = 1;
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||||||
void *conf);
|
void *conf);
|
||||||
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
static char *ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
void *conf);
|
||||||
|
|
||||||
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
|
static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
@@ -74,6 +76,14 @@ static ngx_conf_enum_t ngx_http_ssl_verify[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_conf_enum_t ngx_http_ssl_ocsp[] = {
|
||||||
|
{ ngx_string("off"), 0 },
|
||||||
|
{ ngx_string("on"), 1 },
|
||||||
|
{ ngx_string("leaf"), 2 },
|
||||||
|
{ ngx_null_string, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static ngx_conf_deprecated_t ngx_http_ssl_deprecated = {
|
static ngx_conf_deprecated_t ngx_http_ssl_deprecated = {
|
||||||
ngx_conf_deprecated, "ssl", "listen ... ssl"
|
ngx_conf_deprecated, "ssl", "listen ... ssl"
|
||||||
};
|
};
|
||||||
@@ -221,6 +231,27 @@ static ngx_command_t ngx_http_ssl_commands[] = {
|
|||||||
offsetof(ngx_http_ssl_srv_conf_t, crl),
|
offsetof(ngx_http_ssl_srv_conf_t, crl),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_ocsp"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_enum_slot,
|
||||||
|
NGX_HTTP_SRV_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_ssl_srv_conf_t, ocsp),
|
||||||
|
&ngx_http_ssl_ocsp },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_ocsp_responder"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_str_slot,
|
||||||
|
NGX_HTTP_SRV_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_ssl_srv_conf_t, ocsp_responder),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_ocsp_cache"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_http_ssl_ocsp_cache,
|
||||||
|
NGX_HTTP_SRV_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_stapling"),
|
{ ngx_string("ssl_stapling"),
|
||||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
|
||||||
ngx_conf_set_flag_slot,
|
ngx_conf_set_flag_slot,
|
||||||
@@ -603,6 +634,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
|
|||||||
* sscf->crl = { 0, NULL };
|
* sscf->crl = { 0, NULL };
|
||||||
* sscf->ciphers = { 0, NULL };
|
* sscf->ciphers = { 0, NULL };
|
||||||
* sscf->shm_zone = NULL;
|
* sscf->shm_zone = NULL;
|
||||||
|
* sscf->ocsp_responder = { 0, NULL };
|
||||||
* sscf->stapling_file = { 0, NULL };
|
* sscf->stapling_file = { 0, NULL };
|
||||||
* sscf->stapling_responder = { 0, NULL };
|
* sscf->stapling_responder = { 0, NULL };
|
||||||
*/
|
*/
|
||||||
@@ -621,6 +653,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
|
|||||||
sscf->session_timeout_tls13 = NGX_CONF_UNSET;
|
sscf->session_timeout_tls13 = NGX_CONF_UNSET;
|
||||||
sscf->session_tickets = NGX_CONF_UNSET;
|
sscf->session_tickets = NGX_CONF_UNSET;
|
||||||
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
|
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
|
||||||
|
sscf->ocsp = NGX_CONF_UNSET_UINT;
|
||||||
|
sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR;
|
||||||
sscf->stapling = NGX_CONF_UNSET;
|
sscf->stapling = NGX_CONF_UNSET;
|
||||||
sscf->stapling_verify = NGX_CONF_UNSET;
|
sscf->stapling_verify = NGX_CONF_UNSET;
|
||||||
sscf->dyn_rec_enable = NGX_CONF_UNSET;
|
sscf->dyn_rec_enable = NGX_CONF_UNSET;
|
||||||
@@ -691,6 +725,11 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
|
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
|
||||||
|
|
||||||
|
ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0);
|
||||||
|
ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, "");
|
||||||
|
ngx_conf_merge_ptr_value(conf->ocsp_cache_zone,
|
||||||
|
prev->ocsp_cache_zone, NULL);
|
||||||
|
|
||||||
ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
|
ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
|
||||||
ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
|
ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
|
||||||
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
|
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
|
||||||
@@ -841,7 +880,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
"no ssl_client_certificate for ssl_client_verify");
|
"no ssl_client_certificate for ssl_verify_client");
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,6 +905,23 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conf->ocsp) {
|
||||||
|
|
||||||
|
if (conf->verify == 3) {
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"\"ssl_ocsp\" is incompatible with "
|
||||||
|
"\"ssl_verify_client optional_no_ca\"");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp,
|
||||||
|
conf->ocsp_cache_zone)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
|
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
@@ -1186,6 +1242,85 @@ invalid:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
ngx_http_ssl_srv_conf_t *sscf = conf;
|
||||||
|
|
||||||
|
size_t len;
|
||||||
|
ngx_int_t n;
|
||||||
|
ngx_str_t *value, name, size;
|
||||||
|
ngx_uint_t j;
|
||||||
|
|
||||||
|
if (sscf->ocsp_cache_zone != NGX_CONF_UNSET_PTR) {
|
||||||
|
return "is duplicate";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = cf->args->elts;
|
||||||
|
|
||||||
|
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||||
|
sscf->ocsp_cache_zone = NULL;
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value[1].len <= sizeof("shared:") - 1
|
||||||
|
|| ngx_strncmp(value[1].data, "shared:", sizeof("shared:") - 1) != 0)
|
||||||
|
{
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
for (j = sizeof("shared:") - 1; j < value[1].len; j++) {
|
||||||
|
if (value[1].data[j] == ':') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
name.len = len;
|
||||||
|
name.data = value[1].data + sizeof("shared:") - 1;
|
||||||
|
|
||||||
|
size.len = value[1].len - j - 1;
|
||||||
|
size.data = name.data + len + 1;
|
||||||
|
|
||||||
|
n = ngx_parse_size(&size);
|
||||||
|
|
||||||
|
if (n == NGX_ERROR) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"OCSP cache \"%V\" is too small", &value[1]);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sscf->ocsp_cache_zone = ngx_shared_memory_add(cf, &name, n,
|
||||||
|
&ngx_http_ssl_module_ctx);
|
||||||
|
if (sscf->ocsp_cache_zone == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sscf->ocsp_cache_zone->init = ngx_ssl_ocsp_cache_init;
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid OCSP cache \"%V\"", &value[1]);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_ssl_init(ngx_conf_t *cf)
|
ngx_http_ssl_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
@@ -1204,12 +1339,13 @@ ngx_http_ssl_init(ngx_conf_t *cf)
|
|||||||
|
|
||||||
sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
|
sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
|
||||||
|
|
||||||
if (sscf->ssl.ctx == NULL || !sscf->stapling) {
|
if (sscf->ssl.ctx == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
|
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
|
||||||
|
|
||||||
|
if (sscf->stapling) {
|
||||||
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
|
if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
|
||||||
clcf->resolver_timeout)
|
clcf->resolver_timeout)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
@@ -1218,6 +1354,16 @@ ngx_http_ssl_init(ngx_conf_t *cf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sscf->ocsp) {
|
||||||
|
if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, clcf->resolver,
|
||||||
|
clcf->resolver_timeout)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cmcf->ports == NULL) {
|
if (cmcf->ports == NULL) {
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ typedef struct {
|
|||||||
ngx_flag_t session_tickets;
|
ngx_flag_t session_tickets;
|
||||||
ngx_array_t *session_ticket_keys;
|
ngx_array_t *session_ticket_keys;
|
||||||
|
|
||||||
|
ngx_uint_t ocsp;
|
||||||
|
ngx_str_t ocsp_responder;
|
||||||
|
ngx_shm_zone_t *ocsp_cache_zone;
|
||||||
|
|
||||||
ngx_flag_t stapling;
|
ngx_flag_t stapling;
|
||||||
ngx_flag_t stapling_verify;
|
ngx_flag_t stapling_verify;
|
||||||
ngx_str_t stapling_file;
|
ngx_str_t stapling_file;
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ ngx_http_static_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
len = r->uri.len + 1;
|
len = r->uri.len + 1;
|
||||||
|
|
||||||
if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
|
if (!clcf->alias && r->args.len == 0) {
|
||||||
location = path.data + clcf->root.len;
|
location = path.data + root;
|
||||||
|
|
||||||
*last = '/';
|
*last = '/';
|
||||||
|
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ found:
|
|||||||
|
|
||||||
c->idle = 0;
|
c->idle = 0;
|
||||||
c->sent = 0;
|
c->sent = 0;
|
||||||
|
c->data = NULL;
|
||||||
c->log = pc->log;
|
c->log = pc->log;
|
||||||
c->read->log = pc->log;
|
c->read->log = pc->log;
|
||||||
c->write->log = pc->log;
|
c->write->log = pc->log;
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
|
|||||||
static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_uwsgi_input_filter_init(void *data);
|
||||||
static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
|
static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
|
||||||
static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
|
static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
|
||||||
ngx_int_t rc);
|
ngx_int_t rc);
|
||||||
@@ -703,6 +704,10 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
|
|||||||
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
||||||
u->pipe->input_ctx = r;
|
u->pipe->input_ctx = r;
|
||||||
|
|
||||||
|
u->input_filter_init = ngx_http_uwsgi_input_filter_init;
|
||||||
|
u->input_filter = ngx_http_upstream_non_buffered_filter;
|
||||||
|
u->input_filter_ctx = r;
|
||||||
|
|
||||||
if (!uwcf->upstream.request_buffering
|
if (!uwcf->upstream.request_buffering
|
||||||
&& uwcf->upstream.pass_request_body
|
&& uwcf->upstream.pass_request_body
|
||||||
&& !r->headers_in.chunked)
|
&& !r->headers_in.chunked)
|
||||||
@@ -1141,6 +1146,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
|
|||||||
r->upstream->request_bufs = cl;
|
r->upstream->request_bufs = cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b->flush = 1;
|
||||||
cl->next = NULL;
|
cl->next = NULL;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@@ -1355,6 +1361,37 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_uwsgi_input_filter_init(void *data)
|
||||||
|
{
|
||||||
|
ngx_http_request_t *r = data;
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http uwsgi filter init s:%ui l:%O",
|
||||||
|
u->headers_in.status_n, u->headers_in.content_length_n);
|
||||||
|
|
||||||
|
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||||
|
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
|
||||||
|
{
|
||||||
|
u->pipe->length = 0;
|
||||||
|
u->length = 0;
|
||||||
|
|
||||||
|
} else if (r->method == NGX_HTTP_HEAD) {
|
||||||
|
u->pipe->length = -1;
|
||||||
|
u->length = -1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
u->pipe->length = u->headers_in.content_length_n;
|
||||||
|
u->length = u->headers_in.content_length_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
|
ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ ngx_http_xslt_header_filter(ngx_http_request_t *r)
|
|||||||
ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module);
|
ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module);
|
||||||
|
|
||||||
r->main_filter_need_in_memory = 1;
|
r->main_filter_need_in_memory = 1;
|
||||||
|
r->allow_ranges = 0;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1469,14 +1469,14 @@ ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
|
|||||||
NGX_HASH_WILDCARD_KEY);
|
NGX_HASH_WILDCARD_KEY);
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
if (rc == NGX_ERROR) {
|
||||||
return NGX_ERROR;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == NGX_DECLINED) {
|
if (rc == NGX_DECLINED) {
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
"invalid server name or wildcard \"%V\" on %V",
|
"invalid server name or wildcard \"%V\" on %V",
|
||||||
&name[n].name, &addr->opt.addr_text);
|
&name[n].name, &addr->opt.addr_text);
|
||||||
return NGX_ERROR;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
if (rc == NGX_BUSY) {
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ struct ngx_http_file_cache_s {
|
|||||||
|
|
||||||
ngx_path_t *path;
|
ngx_path_t *path;
|
||||||
|
|
||||||
|
off_t min_free;
|
||||||
off_t max_size;
|
off_t max_size;
|
||||||
size_t bsize;
|
size_t bsize;
|
||||||
|
|
||||||
|
|||||||
+101
-19
@@ -21,6 +21,9 @@ typedef struct {
|
|||||||
#define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2
|
#define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_core_auth_delay(ngx_http_request_t *r);
|
||||||
|
static void ngx_http_core_auth_delay_handler(ngx_http_request_t *r);
|
||||||
|
|
||||||
static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
|
||||||
ngx_http_location_tree_node_t *node);
|
ngx_http_location_tree_node_t *node);
|
||||||
@@ -534,6 +537,13 @@ static ngx_command_t ngx_http_core_commands[] = {
|
|||||||
offsetof(ngx_http_core_loc_conf_t, satisfy),
|
offsetof(ngx_http_core_loc_conf_t, satisfy),
|
||||||
&ngx_http_core_satisfy },
|
&ngx_http_core_satisfy },
|
||||||
|
|
||||||
|
{ ngx_string("auth_delay"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_core_loc_conf_t, auth_delay),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("internal"),
|
{ ngx_string("internal"),
|
||||||
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
|
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
|
||||||
ngx_http_core_internal,
|
ngx_http_core_internal,
|
||||||
@@ -1138,6 +1148,10 @@ ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
|
|||||||
|
|
||||||
/* rc == NGX_ERROR || rc == NGX_HTTP_... */
|
/* rc == NGX_ERROR || rc == NGX_HTTP_... */
|
||||||
|
|
||||||
|
if (rc == NGX_HTTP_UNAUTHORIZED) {
|
||||||
|
return ngx_http_core_auth_delay(r);
|
||||||
|
}
|
||||||
|
|
||||||
ngx_http_finalize_request(r, rc);
|
ngx_http_finalize_request(r, rc);
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -1155,12 +1169,17 @@ ngx_http_core_post_access_phase(ngx_http_request_t *r,
|
|||||||
access_code = r->access_code;
|
access_code = r->access_code;
|
||||||
|
|
||||||
if (access_code) {
|
if (access_code) {
|
||||||
|
r->access_code = 0;
|
||||||
|
|
||||||
if (access_code == NGX_HTTP_FORBIDDEN) {
|
if (access_code == NGX_HTTP_FORBIDDEN) {
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"access forbidden by rule");
|
"access forbidden by rule");
|
||||||
}
|
}
|
||||||
|
|
||||||
r->access_code = 0;
|
if (access_code == NGX_HTTP_UNAUTHORIZED) {
|
||||||
|
return ngx_http_core_auth_delay(r);
|
||||||
|
}
|
||||||
|
|
||||||
ngx_http_finalize_request(r, access_code);
|
ngx_http_finalize_request(r, access_code);
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -1170,6 +1189,65 @@ ngx_http_core_post_access_phase(ngx_http_request_t *r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_core_auth_delay(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
if (clcf->auth_delay == 0) {
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_UNAUTHORIZED);
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"delaying unauthorized request");
|
||||||
|
|
||||||
|
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->read_event_handler = ngx_http_test_reading;
|
||||||
|
r->write_event_handler = ngx_http_core_auth_delay_handler;
|
||||||
|
|
||||||
|
r->connection->write->delayed = 1;
|
||||||
|
ngx_add_timer(r->connection->write, clcf->auth_delay);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* trigger an additional event loop iteration
|
||||||
|
* to ensure constant-time processing
|
||||||
|
*/
|
||||||
|
|
||||||
|
ngx_post_event(r->connection->write, &ngx_posted_next_events);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_core_auth_delay_handler(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_event_t *wev;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"auth delay handler");
|
||||||
|
|
||||||
|
wev = r->connection->write;
|
||||||
|
|
||||||
|
if (wev->delayed) {
|
||||||
|
|
||||||
|
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_core_content_phase(ngx_http_request_t *r,
|
ngx_http_core_content_phase(ngx_http_request_t *r,
|
||||||
ngx_http_phase_handler_t *ph)
|
ngx_http_phase_handler_t *ph)
|
||||||
@@ -1674,8 +1752,10 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
|
|||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
ngx_chain_t out;
|
ngx_chain_t out;
|
||||||
|
|
||||||
if (ngx_http_discard_request_body(r) != NGX_OK) {
|
rc = ngx_http_discard_request_body(r);
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->headers_out.status = status;
|
r->headers_out.status = status;
|
||||||
@@ -1855,7 +1935,8 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
|
last = ngx_copy(last, r->uri.data + alias, r->uri.len - alias);
|
||||||
|
*last = '\0';
|
||||||
|
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
@@ -2678,11 +2759,15 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
|
|||||||
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
|
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p;
|
||||||
ngx_int_t rc;
|
|
||||||
ngx_addr_t paddr;
|
ngx_addr_t paddr;
|
||||||
|
ngx_uint_t found;
|
||||||
|
|
||||||
|
found = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) {
|
if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) {
|
||||||
return NGX_DECLINED;
|
return found ? NGX_DONE : NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
|
for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
|
||||||
@@ -2698,23 +2783,17 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
|
if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff))
|
||||||
return NGX_DECLINED;
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return found ? NGX_DONE : NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
*addr = paddr;
|
*addr = paddr;
|
||||||
|
found = 1;
|
||||||
|
xfflen = p - 1 - xff;
|
||||||
|
|
||||||
if (recursive && p > xff) {
|
} while (recursive && p > xff);
|
||||||
rc = ngx_http_get_forwarded_addr_internal(r, addr, xff, p - 1 - xff,
|
|
||||||
proxies, 1);
|
|
||||||
|
|
||||||
if (rc == NGX_DECLINED) {
|
|
||||||
return NGX_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rc == NGX_OK || rc == NGX_DONE */
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -3407,6 +3486,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
|
|||||||
clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
|
clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
|
||||||
clcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
|
clcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
clcf->satisfy = NGX_CONF_UNSET_UINT;
|
clcf->satisfy = NGX_CONF_UNSET_UINT;
|
||||||
|
clcf->auth_delay = NGX_CONF_UNSET_MSEC;
|
||||||
clcf->if_modified_since = NGX_CONF_UNSET_UINT;
|
clcf->if_modified_since = NGX_CONF_UNSET_UINT;
|
||||||
clcf->max_ranges = NGX_CONF_UNSET_UINT;
|
clcf->max_ranges = NGX_CONF_UNSET_UINT;
|
||||||
clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
|
clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
|
||||||
@@ -3624,6 +3704,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|NGX_HTTP_KEEPALIVE_DISABLE_MSIE6));
|
|NGX_HTTP_KEEPALIVE_DISABLE_MSIE6));
|
||||||
ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
|
ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
|
||||||
NGX_HTTP_SATISFY_ALL);
|
NGX_HTTP_SATISFY_ALL);
|
||||||
|
ngx_conf_merge_msec_value(conf->auth_delay, prev->auth_delay, 0);
|
||||||
ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
|
ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
|
||||||
NGX_HTTP_IMS_EXACT);
|
NGX_HTTP_IMS_EXACT);
|
||||||
ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges,
|
ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges,
|
||||||
@@ -4704,6 +4785,7 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
case NGX_HTTP_TO_HTTPS:
|
case NGX_HTTP_TO_HTTPS:
|
||||||
case NGX_HTTPS_CERT_ERROR:
|
case NGX_HTTPS_CERT_ERROR:
|
||||||
case NGX_HTTPS_NO_CERT:
|
case NGX_HTTPS_NO_CERT:
|
||||||
|
case NGX_HTTP_REQUEST_HEADER_TOO_LARGE:
|
||||||
err->overwrite = NGX_HTTP_BAD_REQUEST;
|
err->overwrite = NGX_HTTP_BAD_REQUEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,6 +363,7 @@ struct ngx_http_core_loc_conf_s {
|
|||||||
ngx_msec_t lingering_time; /* lingering_time */
|
ngx_msec_t lingering_time; /* lingering_time */
|
||||||
ngx_msec_t lingering_timeout; /* lingering_timeout */
|
ngx_msec_t lingering_timeout; /* lingering_timeout */
|
||||||
ngx_msec_t resolver_timeout; /* resolver_timeout */
|
ngx_msec_t resolver_timeout; /* resolver_timeout */
|
||||||
|
ngx_msec_t auth_delay; /* auth_delay */
|
||||||
|
|
||||||
ngx_resolver_t *resolver; /* resolver */
|
ngx_resolver_t *resolver; /* resolver */
|
||||||
|
|
||||||
|
|||||||
@@ -1959,7 +1959,7 @@ ngx_http_file_cache_manager(void *data)
|
|||||||
{
|
{
|
||||||
ngx_http_file_cache_t *cache = data;
|
ngx_http_file_cache_t *cache = data;
|
||||||
|
|
||||||
off_t size;
|
off_t size, free;
|
||||||
time_t wait;
|
time_t wait;
|
||||||
ngx_msec_t elapsed, next;
|
ngx_msec_t elapsed, next;
|
||||||
ngx_uint_t count, watermark;
|
ngx_uint_t count, watermark;
|
||||||
@@ -1988,9 +1988,21 @@ ngx_http_file_cache_manager(void *data)
|
|||||||
size, count, (ngx_int_t) watermark);
|
size, count, (ngx_int_t) watermark);
|
||||||
|
|
||||||
if (size < cache->max_size && count < watermark) {
|
if (size < cache->max_size && count < watermark) {
|
||||||
|
|
||||||
|
if (!cache->min_free) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free = ngx_fs_available(cache->path->name.data);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
|
||||||
|
"http file cache free: %O", free);
|
||||||
|
|
||||||
|
if (free > cache->min_free) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wait = ngx_http_file_cache_forced_expire(cache);
|
wait = ngx_http_file_cache_forced_expire(cache);
|
||||||
|
|
||||||
if (wait > 0) {
|
if (wait > 0) {
|
||||||
@@ -2304,7 +2316,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
{
|
{
|
||||||
char *confp = conf;
|
char *confp = conf;
|
||||||
|
|
||||||
off_t max_size;
|
off_t max_size, min_free;
|
||||||
u_char *last, *p;
|
u_char *last, *p;
|
||||||
time_t inactive;
|
time_t inactive;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
@@ -2341,6 +2353,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
name.len = 0;
|
name.len = 0;
|
||||||
size = 0;
|
size = 0;
|
||||||
max_size = NGX_MAX_OFF_T_VALUE;
|
max_size = NGX_MAX_OFF_T_VALUE;
|
||||||
|
min_free = 0;
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
@@ -2476,6 +2489,29 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_strncmp(value[i].data, "min_free=", 9) == 0) {
|
||||||
|
|
||||||
|
#if (NGX_WIN32 || NGX_HAVE_STATFS || NGX_HAVE_STATVFS)
|
||||||
|
|
||||||
|
s.len = value[i].len - 9;
|
||||||
|
s.data = value[i].data + 9;
|
||||||
|
|
||||||
|
min_free = ngx_parse_offset(&s);
|
||||||
|
if (min_free < 0) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid min_free value \"%V\"", &value[i]);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"min_free is not supported "
|
||||||
|
"on this platform, ignored");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_strncmp(value[i].data, "loader_files=", 13) == 0) {
|
if (ngx_strncmp(value[i].data, "loader_files=", 13) == 0) {
|
||||||
|
|
||||||
loader_files = ngx_atoi(value[i].data + 13, value[i].len - 13);
|
loader_files = ngx_atoi(value[i].data + 13, value[i].len - 13);
|
||||||
@@ -2607,6 +2643,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
cache->inactive = inactive;
|
cache->inactive = inactive;
|
||||||
cache->max_size = max_size;
|
cache->max_size = max_size;
|
||||||
|
cache->min_free = min_free;
|
||||||
|
|
||||||
caches = (ngx_array_t *) (confp + cmd->offset);
|
caches = (ngx_array_t *) (confp + cmd->offset);
|
||||||
|
|
||||||
|
|||||||
@@ -912,6 +912,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
i = 1;
|
i = 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
hash = 0;
|
||||||
|
i = 0;
|
||||||
r->invalid_header = 1;
|
r->invalid_header = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,6 +924,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash = 0;
|
||||||
|
i = 0;
|
||||||
r->invalid_header = 1;
|
r->invalid_header = 1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1437,9 +1441,11 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
|
|||||||
state = sw_quoted;
|
state = sw_quoted;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
|
u--;
|
||||||
r->args_start = p;
|
r->args_start = p;
|
||||||
goto args;
|
goto args;
|
||||||
case '#':
|
case '#':
|
||||||
|
u--;
|
||||||
goto done;
|
goto done;
|
||||||
case '+':
|
case '+':
|
||||||
r->plus_in_uri = 1;
|
r->plus_in_uri = 1;
|
||||||
@@ -1467,8 +1473,9 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
|
|||||||
case '\\':
|
case '\\':
|
||||||
#endif
|
#endif
|
||||||
case '/':
|
case '/':
|
||||||
state = sw_slash;
|
case '?':
|
||||||
u -= 5;
|
case '#':
|
||||||
|
u -= 4;
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
if (u < r->uri.data) {
|
if (u < r->uri.data) {
|
||||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
@@ -1479,16 +1486,19 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
|
|||||||
}
|
}
|
||||||
u--;
|
u--;
|
||||||
}
|
}
|
||||||
|
if (ch == '?') {
|
||||||
|
r->args_start = p;
|
||||||
|
goto args;
|
||||||
|
}
|
||||||
|
if (ch == '#') {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
state = sw_slash;
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
quoted_state = state;
|
quoted_state = state;
|
||||||
state = sw_quoted;
|
state = sw_quoted;
|
||||||
break;
|
break;
|
||||||
case '?':
|
|
||||||
r->args_start = p;
|
|
||||||
goto args;
|
|
||||||
case '#':
|
|
||||||
goto done;
|
|
||||||
case '+':
|
case '+':
|
||||||
r->plus_in_uri = 1;
|
r->plus_in_uri = 1;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
@@ -1561,6 +1571,30 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state == sw_quoted || state == sw_quoted_second) {
|
||||||
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == sw_dot) {
|
||||||
|
u--;
|
||||||
|
|
||||||
|
} else if (state == sw_dot_dot) {
|
||||||
|
u -= 4;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
if (u < r->uri.data) {
|
||||||
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*u == '/') {
|
||||||
|
u++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
r->uri.len = u - r->uri.data;
|
r->uri.len = u - r->uri.data;
|
||||||
@@ -2268,6 +2302,9 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
break;
|
break;
|
||||||
case LF:
|
case LF:
|
||||||
state = sw_chunk_start;
|
state = sw_chunk_start;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto invalid;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
+49
-32
@@ -131,7 +131,7 @@ ngx_http_header_t ngx_http_headers_in[] = {
|
|||||||
|
|
||||||
{ ngx_string("Transfer-Encoding"),
|
{ ngx_string("Transfer-Encoding"),
|
||||||
offsetof(ngx_http_headers_in_t, transfer_encoding),
|
offsetof(ngx_http_headers_in_t, transfer_encoding),
|
||||||
ngx_http_process_header_line },
|
ngx_http_process_unique_header_line },
|
||||||
|
|
||||||
{ ngx_string("TE"),
|
{ ngx_string("TE"),
|
||||||
offsetof(ngx_http_headers_in_t, te),
|
offsetof(ngx_http_headers_in_t, te),
|
||||||
@@ -748,6 +748,8 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngx_reusable_connection(c, 0);
|
||||||
|
|
||||||
rc = ngx_ssl_handshake(c);
|
rc = ngx_ssl_handshake(c);
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
@@ -756,8 +758,6 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
|
|||||||
ngx_add_timer(rev, c->listening->post_accept_timeout);
|
ngx_add_timer(rev, c->listening->post_accept_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_reusable_connection(c, 0);
|
|
||||||
|
|
||||||
c->ssl->handler = ngx_http_ssl_handshake_handler;
|
c->ssl->handler = ngx_http_ssl_handshake_handler;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1654,6 +1654,12 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
|
|||||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"http large header copy: %uz", r->header_in->pos - old);
|
"http large header copy: %uz", r->header_in->pos - old);
|
||||||
|
|
||||||
|
if (r->header_in->pos - old > b->end - b->start) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||||
|
"too large header to copy");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
new = b->start;
|
new = b->start;
|
||||||
|
|
||||||
ngx_memcpy(new, old, r->header_in->pos - old);
|
ngx_memcpy(new, old, r->header_in->pos - old);
|
||||||
@@ -1762,10 +1768,18 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_str_t host;
|
ngx_str_t host;
|
||||||
|
|
||||||
if (r->headers_in.host == NULL) {
|
if (r->headers_in.host) {
|
||||||
r->headers_in.host = h;
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"client sent duplicate host header: \"%V: %V\", "
|
||||||
|
"previous value: \"%V: %V\"",
|
||||||
|
&h->key, &h->value, &r->headers_in.host->key,
|
||||||
|
&r->headers_in.host->value);
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->headers_in.host = h;
|
||||||
|
|
||||||
host = h->value;
|
host = h->value;
|
||||||
|
|
||||||
rc = ngx_http_validate_host(&host, r->pool, 0);
|
rc = ngx_http_validate_host(&host, r->pool, 0);
|
||||||
@@ -1962,10 +1976,7 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
|||||||
r->headers_in.content_length_n = -1;
|
r->headers_in.content_length_n = -1;
|
||||||
r->headers_in.chunked = 1;
|
r->headers_in.chunked = 1;
|
||||||
|
|
||||||
} else if (r->headers_in.transfer_encoding->value.len != 8
|
} else {
|
||||||
|| ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
|
|
||||||
(u_char *) "identity", 8) != 0)
|
|
||||||
{
|
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
"client sent unknown \"Transfer-Encoding\": \"%V\"",
|
"client sent unknown \"Transfer-Encoding\": \"%V\"",
|
||||||
&r->headers_in.transfer_encoding->value);
|
&r->headers_in.transfer_encoding->value);
|
||||||
@@ -1998,6 +2009,7 @@ ngx_http_process_request(ngx_http_request_t *r)
|
|||||||
if (r->http_connection->ssl) {
|
if (r->http_connection->ssl) {
|
||||||
long rc;
|
long rc;
|
||||||
X509 *cert;
|
X509 *cert;
|
||||||
|
const char *s;
|
||||||
ngx_http_ssl_srv_conf_t *sscf;
|
ngx_http_ssl_srv_conf_t *sscf;
|
||||||
|
|
||||||
if (c->ssl == NULL) {
|
if (c->ssl == NULL) {
|
||||||
@@ -2046,6 +2058,17 @@ ngx_http_process_request(ngx_http_request_t *r)
|
|||||||
|
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
|
"client SSL certificate verify error: %s", s);
|
||||||
|
|
||||||
|
ngx_ssl_remove_cached_session(c->ssl->session_ctx,
|
||||||
|
(SSL_get0_session(c->ssl->connection)));
|
||||||
|
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2497,26 +2520,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (r != r->main) {
|
if (r != r->main) {
|
||||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
|
||||||
|
|
||||||
if (r->background) {
|
|
||||||
if (!r->logged) {
|
|
||||||
if (clcf->log_subrequest) {
|
|
||||||
ngx_http_log_request(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
r->logged = 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
|
||||||
"subrequest: \"%V?%V\" logged again",
|
|
||||||
&r->uri, &r->args);
|
|
||||||
}
|
|
||||||
|
|
||||||
r->done = 1;
|
|
||||||
ngx_http_finalize_connection(r);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->buffered || r->postponed) {
|
if (r->buffered || r->postponed) {
|
||||||
|
|
||||||
@@ -2529,11 +2532,12 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
|||||||
|
|
||||||
pr = r->parent;
|
pr = r->parent;
|
||||||
|
|
||||||
if (r == c->data) {
|
if (r == c->data || r->background) {
|
||||||
|
|
||||||
r->main->count--;
|
|
||||||
|
|
||||||
if (!r->logged) {
|
if (!r->logged) {
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
if (clcf->log_subrequest) {
|
if (clcf->log_subrequest) {
|
||||||
ngx_http_log_request(r);
|
ngx_http_log_request(r);
|
||||||
}
|
}
|
||||||
@@ -2548,6 +2552,13 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
|||||||
|
|
||||||
r->done = 1;
|
r->done = 1;
|
||||||
|
|
||||||
|
if (r->background) {
|
||||||
|
ngx_http_finalize_connection(r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->main->count--;
|
||||||
|
|
||||||
if (pr->postponed && pr->postponed->request == r) {
|
if (pr->postponed && pr->postponed->request == r) {
|
||||||
pr->postponed = pr->postponed->next;
|
pr->postponed = pr->postponed->next;
|
||||||
}
|
}
|
||||||
@@ -2995,6 +3006,12 @@ closed:
|
|||||||
rev->error = 1;
|
rev->error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HTTP_SSL)
|
||||||
|
if (c->ssl) {
|
||||||
|
c->ssl->no_send_shutdown = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, err,
|
ngx_log_error(NGX_LOG_INFO, c->log, err,
|
||||||
"client prematurely closed connection");
|
"client prematurely closed connection");
|
||||||
|
|
||||||
|
|||||||
@@ -510,10 +510,10 @@ struct ngx_http_request_s {
|
|||||||
/*
|
/*
|
||||||
* instead of using the request context data in
|
* instead of using the request context data in
|
||||||
* ngx_http_limit_conn_module and ngx_http_limit_req_module
|
* ngx_http_limit_conn_module and ngx_http_limit_req_module
|
||||||
* we use the single bits in the request structure
|
* we use the bit fields in the request structure
|
||||||
*/
|
*/
|
||||||
unsigned limit_conn_set:1;
|
unsigned limit_conn_status:2;
|
||||||
unsigned limit_req_set:1;
|
unsigned limit_req_status:3;
|
||||||
|
|
||||||
unsigned limit_rate_set:1;
|
unsigned limit_rate_set:1;
|
||||||
unsigned limit_rate_after_set:1;
|
unsigned limit_rate_after_set:1;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
|
static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_copy_pipelined_header(ngx_http_request_t *r,
|
||||||
|
ngx_buf_t *buf);
|
||||||
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
|
||||||
@@ -282,21 +284,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
if (rb->buf->last == rb->buf->end) {
|
if (rb->buf->last == rb->buf->end) {
|
||||||
|
|
||||||
if (rb->buf->pos != rb->buf->last) {
|
|
||||||
|
|
||||||
/* pass buffer to request body filter chain */
|
|
||||||
|
|
||||||
out.buf = rb->buf;
|
|
||||||
out.next = NULL;
|
|
||||||
|
|
||||||
rc = ngx_http_request_body_filter(r, &out);
|
|
||||||
|
|
||||||
if (rc != NGX_OK) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* update chains */
|
/* update chains */
|
||||||
|
|
||||||
rc = ngx_http_request_body_filter(r, NULL);
|
rc = ngx_http_request_body_filter(r, NULL);
|
||||||
@@ -304,7 +291,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
if (rc != NGX_OK) {
|
if (rc != NGX_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (rb->busy != NULL) {
|
if (rb->busy != NULL) {
|
||||||
if (r->request_body_no_buffering) {
|
if (r->request_body_no_buffering) {
|
||||||
@@ -355,7 +341,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
rb->buf->last += n;
|
rb->buf->last += n;
|
||||||
r->request_length += n;
|
r->request_length += n;
|
||||||
|
|
||||||
if (n == rest) {
|
|
||||||
/* pass buffer to request body filter chain */
|
/* pass buffer to request body filter chain */
|
||||||
|
|
||||||
out.buf = rb->buf;
|
out.buf = rb->buf;
|
||||||
@@ -366,7 +351,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
if (rc != NGX_OK) {
|
if (rc != NGX_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (rb->rest == 0) {
|
if (rb->rest == 0) {
|
||||||
break;
|
break;
|
||||||
@@ -386,21 +370,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if (!c->read->ready) {
|
if (!c->read->ready) {
|
||||||
|
|
||||||
if (r->request_body_no_buffering
|
|
||||||
&& rb->buf->pos != rb->buf->last)
|
|
||||||
{
|
|
||||||
/* pass buffer to request body filter chain */
|
|
||||||
|
|
||||||
out.buf = rb->buf;
|
|
||||||
out.next = NULL;
|
|
||||||
|
|
||||||
rc = ngx_http_request_body_filter(r, &out);
|
|
||||||
|
|
||||||
if (rc != NGX_OK) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
ngx_add_timer(c->read, clcf->client_body_timeout);
|
ngx_add_timer(c->read, clcf->client_body_timeout);
|
||||||
|
|
||||||
@@ -412,6 +381,10 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_http_copy_pipelined_header(r, rb->buf) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (c->read->timer_set) {
|
if (c->read->timer_set) {
|
||||||
ngx_del_timer(c->read);
|
ngx_del_timer(c->read);
|
||||||
}
|
}
|
||||||
@@ -425,6 +398,88 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_copy_pipelined_header(ngx_http_request_t *r, ngx_buf_t *buf)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
ngx_buf_t *b;
|
||||||
|
ngx_chain_t *cl;
|
||||||
|
ngx_http_connection_t *hc;
|
||||||
|
ngx_http_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
b = r->header_in;
|
||||||
|
n = buf->last - buf->pos;
|
||||||
|
|
||||||
|
if (buf == b || n == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http body pipelined header: %uz", n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if there is a pipelined request in the client body buffer,
|
||||||
|
* copy it to the r->header_in buffer if there is enough room,
|
||||||
|
* or allocate a large client header buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (n > (size_t) (b->end - b->last)) {
|
||||||
|
|
||||||
|
hc = r->http_connection;
|
||||||
|
|
||||||
|
if (hc->free) {
|
||||||
|
cl = hc->free;
|
||||||
|
hc->free = cl->next;
|
||||||
|
|
||||||
|
b = cl->buf;
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http large header free: %p %uz",
|
||||||
|
b->pos, b->end - b->last);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
b = ngx_create_temp_buf(r->connection->pool,
|
||||||
|
cscf->large_client_header_buffers.size);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl = ngx_alloc_chain_link(r->connection->pool);
|
||||||
|
if (cl == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->buf = b;
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http large header alloc: %p %uz",
|
||||||
|
b->pos, b->end - b->last);
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->next = hc->busy;
|
||||||
|
hc->busy = cl;
|
||||||
|
hc->nbusy++;
|
||||||
|
|
||||||
|
r->header_in = b;
|
||||||
|
|
||||||
|
if (n > (size_t) (b->end - b->last)) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||||
|
"too large pipelined header after reading body");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(b->last, buf->pos, n);
|
||||||
|
|
||||||
|
b->last += n;
|
||||||
|
r->request_length -= n;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_write_request_body(ngx_http_request_t *r)
|
ngx_http_write_request_body(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
@@ -670,8 +725,7 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
|
|||||||
|
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
if (r->headers_in.content_length_n == 0) {
|
if (r->headers_in.content_length_n == 0) {
|
||||||
r->read_event_handler = ngx_http_block_reading;
|
break;
|
||||||
return NGX_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!r->connection->read->ready) {
|
if (!r->connection->read->ready) {
|
||||||
@@ -705,6 +759,14 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_http_copy_pipelined_header(r, &b) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->read_event_handler = ngx_http_block_reading;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -714,6 +776,7 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
size_t size;
|
size_t size;
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_http_request_body_t *rb;
|
ngx_http_request_body_t *rb;
|
||||||
|
ngx_http_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
if (r->headers_in.chunked) {
|
if (r->headers_in.chunked) {
|
||||||
|
|
||||||
@@ -768,7 +831,10 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
|
|
||||||
/* set amount of data we want to see next time */
|
/* set amount of data we want to see next time */
|
||||||
|
|
||||||
r->headers_in.content_length_n = rb->chunked->length;
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
r->headers_in.content_length_n = ngx_max(rb->chunked->length,
|
||||||
|
(off_t) cscf->large_client_header_buffers.size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,6 +1002,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
ngx_chain_t *cl, *out, *tl, **ll;
|
ngx_chain_t *cl, *out, *tl, **ll;
|
||||||
ngx_http_request_body_t *rb;
|
ngx_http_request_body_t *rb;
|
||||||
ngx_http_core_loc_conf_t *clcf;
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
ngx_http_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
rb = r->request_body;
|
rb = r->request_body;
|
||||||
|
|
||||||
@@ -949,8 +1016,10 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
r->headers_in.content_length_n = 0;
|
r->headers_in.content_length_n = 0;
|
||||||
rb->rest = 3;
|
rb->rest = cscf->large_client_header_buffers.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
out = NULL;
|
out = NULL;
|
||||||
@@ -958,6 +1027,8 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
|
|
||||||
for (cl = in; cl; cl = cl->next) {
|
for (cl = in; cl; cl = cl->next) {
|
||||||
|
|
||||||
|
b = NULL;
|
||||||
|
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
|
|
||||||
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
||||||
@@ -992,6 +1063,29 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
|
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b
|
||||||
|
&& rb->chunked->size <= 128
|
||||||
|
&& cl->buf->last - cl->buf->pos >= rb->chunked->size)
|
||||||
|
{
|
||||||
|
r->headers_in.content_length_n += rb->chunked->size;
|
||||||
|
|
||||||
|
if (rb->chunked->size < 8) {
|
||||||
|
|
||||||
|
while (rb->chunked->size) {
|
||||||
|
*b->last++ = *cl->buf->pos++;
|
||||||
|
rb->chunked->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_memmove(b->last, cl->buf->pos, rb->chunked->size);
|
||||||
|
b->last += rb->chunked->size;
|
||||||
|
cl->buf->pos += rb->chunked->size;
|
||||||
|
rb->chunked->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
||||||
if (tl == NULL) {
|
if (tl == NULL) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
@@ -1057,7 +1151,10 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
|
|
||||||
/* set rb->rest, amount of data we want to see next time */
|
/* set rb->rest, amount of data we want to see next time */
|
||||||
|
|
||||||
rb->rest = rb->chunked->length;
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
rb->rest = ngx_max(rb->chunked->length,
|
||||||
|
(off_t) cscf->large_client_header_buffers.size);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1470,7 +1470,14 @@ ngx_http_script_return_code(ngx_http_script_engine_t *e)
|
|||||||
void
|
void
|
||||||
ngx_http_script_break_code(ngx_http_script_engine_t *e)
|
ngx_http_script_break_code(ngx_http_script_engine_t *e)
|
||||||
{
|
{
|
||||||
e->request->uri_changed = 0;
|
ngx_http_request_t *r;
|
||||||
|
|
||||||
|
r = e->request;
|
||||||
|
|
||||||
|
if (r->uri_changed) {
|
||||||
|
r->valid_location = 0;
|
||||||
|
r->uri_changed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
e->ip = ngx_http_script_exit;
|
e->ip = ngx_http_script_exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ static u_char ngx_http_error_build_tail[] =
|
|||||||
|
|
||||||
|
|
||||||
static u_char ngx_http_error_tail[] =
|
static u_char ngx_http_error_tail[] =
|
||||||
|
"<hr><center>" NGINX_SERVER "</center>" CRLF
|
||||||
"</body>" CRLF
|
"</body>" CRLF
|
||||||
"</html>" CRLF
|
"</html>" CRLF
|
||||||
;
|
;
|
||||||
@@ -622,6 +623,12 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
|
|||||||
return ngx_http_named_location(r, &uri);
|
return ngx_http_named_location(r, &uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->expect_tested = 1;
|
||||||
|
|
||||||
|
if (ngx_http_discard_request_body(r) != NGX_OK) {
|
||||||
|
r->keepalive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
location = ngx_list_push(&r->headers_out.headers);
|
location = ngx_list_push(&r->headers_out.headers);
|
||||||
|
|
||||||
if (location == NULL) {
|
if (location == NULL) {
|
||||||
|
|||||||
@@ -77,9 +77,6 @@ static void
|
|||||||
static void
|
static void
|
||||||
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
||||||
ngx_uint_t do_write);
|
ngx_uint_t do_write);
|
||||||
static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
|
|
||||||
static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
|
|
||||||
ssize_t bytes);
|
|
||||||
#if (NGX_THREADS)
|
#if (NGX_THREADS)
|
||||||
static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
|
static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
|
||||||
ngx_file_t *file);
|
ngx_file_t *file);
|
||||||
@@ -1919,6 +1916,7 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
|
|
||||||
u->keepalive = 0;
|
u->keepalive = 0;
|
||||||
u->upgrade = 0;
|
u->upgrade = 0;
|
||||||
|
u->error = 0;
|
||||||
|
|
||||||
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
|
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
|
||||||
u->headers_in.content_length_n = -1;
|
u->headers_in.content_length_n = -1;
|
||||||
@@ -2475,7 +2473,7 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
#if (NGX_HTTP_CACHE)
|
#if (NGX_HTTP_CACHE)
|
||||||
|
|
||||||
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
|
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
|
||||||
&& ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error))
|
&& (u->conf->cache_use_stale & un->mask))
|
||||||
{
|
{
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
|
|
||||||
@@ -2502,6 +2500,8 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (NGX_HTTP_CACHE)
|
#if (NGX_HTTP_CACHE)
|
||||||
@@ -3625,7 +3625,7 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upstream->read->error) {
|
if (upstream->read->error || u->error) {
|
||||||
ngx_http_upstream_finalize_request(r, u,
|
ngx_http_upstream_finalize_request(r, u,
|
||||||
NGX_HTTP_BAD_GATEWAY);
|
NGX_HTTP_BAD_GATEWAY);
|
||||||
return;
|
return;
|
||||||
@@ -3703,14 +3703,14 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_upstream_non_buffered_filter_init(void *data)
|
ngx_http_upstream_non_buffered_filter_init(void *data)
|
||||||
{
|
{
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
|
ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
|
||||||
{
|
{
|
||||||
ngx_http_request_t *r = data;
|
ngx_http_request_t *r = data;
|
||||||
@@ -3746,6 +3746,18 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bytes > u->length) {
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||||
|
"upstream sent more data than specified in "
|
||||||
|
"\"Content-Length\" header");
|
||||||
|
|
||||||
|
cl->buf->last = cl->buf->pos + u->length;
|
||||||
|
u->length = 0;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
u->length -= bytes;
|
u->length -= bytes;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
|||||||
@@ -391,6 +391,7 @@ struct ngx_http_upstream_s {
|
|||||||
unsigned buffering:1;
|
unsigned buffering:1;
|
||||||
unsigned keepalive:1;
|
unsigned keepalive:1;
|
||||||
unsigned upgrade:1;
|
unsigned upgrade:1;
|
||||||
|
unsigned error:1;
|
||||||
|
|
||||||
unsigned request_sent:1;
|
unsigned request_sent:1;
|
||||||
unsigned request_body_sent:1;
|
unsigned request_body_sent:1;
|
||||||
@@ -414,6 +415,8 @@ typedef struct {
|
|||||||
|
|
||||||
ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r);
|
ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r);
|
||||||
void ngx_http_upstream_init(ngx_http_request_t *r);
|
void ngx_http_upstream_init(ngx_http_request_t *r);
|
||||||
|
ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
|
||||||
|
ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes);
|
||||||
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
|
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
|
||||||
ngx_url_t *u, ngx_uint_t flags);
|
ngx_url_t *u, ngx_uint_t flags);
|
||||||
char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
|||||||
@@ -199,10 +199,20 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
|||||||
{ ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
|
{ ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("proxy_protocol_addr"), NULL,
|
{ ngx_string("proxy_protocol_addr"), NULL,
|
||||||
ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
|
ngx_http_variable_proxy_protocol_addr,
|
||||||
|
offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("proxy_protocol_port"), NULL,
|
{ ngx_string("proxy_protocol_port"), NULL,
|
||||||
ngx_http_variable_proxy_protocol_port, 0, 0, 0 },
|
ngx_http_variable_proxy_protocol_port,
|
||||||
|
offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("proxy_protocol_server_addr"), NULL,
|
||||||
|
ngx_http_variable_proxy_protocol_addr,
|
||||||
|
offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("proxy_protocol_server_port"), NULL,
|
||||||
|
ngx_http_variable_proxy_protocol_port,
|
||||||
|
offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
|
{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
|
||||||
|
|
||||||
@@ -1065,7 +1075,7 @@ ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||||||
len = name->len - (sizeof("arg_") - 1);
|
len = name->len - (sizeof("arg_") - 1);
|
||||||
arg = name->data + sizeof("arg_") - 1;
|
arg = name->data + sizeof("arg_") - 1;
|
||||||
|
|
||||||
if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
|
if (len == 0 || ngx_http_arg(r, arg, len, &value) != NGX_OK) {
|
||||||
v->not_found = 1;
|
v->not_found = 1;
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -1293,11 +1303,22 @@ static ngx_int_t
|
|||||||
ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
|
ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data)
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
{
|
{
|
||||||
v->len = r->connection->proxy_protocol_addr.len;
|
ngx_str_t *addr;
|
||||||
|
ngx_proxy_protocol_t *pp;
|
||||||
|
|
||||||
|
pp = r->connection->proxy_protocol;
|
||||||
|
if (pp == NULL) {
|
||||||
|
v->not_found = 1;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (ngx_str_t *) ((char *) pp + data);
|
||||||
|
|
||||||
|
v->len = addr->len;
|
||||||
v->valid = 1;
|
v->valid = 1;
|
||||||
v->no_cacheable = 0;
|
v->no_cacheable = 0;
|
||||||
v->not_found = 0;
|
v->not_found = 0;
|
||||||
v->data = r->connection->proxy_protocol_addr.data;
|
v->data = addr->data;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -1308,6 +1329,13 @@ ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
|
|||||||
ngx_http_variable_value_t *v, uintptr_t data)
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
{
|
{
|
||||||
ngx_uint_t port;
|
ngx_uint_t port;
|
||||||
|
ngx_proxy_protocol_t *pp;
|
||||||
|
|
||||||
|
pp = r->connection->proxy_protocol;
|
||||||
|
if (pp == NULL) {
|
||||||
|
v->not_found = 1;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
v->len = 0;
|
v->len = 0;
|
||||||
v->valid = 1;
|
v->valid = 1;
|
||||||
@@ -1319,7 +1347,7 @@ ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
port = r->connection->proxy_protocol_port;
|
port = *(in_port_t *) ((char *) pp + data);
|
||||||
|
|
||||||
if (port > 0 && port < 65536) {
|
if (port > 0 && port < 65536) {
|
||||||
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
|
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
|
||||||
|
|||||||
+214
-110
@@ -60,6 +60,8 @@ typedef struct {
|
|||||||
static void ngx_http_v2_read_handler(ngx_event_t *rev);
|
static void ngx_http_v2_read_handler(ngx_event_t *rev);
|
||||||
static void ngx_http_v2_write_handler(ngx_event_t *wev);
|
static void ngx_http_v2_write_handler(ngx_event_t *wev);
|
||||||
static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
|
static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
|
||||||
|
static void ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c);
|
||||||
|
static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev);
|
||||||
|
|
||||||
static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
|
static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
|
||||||
u_char *pos, u_char *end);
|
u_char *pos, u_char *end);
|
||||||
@@ -178,6 +180,7 @@ static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r);
|
|||||||
static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
|
static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
|
||||||
ngx_http_v2_stream_t *stream, ngx_uint_t status);
|
ngx_http_v2_stream_t *stream, ngx_uint_t status);
|
||||||
static void ngx_http_v2_close_stream_handler(ngx_event_t *ev);
|
static void ngx_http_v2_close_stream_handler(ngx_event_t *ev);
|
||||||
|
static void ngx_http_v2_retry_close_stream_handler(ngx_event_t *ev);
|
||||||
static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev);
|
static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev);
|
||||||
static void ngx_http_v2_idle_handler(ngx_event_t *rev);
|
static void ngx_http_v2_idle_handler(ngx_event_t *rev);
|
||||||
static void ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
|
static void ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
|
||||||
@@ -275,6 +278,7 @@ ngx_http_v2_init(ngx_event_t *rev)
|
|||||||
h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
|
h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
|
||||||
|
|
||||||
h2c->concurrent_pushes = h2scf->concurrent_pushes;
|
h2c->concurrent_pushes = h2scf->concurrent_pushes;
|
||||||
|
h2c->priority_limit = h2scf->concurrent_streams;
|
||||||
|
|
||||||
h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
|
h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
|
||||||
if (h2c->pool == NULL) {
|
if (h2c->pool == NULL) {
|
||||||
@@ -355,6 +359,11 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
|
|||||||
if (c->close) {
|
if (c->close) {
|
||||||
c->close = 0;
|
c->close = 0;
|
||||||
|
|
||||||
|
if (c->error) {
|
||||||
|
ngx_http_v2_finalize_connection(h2c, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!h2c->goaway) {
|
if (!h2c->goaway) {
|
||||||
h2c->goaway = 1;
|
h2c->goaway = 1;
|
||||||
|
|
||||||
@@ -420,6 +429,14 @@ ngx_http_v2_read_handler(ngx_event_t *rev)
|
|||||||
|
|
||||||
} while (p != end);
|
} while (p != end);
|
||||||
|
|
||||||
|
h2c->total_bytes += n;
|
||||||
|
|
||||||
|
if (h2c->total_bytes / 8 > h2c->payload_bytes + 1048576) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0, "http2 flood detected");
|
||||||
|
ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} while (rev->ready);
|
} while (rev->ready);
|
||||||
|
|
||||||
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||||||
@@ -460,6 +477,7 @@ ngx_http_v2_write_handler(ngx_event_t *wev)
|
|||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
"http2 write event timed out");
|
"http2 write event timed out");
|
||||||
c->error = 1;
|
c->error = 1;
|
||||||
|
c->timedout = 1;
|
||||||
ngx_http_v2_finalize_connection(h2c, 0);
|
ngx_http_v2_finalize_connection(h2c, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -506,13 +524,12 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c)
|
|||||||
ngx_http_core_loc_conf_t *clcf;
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
c = h2c->connection;
|
c = h2c->connection;
|
||||||
|
wev = c->write;
|
||||||
|
|
||||||
if (c->error) {
|
if (c->error) {
|
||||||
return NGX_ERROR;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
wev = c->write;
|
|
||||||
|
|
||||||
if (!wev->ready) {
|
if (!wev->ready) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
@@ -649,7 +666,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (h2c->goaway) {
|
if (h2c->goaway) {
|
||||||
ngx_http_close_connection(c);
|
ngx_http_v2_lingering_close(h2c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,6 +704,113 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c)
|
||||||
|
{
|
||||||
|
ngx_event_t *rev, *wev;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
|
c = h2c->connection;
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
|
||||||
|
ngx_http_core_module);
|
||||||
|
|
||||||
|
if (clcf->lingering_close == NGX_HTTP_LINGERING_OFF) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rev = c->read;
|
||||||
|
rev->handler = ngx_http_v2_lingering_close_handler;
|
||||||
|
|
||||||
|
h2c->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
|
||||||
|
ngx_add_timer(rev, clcf->lingering_timeout);
|
||||||
|
|
||||||
|
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wev = c->write;
|
||||||
|
wev->handler = ngx_http_empty_handler;
|
||||||
|
|
||||||
|
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
|
||||||
|
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
|
||||||
|
ngx_connection_error(c, ngx_socket_errno,
|
||||||
|
ngx_shutdown_socket_n " failed");
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rev->ready) {
|
||||||
|
ngx_http_v2_lingering_close_handler(rev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_v2_lingering_close_handler(ngx_event_t *rev)
|
||||||
|
{
|
||||||
|
ssize_t n;
|
||||||
|
ngx_msec_t timer;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
ngx_http_v2_connection_t *h2c;
|
||||||
|
u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
|
||||||
|
|
||||||
|
c = rev->data;
|
||||||
|
h2c = c->data;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"http2 lingering close handler");
|
||||||
|
|
||||||
|
if (rev->timedout) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer = (ngx_msec_t) h2c->lingering_time - (ngx_msec_t) ngx_time();
|
||||||
|
if ((ngx_msec_int_t) timer <= 0) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
|
||||||
|
|
||||||
|
if (n == NGX_ERROR || n == 0) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (rev->ready);
|
||||||
|
|
||||||
|
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||||||
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
|
||||||
|
ngx_http_core_module);
|
||||||
|
timer *= 1000;
|
||||||
|
|
||||||
|
if (timer > clcf->lingering_timeout) {
|
||||||
|
timer = clcf->lingering_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_add_timer(rev, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u_char *
|
static u_char *
|
||||||
ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos,
|
ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||||
u_char *end)
|
u_char *end)
|
||||||
@@ -719,9 +843,8 @@ ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
|
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
"invalid http2 connection preface \"%*s\"",
|
"invalid connection preface");
|
||||||
sizeof(preface) - 1, pos);
|
|
||||||
|
|
||||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
@@ -742,9 +865,8 @@ ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
|
if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) {
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
"invalid http2 connection preface \"%*s\"",
|
"invalid connection preface");
|
||||||
sizeof(preface) - 1, pos);
|
|
||||||
|
|
||||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
@@ -948,6 +1070,15 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
return ngx_http_v2_state_skip_padded(h2c, pos, end);
|
return ngx_http_v2_state_skip_padded(h2c, pos, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = stream->request;
|
||||||
|
|
||||||
|
if (r->reading_body && !r->request_body_no_buffering) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||||
|
"skipping http2 DATA frame");
|
||||||
|
|
||||||
|
return ngx_http_v2_state_skip_padded(h2c, pos, end);
|
||||||
|
}
|
||||||
|
|
||||||
size = end - pos;
|
size = end - pos;
|
||||||
|
|
||||||
if (size >= h2c->state.length) {
|
if (size >= h2c->state.length) {
|
||||||
@@ -955,7 +1086,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
|
stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = stream->request;
|
h2c->payload_bytes += size;
|
||||||
|
|
||||||
if (r->request_body) {
|
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);
|
||||||
@@ -1101,20 +1232,19 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
h2c->last_sid = h2c->state.sid;
|
|
||||||
|
|
||||||
h2c->state.pool = ngx_create_pool(1024, h2c->connection->log);
|
|
||||||
if (h2c->state.pool == NULL) {
|
|
||||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depend == h2c->state.sid) {
|
if (depend == h2c->state.sid) {
|
||||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
"client sent HEADERS frame for stream %ui "
|
"client sent HEADERS frame for stream %ui "
|
||||||
"with incorrect dependency", h2c->state.sid);
|
"with incorrect dependency", h2c->state.sid);
|
||||||
|
|
||||||
status = NGX_HTTP_V2_PROTOCOL_ERROR;
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
goto rst_stream;
|
}
|
||||||
|
|
||||||
|
h2c->last_sid = h2c->state.sid;
|
||||||
|
|
||||||
|
h2c->state.pool = ngx_create_pool(1024, h2c->connection->log);
|
||||||
|
if (h2c->state.pool == NULL) {
|
||||||
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
|
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
|
||||||
@@ -1548,6 +1678,14 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
header->name.len = h2c->state.field_end - h2c->state.field_start;
|
header->name.len = h2c->state.field_end - h2c->state.field_start;
|
||||||
header->name.data = h2c->state.field_start;
|
header->name.data = h2c->state.field_start;
|
||||||
|
|
||||||
|
if (header->name.len == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
|
"client sent zero header name length");
|
||||||
|
|
||||||
|
return ngx_http_v2_connection_error(h2c,
|
||||||
|
NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
return ngx_http_v2_state_field_len(h2c, pos, end);
|
return ngx_http_v2_state_field_len(h2c, pos, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1691,10 +1829,15 @@ ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
ngx_http_v2_stream_t *stream;
|
ngx_http_v2_stream_t *stream;
|
||||||
|
|
||||||
if (h2c->state.length) {
|
if (h2c->state.length) {
|
||||||
|
if (end - pos > 0) {
|
||||||
h2c->state.handler = ngx_http_v2_state_header_block;
|
h2c->state.handler = ngx_http_v2_state_header_block;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ngx_http_v2_state_headers_save(h2c, pos, end,
|
||||||
|
ngx_http_v2_state_header_block);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)) {
|
if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)) {
|
||||||
return ngx_http_v2_handle_continuation(h2c, pos, end,
|
return ngx_http_v2_handle_continuation(h2c, pos, end,
|
||||||
ngx_http_v2_state_header_complete);
|
ngx_http_v2_state_header_complete);
|
||||||
@@ -1798,6 +1941,13 @@ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (--h2c->priority_limit == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
|
"client sent too many PRIORITY frames");
|
||||||
|
|
||||||
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM);
|
||||||
|
}
|
||||||
|
|
||||||
if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) {
|
if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) {
|
||||||
return ngx_http_v2_state_save(h2c, pos, end,
|
return ngx_http_v2_state_save(h2c, pos, end,
|
||||||
ngx_http_v2_state_priority);
|
ngx_http_v2_state_priority);
|
||||||
@@ -1828,28 +1978,7 @@ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
"client sent PRIORITY frame for stream %ui "
|
"client sent PRIORITY frame for stream %ui "
|
||||||
"with incorrect dependency", h2c->state.sid);
|
"with incorrect dependency", h2c->state.sid);
|
||||||
|
|
||||||
node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0);
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
|
|
||||||
if (node && node->stream) {
|
|
||||||
if (ngx_http_v2_terminate_stream(h2c, node->stream,
|
|
||||||
NGX_HTTP_V2_PROTOCOL_ERROR)
|
|
||||||
== NGX_ERROR)
|
|
||||||
{
|
|
||||||
return ngx_http_v2_connection_error(h2c,
|
|
||||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid,
|
|
||||||
NGX_HTTP_V2_PROTOCOL_ERROR)
|
|
||||||
== NGX_ERROR)
|
|
||||||
{
|
|
||||||
return ngx_http_v2_connection_error(h2c,
|
|
||||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ngx_http_v2_state_complete(h2c, pos, end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1);
|
node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1);
|
||||||
@@ -2240,41 +2369,11 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||||||
h2c->state.sid, window);
|
h2c->state.sid, window);
|
||||||
|
|
||||||
if (window == 0) {
|
if (window == 0) {
|
||||||
if (h2c->state.sid == 0) {
|
|
||||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
"client sent WINDOW_UPDATE frame "
|
"client sent WINDOW_UPDATE frame "
|
||||||
"with incorrect window increment 0");
|
"with incorrect window increment 0");
|
||||||
|
|
||||||
return ngx_http_v2_connection_error(h2c,
|
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||||
NGX_HTTP_V2_PROTOCOL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
|
||||||
"client sent WINDOW_UPDATE frame for stream %ui "
|
|
||||||
"with incorrect window increment 0", h2c->state.sid);
|
|
||||||
|
|
||||||
node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0);
|
|
||||||
|
|
||||||
if (node && node->stream) {
|
|
||||||
if (ngx_http_v2_terminate_stream(h2c, node->stream,
|
|
||||||
NGX_HTTP_V2_PROTOCOL_ERROR)
|
|
||||||
== NGX_ERROR)
|
|
||||||
{
|
|
||||||
return ngx_http_v2_connection_error(h2c,
|
|
||||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid,
|
|
||||||
NGX_HTTP_V2_PROTOCOL_ERROR)
|
|
||||||
== NGX_ERROR)
|
|
||||||
{
|
|
||||||
return ngx_http_v2_connection_error(h2c,
|
|
||||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ngx_http_v2_state_complete(h2c, pos, end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h2c->state.sid) {
|
if (h2c->state.sid) {
|
||||||
@@ -2490,10 +2589,6 @@ ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c,
|
|||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||||
"http2 state connection error");
|
"http2 state connection error");
|
||||||
|
|
||||||
if (err == NGX_HTTP_V2_INTERNAL_ERROR) {
|
|
||||||
ngx_debug_point();
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_http_v2_finalize_connection(h2c, err);
|
ngx_http_v2_finalize_connection(h2c, err);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2948,9 +3043,9 @@ ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length,
|
|||||||
"requested control frame is too large: %uz", length);
|
"requested control frame is too large: %uz", length);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
frame->length = length;
|
frame->length = length;
|
||||||
#endif
|
|
||||||
|
|
||||||
buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type);
|
buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type);
|
||||||
|
|
||||||
@@ -2977,6 +3072,8 @@ ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c,
|
|||||||
frame->next = h2c->free_frames;
|
frame->next = h2c->free_frames;
|
||||||
h2c->free_frames = frame;
|
h2c->free_frames = frame;
|
||||||
|
|
||||||
|
h2c->total_bytes += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3122,6 +3219,8 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push)
|
|||||||
h2c->processing++;
|
h2c->processing++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2c->priority_limit += h2scf->concurrent_streams;
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3259,10 +3358,6 @@ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
|
|||||||
ngx_uint_t i;
|
ngx_uint_t i;
|
||||||
ngx_http_core_srv_conf_t *cscf;
|
ngx_http_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
if (header->name.len == 0) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->invalid_header = 0;
|
r->invalid_header = 0;
|
||||||
|
|
||||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
@@ -3765,6 +3860,7 @@ static void
|
|||||||
ngx_http_v2_run_request(ngx_http_request_t *r)
|
ngx_http_v2_run_request(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
ngx_connection_t *fc;
|
ngx_connection_t *fc;
|
||||||
|
ngx_http_v2_connection_t *h2c;
|
||||||
|
|
||||||
fc = r->connection;
|
fc = r->connection;
|
||||||
|
|
||||||
@@ -3796,6 +3892,10 @@ ngx_http_v2_run_request(ngx_http_request_t *r)
|
|||||||
r->headers_in.chunked = 1;
|
r->headers_in.chunked = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2c = r->stream->connection;
|
||||||
|
|
||||||
|
h2c->payload_bytes += r->request_length;
|
||||||
|
|
||||||
ngx_http_process_request(r);
|
ngx_http_process_request(r);
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
@@ -4308,8 +4408,9 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc)
|
|||||||
fc = stream->request->connection;
|
fc = stream->request->connection;
|
||||||
|
|
||||||
if (stream->queued) {
|
if (stream->queued) {
|
||||||
fc->write->handler = ngx_http_v2_close_stream_handler;
|
fc->error = 1;
|
||||||
fc->read->handler = ngx_http_empty_handler;
|
fc->write->handler = ngx_http_v2_retry_close_stream_handler;
|
||||||
|
fc->read->handler = ngx_http_v2_retry_close_stream_handler;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4325,33 +4426,11 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (!stream->in_closed) {
|
} else if (!stream->in_closed) {
|
||||||
#if 0
|
|
||||||
if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR)
|
if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
h2c->connection->error = 1;
|
h2c->connection->error = 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* At the time of writing at least the latest versions of Chrome
|
|
||||||
* do not properly handle RST_STREAM with NO_ERROR status.
|
|
||||||
*
|
|
||||||
* See: https://bugs.chromium.org/p/chromium/issues/detail?id=603182
|
|
||||||
*
|
|
||||||
* As a workaround, the stream window is maximized before closing
|
|
||||||
* the stream. This allows a client to send up to 2 GB of data
|
|
||||||
* before getting blocked on flow control.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW
|
|
||||||
&& ngx_http_v2_send_window_update(h2c, node->id,
|
|
||||||
NGX_HTTP_V2_MAX_WINDOW
|
|
||||||
- stream->recv_window)
|
|
||||||
!= NGX_OK)
|
|
||||||
{
|
|
||||||
h2c->connection->error = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4375,6 +4454,8 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc)
|
|||||||
*/
|
*/
|
||||||
pool = stream->pool;
|
pool = stream->pool;
|
||||||
|
|
||||||
|
h2c->frames -= stream->frames;
|
||||||
|
|
||||||
ngx_http_free_request(stream->request, rc);
|
ngx_http_free_request(stream->request, rc);
|
||||||
|
|
||||||
if (pool != h2c->state.pool) {
|
if (pool != h2c->state.pool) {
|
||||||
@@ -4451,6 +4532,22 @@ ngx_http_v2_close_stream_handler(ngx_event_t *ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_v2_retry_close_stream_handler(ngx_event_t *ev)
|
||||||
|
{
|
||||||
|
ngx_connection_t *fc;
|
||||||
|
ngx_http_request_t *r;
|
||||||
|
|
||||||
|
fc = ev->data;
|
||||||
|
r = fc->data;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||||
|
"http2 retry close stream handler");
|
||||||
|
|
||||||
|
ngx_http_v2_close_stream(r->stream, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_http_v2_handle_connection_handler(ngx_event_t *rev)
|
ngx_http_v2_handle_connection_handler(ngx_event_t *rev)
|
||||||
{
|
{
|
||||||
@@ -4564,16 +4661,15 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
|
|||||||
h2c->blocked = 1;
|
h2c->blocked = 1;
|
||||||
|
|
||||||
if (!c->error && !h2c->goaway) {
|
if (!c->error && !h2c->goaway) {
|
||||||
|
h2c->goaway = 1;
|
||||||
|
|
||||||
if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
|
if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
|
||||||
(void) ngx_http_v2_send_output_queue(h2c);
|
(void) ngx_http_v2_send_output_queue(h2c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c->error = 1;
|
|
||||||
|
|
||||||
if (!h2c->processing && !h2c->pushing) {
|
if (!h2c->processing && !h2c->pushing) {
|
||||||
ngx_http_close_connection(c);
|
goto done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c->read->handler = ngx_http_empty_handler;
|
c->read->handler = ngx_http_empty_handler;
|
||||||
@@ -4621,10 +4717,18 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
|
|||||||
h2c->blocked = 0;
|
h2c->blocked = 0;
|
||||||
|
|
||||||
if (h2c->processing || h2c->pushing) {
|
if (h2c->processing || h2c->pushing) {
|
||||||
|
c->error = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
if (c->error) {
|
||||||
ngx_http_close_connection(c);
|
ngx_http_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_http_v2_lingering_close(h2c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -167,9 +167,13 @@ struct ngx_http_v2_connection_s {
|
|||||||
ngx_connection_t *connection;
|
ngx_connection_t *connection;
|
||||||
ngx_http_connection_t *http_connection;
|
ngx_http_connection_t *http_connection;
|
||||||
|
|
||||||
|
off_t total_bytes;
|
||||||
|
off_t payload_bytes;
|
||||||
|
|
||||||
ngx_uint_t processing;
|
ngx_uint_t processing;
|
||||||
ngx_uint_t frames;
|
ngx_uint_t frames;
|
||||||
ngx_uint_t idle;
|
ngx_uint_t idle;
|
||||||
|
ngx_uint_t priority_limit;
|
||||||
|
|
||||||
ngx_uint_t pushing;
|
ngx_uint_t pushing;
|
||||||
ngx_uint_t concurrent_pushes;
|
ngx_uint_t concurrent_pushes;
|
||||||
@@ -203,6 +207,8 @@ struct ngx_http_v2_connection_s {
|
|||||||
ngx_uint_t last_sid;
|
ngx_uint_t last_sid;
|
||||||
ngx_uint_t last_push;
|
ngx_uint_t last_push;
|
||||||
|
|
||||||
|
time_t lingering_time;
|
||||||
|
|
||||||
unsigned closed_nodes:8;
|
unsigned closed_nodes:8;
|
||||||
unsigned settings_ack:1;
|
unsigned settings_ack:1;
|
||||||
unsigned table_update:1;
|
unsigned table_update:1;
|
||||||
@@ -247,6 +253,8 @@ struct ngx_http_v2_stream_s {
|
|||||||
|
|
||||||
ngx_buf_t *preread;
|
ngx_buf_t *preread;
|
||||||
|
|
||||||
|
ngx_uint_t frames;
|
||||||
|
|
||||||
ngx_http_v2_out_frame_t *free_frames;
|
ngx_http_v2_out_frame_t *free_frames;
|
||||||
ngx_chain_t *free_frame_headers;
|
ngx_chain_t *free_frame_headers;
|
||||||
ngx_chain_t *free_bufs;
|
ngx_chain_t *free_bufs;
|
||||||
|
|||||||
@@ -1649,18 +1649,30 @@ ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream,
|
|||||||
ngx_buf_t *buf;
|
ngx_buf_t *buf;
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *cl;
|
||||||
ngx_http_v2_out_frame_t *frame;
|
ngx_http_v2_out_frame_t *frame;
|
||||||
|
ngx_http_v2_connection_t *h2c;
|
||||||
|
|
||||||
frame = stream->free_frames;
|
frame = stream->free_frames;
|
||||||
|
h2c = stream->connection;
|
||||||
|
|
||||||
if (frame) {
|
if (frame) {
|
||||||
stream->free_frames = frame->next;
|
stream->free_frames = frame->next;
|
||||||
|
|
||||||
} else {
|
} else if (h2c->frames < 10000) {
|
||||||
frame = ngx_palloc(stream->request->pool,
|
frame = ngx_palloc(stream->request->pool,
|
||||||
sizeof(ngx_http_v2_out_frame_t));
|
sizeof(ngx_http_v2_out_frame_t));
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream->frames++;
|
||||||
|
h2c->frames++;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||||
|
"http2 flood detected");
|
||||||
|
|
||||||
|
h2c->connection->error = 1;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0;
|
flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0;
|
||||||
@@ -1841,6 +1853,8 @@ ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c,
|
|||||||
stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE
|
stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE
|
||||||
+ frame->length;
|
+ frame->length;
|
||||||
|
|
||||||
|
h2c->payload_bytes += frame->length;
|
||||||
|
|
||||||
ngx_http_v2_handle_frame(stream, frame);
|
ngx_http_v2_handle_frame(stream, frame);
|
||||||
|
|
||||||
ngx_http_v2_handle_stream(h2c, stream);
|
ngx_http_v2_handle_stream(h2c, stream);
|
||||||
@@ -1895,6 +1909,8 @@ ngx_http_v2_push_frame_handler(ngx_http_v2_connection_t *h2c,
|
|||||||
stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE
|
stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE
|
||||||
+ frame->length;
|
+ frame->length;
|
||||||
|
|
||||||
|
h2c->payload_bytes += frame->length;
|
||||||
|
|
||||||
ngx_http_v2_handle_frame(stream, frame);
|
ngx_http_v2_handle_frame(stream, frame);
|
||||||
|
|
||||||
ngx_http_v2_handle_stream(h2c, stream);
|
ngx_http_v2_handle_stream(h2c, stream);
|
||||||
@@ -1988,6 +2004,8 @@ done:
|
|||||||
|
|
||||||
stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE;
|
stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE;
|
||||||
|
|
||||||
|
h2c->payload_bytes += frame->length;
|
||||||
|
|
||||||
ngx_http_v2_handle_frame(stream, frame);
|
ngx_http_v2_handle_frame(stream, frame);
|
||||||
|
|
||||||
ngx_http_v2_handle_stream(h2c, stream);
|
ngx_http_v2_handle_stream(h2c, stream);
|
||||||
@@ -2001,11 +2019,16 @@ ngx_http_v2_handle_frame(ngx_http_v2_stream_t *stream,
|
|||||||
ngx_http_v2_out_frame_t *frame)
|
ngx_http_v2_out_frame_t *frame)
|
||||||
{
|
{
|
||||||
ngx_http_request_t *r;
|
ngx_http_request_t *r;
|
||||||
|
ngx_http_v2_connection_t *h2c;
|
||||||
|
|
||||||
r = stream->request;
|
r = stream->request;
|
||||||
|
|
||||||
r->connection->sent += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length;
|
r->connection->sent += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length;
|
||||||
|
|
||||||
|
h2c = stream->connection;
|
||||||
|
|
||||||
|
h2c->total_bytes += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length;
|
||||||
|
|
||||||
if (frame->fin) {
|
if (frame->fin) {
|
||||||
stream->out_closed = 1;
|
stream->out_closed = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
|
static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
|
||||||
static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
|
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_resolve_name_handler(ngx_resolver_ctx_t *ctx);
|
||||||
|
static void ngx_mail_smtp_block_reading(ngx_event_t *rev);
|
||||||
static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
|
static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
|
||||||
static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
|
static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
|
||||||
static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
|
static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
|
||||||
@@ -88,6 +89,9 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||||||
ctx->data = s;
|
ctx->data = s;
|
||||||
ctx->timeout = cscf->resolver_timeout;
|
ctx->timeout = cscf->resolver_timeout;
|
||||||
|
|
||||||
|
s->resolver_ctx = ctx;
|
||||||
|
c->read->handler = ngx_mail_smtp_block_reading;
|
||||||
|
|
||||||
if (ngx_resolve_addr(ctx) != NGX_OK) {
|
if (ngx_resolve_addr(ctx) != NGX_OK) {
|
||||||
ngx_mail_close_connection(c);
|
ngx_mail_close_connection(c);
|
||||||
}
|
}
|
||||||
@@ -169,6 +173,9 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)
|
|||||||
ctx->data = s;
|
ctx->data = s;
|
||||||
ctx->timeout = cscf->resolver_timeout;
|
ctx->timeout = cscf->resolver_timeout;
|
||||||
|
|
||||||
|
s->resolver_ctx = ctx;
|
||||||
|
c->read->handler = ngx_mail_smtp_block_reading;
|
||||||
|
|
||||||
if (ngx_resolve_name(ctx) != NGX_OK) {
|
if (ngx_resolve_name(ctx) != NGX_OK) {
|
||||||
ngx_mail_close_connection(c);
|
ngx_mail_close_connection(c);
|
||||||
}
|
}
|
||||||
@@ -238,6 +245,38 @@ found:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_mail_smtp_block_reading(ngx_event_t *rev)
|
||||||
|
{
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_mail_session_t *s;
|
||||||
|
ngx_resolver_ctx_t *ctx;
|
||||||
|
|
||||||
|
c = rev->data;
|
||||||
|
s = c->data;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp reading blocked");
|
||||||
|
|
||||||
|
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||||||
|
|
||||||
|
if (s->resolver_ctx) {
|
||||||
|
ctx = s->resolver_ctx;
|
||||||
|
|
||||||
|
if (ctx->handler == ngx_mail_smtp_resolve_addr_handler) {
|
||||||
|
ngx_resolve_addr_done(ctx);
|
||||||
|
|
||||||
|
} else if (ctx->handler == ngx_mail_smtp_resolve_name_handler) {
|
||||||
|
ngx_resolve_name_done(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->resolver_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_mail_close_connection(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
|
ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
@@ -258,6 +297,10 @@ ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||||||
ngx_mail_close_connection(c);
|
ngx_mail_close_connection(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->read->ready) {
|
||||||
|
ngx_post_event(c->read, &ngx_posted_events);
|
||||||
|
}
|
||||||
|
|
||||||
if (sscf->greeting_delay) {
|
if (sscf->greeting_delay) {
|
||||||
c->read->handler = ngx_mail_smtp_invalid_pipelining;
|
c->read->handler = ngx_mail_smtp_invalid_pipelining;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
"no ssl_client_certificate for ssl_client_verify");
|
"no ssl_client_certificate for ssl_verify_client");
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -875,9 +875,28 @@ ngx_fs_bsize(u_char *name)
|
|||||||
return 512;
|
return 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_LINUX)
|
||||||
|
if ((size_t) fs.f_bsize > ngx_pagesize) {
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return (size_t) fs.f_bsize;
|
return (size_t) fs.f_bsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t
|
||||||
|
ngx_fs_available(u_char *name)
|
||||||
|
{
|
||||||
|
struct statfs fs;
|
||||||
|
|
||||||
|
if (statfs((char *) name, &fs) == -1) {
|
||||||
|
return NGX_MAX_OFF_T_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (off_t) fs.f_bavail * fs.f_bsize;
|
||||||
|
}
|
||||||
|
|
||||||
#elif (NGX_HAVE_STATVFS)
|
#elif (NGX_HAVE_STATVFS)
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -893,9 +912,28 @@ ngx_fs_bsize(u_char *name)
|
|||||||
return 512;
|
return 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_LINUX)
|
||||||
|
if ((size_t) fs.f_frsize > ngx_pagesize) {
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return (size_t) fs.f_frsize;
|
return (size_t) fs.f_frsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t
|
||||||
|
ngx_fs_available(u_char *name)
|
||||||
|
{
|
||||||
|
struct statvfs fs;
|
||||||
|
|
||||||
|
if (statvfs((char *) name, &fs) == -1) {
|
||||||
|
return NGX_MAX_OFF_T_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (off_t) fs.f_bavail * fs.f_frsize;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -904,4 +942,11 @@ ngx_fs_bsize(u_char *name)
|
|||||||
return 512;
|
return 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t
|
||||||
|
ngx_fs_available(u_char *name)
|
||||||
|
{
|
||||||
|
return NGX_MAX_OFF_T_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -185,7 +185,10 @@ ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
|
|||||||
#define ngx_is_exec(sb) (((sb)->st_mode & S_IXUSR) == S_IXUSR)
|
#define ngx_is_exec(sb) (((sb)->st_mode & S_IXUSR) == S_IXUSR)
|
||||||
#define ngx_file_access(sb) ((sb)->st_mode & 0777)
|
#define ngx_file_access(sb) ((sb)->st_mode & 0777)
|
||||||
#define ngx_file_size(sb) (sb)->st_size
|
#define ngx_file_size(sb) (sb)->st_size
|
||||||
#define ngx_file_fs_size(sb) ngx_max((sb)->st_size, (sb)->st_blocks * 512)
|
#define ngx_file_fs_size(sb) \
|
||||||
|
(((sb)->st_blocks * 512 > (sb)->st_size \
|
||||||
|
&& (sb)->st_blocks * 512 < (sb)->st_size + 8 * (sb)->st_blksize) \
|
||||||
|
? (sb)->st_blocks * 512 : (sb)->st_size)
|
||||||
#define ngx_file_mtime(sb) (sb)->st_mtime
|
#define ngx_file_mtime(sb) (sb)->st_mtime
|
||||||
#define ngx_file_uniq(sb) (sb)->st_ino
|
#define ngx_file_uniq(sb) (sb)->st_ino
|
||||||
|
|
||||||
@@ -346,6 +349,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t ngx_fs_bsize(u_char *name);
|
size_t ngx_fs_bsize(u_char *name);
|
||||||
|
off_t ngx_fs_available(u_char *name);
|
||||||
|
|
||||||
|
|
||||||
#if (NGX_HAVE_OPENAT)
|
#if (NGX_HAVE_OPENAT)
|
||||||
|
|||||||
@@ -77,12 +77,11 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
|
|||||||
u_char *p;
|
u_char *p;
|
||||||
size_t size;
|
size_t size;
|
||||||
ngx_int_t i;
|
ngx_int_t i;
|
||||||
ngx_uint_t n, sigio;
|
ngx_uint_t sigio;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
struct itimerval itv;
|
struct itimerval itv;
|
||||||
ngx_uint_t live;
|
ngx_uint_t live;
|
||||||
ngx_msec_t delay;
|
ngx_msec_t delay;
|
||||||
ngx_listening_t *ls;
|
|
||||||
ngx_core_conf_t *ccf;
|
ngx_core_conf_t *ccf;
|
||||||
|
|
||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
@@ -204,16 +203,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
|
|||||||
if (ngx_quit) {
|
if (ngx_quit) {
|
||||||
ngx_signal_worker_processes(cycle,
|
ngx_signal_worker_processes(cycle,
|
||||||
ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
|
ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
|
||||||
|
ngx_close_listening_sockets(cycle);
|
||||||
ls = cycle->listening.elts;
|
|
||||||
for (n = 0; n < cycle->listening.nelts; n++) {
|
|
||||||
if (ngx_close_socket(ls[n].fd) == -1) {
|
|
||||||
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
|
|
||||||
ngx_close_socket_n " %V failed",
|
|
||||||
&ls[n].addr_text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cycle->listening.nelts = 0;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
|
|||||||
"readv: eof:%d, avail:%d",
|
"readv: eof:%d, avail:%d",
|
||||||
rev->pending_eof, rev->available);
|
rev->pending_eof, rev->available);
|
||||||
|
|
||||||
if (!rev->available && !rev->pending_eof) {
|
if (rev->available == 0 && !rev->pending_eof) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,6 +165,40 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_FIONREAD)
|
||||||
|
|
||||||
|
if (rev->available >= 0) {
|
||||||
|
rev->available -= n;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* negative rev->available means some additional bytes
|
||||||
|
* were received between kernel notification and readv(),
|
||||||
|
* and therefore ev->ready can be safely reset even for
|
||||||
|
* edge-triggered event methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (rev->available < 0) {
|
||||||
|
rev->available = 0;
|
||||||
|
rev->ready = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"readv: avail:%d", rev->available);
|
||||||
|
|
||||||
|
} else if (n == size) {
|
||||||
|
|
||||||
|
if (ngx_socket_nread(c->fd, &rev->available) == -1) {
|
||||||
|
n = ngx_connection_error(c, ngx_socket_errno,
|
||||||
|
ngx_socket_nread_n " failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"readv: avail:%d", rev->available);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NGX_HAVE_EPOLLRDHUP)
|
#if (NGX_HAVE_EPOLLRDHUP)
|
||||||
|
|
||||||
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
||||||
|
|||||||
+35
-1
@@ -57,7 +57,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||||||
"recv: eof:%d, avail:%d",
|
"recv: eof:%d, avail:%d",
|
||||||
rev->pending_eof, rev->available);
|
rev->pending_eof, rev->available);
|
||||||
|
|
||||||
if (!rev->available && !rev->pending_eof) {
|
if (rev->available == 0 && !rev->pending_eof) {
|
||||||
rev->ready = 0;
|
rev->ready = 0;
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
@@ -116,6 +116,40 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_FIONREAD)
|
||||||
|
|
||||||
|
if (rev->available >= 0) {
|
||||||
|
rev->available -= n;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* negative rev->available means some additional bytes
|
||||||
|
* were received between kernel notification and recv(),
|
||||||
|
* and therefore ev->ready can be safely reset even for
|
||||||
|
* edge-triggered event methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (rev->available < 0) {
|
||||||
|
rev->available = 0;
|
||||||
|
rev->ready = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"recv: avail:%d", rev->available);
|
||||||
|
|
||||||
|
} else if ((size_t) n == size) {
|
||||||
|
|
||||||
|
if (ngx_socket_nread(c->fd, &rev->available) == -1) {
|
||||||
|
n = ngx_connection_error(c, ngx_socket_errno,
|
||||||
|
ngx_socket_nread_n " failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"recv: avail:%d", rev->available);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NGX_HAVE_EPOLLRDHUP)
|
#if (NGX_HAVE_EPOLLRDHUP)
|
||||||
|
|
||||||
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ int ngx_blocking(ngx_socket_t s);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_FIONREAD)
|
||||||
|
|
||||||
|
#define ngx_socket_nread(s, n) ioctl(s, FIONREAD, n)
|
||||||
|
#define ngx_socket_nread_n "ioctl(FIONREAD)"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int ngx_tcp_nopush(ngx_socket_t s);
|
int ngx_tcp_nopush(ngx_socket_t s);
|
||||||
int ngx_tcp_push(ngx_socket_t s);
|
int ngx_tcp_push(ngx_socket_t s);
|
||||||
|
|
||||||
|
|||||||
@@ -189,6 +189,13 @@ ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, ngx_log_t *log)
|
|||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* zero-sized datagram; pretend to have at least 1 iov */
|
||||||
|
if (n == 0) {
|
||||||
|
iov = &vec->iovs[n++];
|
||||||
|
iov->iov_base = NULL;
|
||||||
|
iov->iov_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
vec->count = n;
|
vec->count = n;
|
||||||
vec->size = total;
|
vec->size = total;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
|
|||||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
NULL, err, lang, (char *) errstr, size, NULL);
|
NULL, err, lang, (char *) errstr, size, NULL);
|
||||||
|
|
||||||
if (len == 0 && lang && GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND) {
|
if (len == 0 && lang) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to use English messages first and fallback to a language,
|
* Try to use English messages first and fallback to a language,
|
||||||
|
|||||||
@@ -658,6 +658,19 @@ ngx_fs_bsize(u_char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t
|
||||||
|
ngx_fs_available(u_char *name)
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER navail;
|
||||||
|
|
||||||
|
if (GetDiskFreeSpaceEx((const char *) name, &navail, NULL, NULL) == 0) {
|
||||||
|
return NGX_MAX_OFF_T_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (off_t) navail.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_win32_check_filename(u_char *name, u_short *u, size_t len)
|
ngx_win32_check_filename(u_char *name, u_short *u, size_t len)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
|
|||||||
#define ngx_directio_off_n "ngx_directio_off_n"
|
#define ngx_directio_off_n "ngx_directio_off_n"
|
||||||
|
|
||||||
size_t ngx_fs_bsize(u_char *name);
|
size_t ngx_fs_bsize(u_char *name);
|
||||||
|
off_t ngx_fs_available(u_char *name);
|
||||||
|
|
||||||
|
|
||||||
#define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE)
|
#define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
|
|||||||
@@ -27,6 +27,21 @@ ngx_blocking(ngx_socket_t s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ngx_socket_nread(ngx_socket_t s, int *n)
|
||||||
|
{
|
||||||
|
unsigned long nread;
|
||||||
|
|
||||||
|
if (ioctlsocket(s, FIONREAD, &nread) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*n = nread;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ngx_tcp_push(ngx_socket_t s)
|
ngx_tcp_push(ngx_socket_t s)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ int ngx_blocking(ngx_socket_t s);
|
|||||||
#define ngx_nonblocking_n "ioctlsocket(FIONBIO)"
|
#define ngx_nonblocking_n "ioctlsocket(FIONBIO)"
|
||||||
#define ngx_blocking_n "ioctlsocket(!FIONBIO)"
|
#define ngx_blocking_n "ioctlsocket(!FIONBIO)"
|
||||||
|
|
||||||
|
int ngx_socket_nread(ngx_socket_t s, int *n);
|
||||||
|
#define ngx_socket_nread_n "ioctlsocket(FIONREAD)"
|
||||||
|
|
||||||
#define ngx_shutdown_socket shutdown
|
#define ngx_shutdown_socket shutdown
|
||||||
#define ngx_shutdown_socket_n "shutdown()"
|
#define ngx_shutdown_socket_n "shutdown()"
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,10 @@ typedef int sig_atomic_t;
|
|||||||
#define NGX_HAVE_SO_SNDLOWAT 0
|
#define NGX_HAVE_SO_SNDLOWAT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NGX_HAVE_FIONREAD
|
||||||
|
#define NGX_HAVE_FIONREAD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NGX_HAVE_GETADDRINFO 1
|
#define NGX_HAVE_GETADDRINFO 1
|
||||||
|
|
||||||
#define ngx_random rand
|
#define ngx_random rand
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ ngx_os_init(ngx_log_t *log)
|
|||||||
goto nopoll;
|
goto nopoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
WSAPoll = (ngx_wsapoll_pt) GetProcAddress(hmod, "WSAPoll");
|
WSAPoll = (ngx_wsapoll_pt) (void *) GetProcAddress(hmod, "WSAPoll");
|
||||||
if (WSAPoll == NULL) {
|
if (WSAPoll == NULL) {
|
||||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno,
|
ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno,
|
||||||
"GetProcAddress(\"WSAPoll\") failed");
|
"GetProcAddress(\"WSAPoll\") failed");
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user