summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES54
-rw-r--r--CHANGES.ru55
-rw-r--r--contrib/vim/syntax/nginx.vim233
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_buf.c44
-rw-r--r--src/core/ngx_buf.h4
-rw-r--r--src/core/ngx_crypt.c2
-rw-r--r--src/core/ngx_rbtree.c6
-rw-r--r--src/core/ngx_rbtree.h6
-rw-r--r--src/core/ngx_resolver.c33
-rw-r--r--src/core/ngx_resolver.h15
-rw-r--r--src/core/ngx_syslog.c5
-rw-r--r--src/event/ngx_event.h2
-rw-r--r--src/event/ngx_event_openssl.c20
-rw-r--r--src/event/ngx_event_timer.c102
-rw-r--r--src/event/ngx_event_timer.h16
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c167
-rw-r--r--src/http/modules/ngx_http_log_module.c24
-rw-r--r--src/http/modules/ngx_http_proxy_module.c269
-rw-r--r--src/http/modules/ngx_http_scgi_module.c173
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c239
-rw-r--r--src/http/ngx_http_cache.h3
-rw-r--r--src/http/ngx_http_core_module.c4
-rw-r--r--src/http/ngx_http_file_cache.c77
-rw-r--r--src/http/ngx_http_request.c8
-rw-r--r--src/http/ngx_http_request.h4
-rw-r--r--src/http/ngx_http_spdy.c81
-rw-r--r--src/http/ngx_http_spdy_filter_module.c8
-rw-r--r--src/http/ngx_http_upstream.c59
-rw-r--r--src/http/ngx_http_upstream.h1
-rw-r--r--src/http/ngx_http_write_filter_module.c13
-rw-r--r--src/os/unix/ngx_darwin_sendfile_chain.c189
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c183
-rw-r--r--src/os/unix/ngx_linux_sendfile_chain.c152
-rw-r--r--src/os/unix/ngx_os.h14
-rw-r--r--src/os/unix/ngx_process_cycle.c3
-rw-r--r--src/os/unix/ngx_solaris_sendfilev_chain.c27
-rw-r--r--src/os/unix/ngx_writev_chain.c208
38 files changed, 1442 insertions, 1065 deletions
diff --git a/CHANGES b/CHANGES
index b94ba2fe3..8b2c1ccc2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,56 @@
+Changes with nginx 1.7.8 02 Dec 2014
+
+ *) Change: now the "If-Modified-Since", "If-Range", etc. client request
+ header lines are passed to a backend while caching if nginx knows in
+ advance that the response will not be cached (e.g., when using
+ proxy_cache_min_uses).
+
+ *) Change: now after proxy_cache_lock_timeout nginx sends a request to a
+ backend with caching disabled; the new directives
+ "proxy_cache_lock_age", "fastcgi_cache_lock_age",
+ "scgi_cache_lock_age", and "uwsgi_cache_lock_age" specify a time
+ after which the lock will be released and another attempt to cache a
+ response will be made.
+
+ *) Change: the "log_format" directive can now be used only at http
+ level.
+
+ *) Feature: the "proxy_ssl_certificate", "proxy_ssl_certificate_key",
+ "proxy_ssl_password_file", "uwsgi_ssl_certificate",
+ "uwsgi_ssl_certificate_key", and "uwsgi_ssl_password_file"
+ directives.
+ Thanks to Piotr Sikora.
+
+ *) Feature: it is now possible to switch to a named location using
+ "X-Accel-Redirect".
+ Thanks to Toshikuni Fukaya.
+
+ *) Feature: now the "tcp_nodelay" directive works with SPDY connections.
+
+ *) Feature: new directives in vim syntax highliting scripts.
+ Thanks to Peter Wu.
+
+ *) Bugfix: nginx ignored the "s-maxage" value in the "Cache-Control"
+ backend response header line.
+ Thanks to Piotr Sikora.
+
+ *) Bugfix: in the ngx_http_spdy_module.
+ Thanks to Piotr Sikora.
+
+ *) Bugfix: in the "ssl_password_file" directive when using OpenSSL
+ 0.9.8zc, 1.0.0o, 1.0.1j.
+
+ *) Bugfix: alerts "header already sent" appeared in logs if the
+ "post_action" directive was used; the bug had appeared in 1.5.4.
+
+ *) Bugfix: alerts "the http output chain is empty" might appear in logs
+ if the "postpone_output 0" directive was used with SSI includes.
+
+ *) Bugfix: in the "proxy_cache_lock" directive with SSI subrequests.
+ Thanks to Yichun Zhang.
+
+
Changes with nginx 1.7.7 28 Oct 2014
*) Change: now nginx takes into account the "Vary" header line in a
@@ -3412,7 +3464,7 @@ Changes with nginx 0.7.11 18 Aug 2008
*) Feature: the "proxy_ssl_session_reuse" directive.
*) Bugfix: a "proxy_pass" directive without URI part might use original
- request after the "X-Accel-Redirect" redirection was used;
+ request after the "X-Accel-Redirect" redirection was used.
*) Bugfix: if a directory has search only rights and the first index
file was absent, then nginx returned the 500 status code.
diff --git a/CHANGES.ru b/CHANGES.ru
index 988651ef7..d648c1cf6 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,59 @@
+Изменения в nginx 1.7.8 02.12.2014
+
+ *) Изменение: теперь строки "If-Modified-Since", "If-Range" и им
+ подобные в заголовке запроса клиента передаются бэкенду при
+ включённом кэшировании, если nginx заранее знает, что не будет
+ кэшировать ответ (например, при использовании proxy_cache_min_uses).
+
+ *) Изменение: теперь после истечения proxy_cache_lock_timeout nginx
+ отправляет запрос на бэкенд без кэширования; новые директивы
+ proxy_cache_lock_age, fastcgi_cache_lock_age, scgi_cache_lock_age и
+ uwsgi_cache_lock_age позволяют указать, через какое время блокировка
+ будет принудительно снята и будет сделана ещё одна попытка
+ закэшировать ответ.
+
+ *) Изменение: директива log_format теперь может использоваться только на
+ уровне http.
+
+ *) Добавление: директивы proxy_ssl_certificate,
+ proxy_ssl_certificate_key, proxy_ssl_password_file,
+ uwsgi_ssl_certificate, uwsgi_ssl_certificate_key и
+ uwsgi_ssl_password_file.
+ Спасибо Piotr Sikora.
+
+ *) Добавление: теперь с помощью X-Accel-Redirect можно перейти в
+ именованный location.
+ Спасибо Toshikuni Fukaya.
+
+ *) Добавление: теперь директива tcp_nodelay работает для
+ SPDY-соединений.
+
+ *) Добавление: новые директивы в скриптах подсветки синтаксиса для vim.
+ Спасибо Peter Wu.
+
+ *) Исправление: nginx игнорировал значение "s-maxage" в строке
+ "Cache-Control" в заголовке ответа бэкенда.
+ Спасибо Piotr Sikora.
+
+ *) Исправление: в модуле ngx_http_spdy_module.
+ Спасибо Piotr Sikora.
+
+ *) Исправление: в директиве ssl_password_file при использовании OpenSSL
+ 0.9.8zc, 1.0.0o, 1.0.1j.
+
+ *) Исправление: при использовании директивы post_action в лог писались
+ сообщения "header already sent"; ошибка появилась в nginx 1.5.4.
+
+ *) Исправление: при использовании директивы "postpone_output 0" с
+ SSI-подзапросами в лог могли писаться сообщения "the http output
+ chain is empty".
+
+ *) Исправление: в директиве proxy_cache_lock при использовании
+ SSI-подзапросов.
+ Спасибо Yichun Zhang.
+
+
Изменения в nginx 1.7.7 28.10.2014
*) Изменение: теперь nginx учитывает при кэшировании строку "Vary" в
diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim
index 50d809bc4..444d96e4d 100644
--- a/contrib/vim/syntax/nginx.vim
+++ b/contrib/vim/syntax/nginx.vim
@@ -31,6 +31,7 @@ syn keyword ngxDirectiveBlock limit_except contained
syn keyword ngxDirectiveBlock if contained
syn keyword ngxDirectiveBlock geo contained
syn keyword ngxDirectiveBlock map contained
+syn keyword ngxDirectiveBlock split_clients contained
syn keyword ngxDirectiveImportant include
syn keyword ngxDirectiveImportant root
@@ -41,6 +42,8 @@ syn keyword ngxDirectiveImportant internal
syn keyword ngxDirectiveImportant proxy_pass
syn keyword ngxDirectiveImportant memcached_pass
syn keyword ngxDirectiveImportant fastcgi_pass
+syn keyword ngxDirectiveImportant scgi_pass
+syn keyword ngxDirectiveImportant uwsgi_pass
syn keyword ngxDirectiveImportant try_files
syn keyword ngxDirectiveControl break
@@ -53,12 +56,15 @@ syn keyword ngxDirectiveError post_action
syn keyword ngxDirectiveDeprecated connections
syn keyword ngxDirectiveDeprecated imap
+syn keyword ngxDirectiveDeprecated limit_zone
syn keyword ngxDirectiveDeprecated open_file_cache_retest
syn keyword ngxDirectiveDeprecated optimize_server_names
syn keyword ngxDirectiveDeprecated satisfy_any
+syn keyword ngxDirectiveDeprecated so_keepalive
syn keyword ngxDirective accept_mutex
syn keyword ngxDirective accept_mutex_delay
+syn keyword ngxDirective acceptex_read
syn keyword ngxDirective access_log
syn keyword ngxDirective add_after_body
syn keyword ngxDirective add_before_body
@@ -74,11 +80,14 @@ syn keyword ngxDirective auth_basic_user_file
syn keyword ngxDirective auth_http
syn keyword ngxDirective auth_http_header
syn keyword ngxDirective auth_http_timeout
+syn keyword ngxDirective auth_request
+syn keyword ngxDirective auth_request_set
syn keyword ngxDirective autoindex
syn keyword ngxDirective autoindex_exact_size
syn keyword ngxDirective autoindex_localtime
syn keyword ngxDirective charset
syn keyword ngxDirective charset_types
+syn keyword ngxDirective chunked_transfer_encoding
syn keyword ngxDirective client_body_buffer_size
syn keyword ngxDirective client_body_in_file_only
syn keyword ngxDirective client_body_in_single_buffer
@@ -102,32 +111,44 @@ syn keyword ngxDirective devpoll_changes
syn keyword ngxDirective devpoll_events
syn keyword ngxDirective directio
syn keyword ngxDirective directio_alignment
+syn keyword ngxDirective disable_symlinks
syn keyword ngxDirective empty_gif
syn keyword ngxDirective env
syn keyword ngxDirective epoll_events
syn keyword ngxDirective error_log
+syn keyword ngxDirective etag
syn keyword ngxDirective eventport_events
syn keyword ngxDirective expires
syn keyword ngxDirective fastcgi_bind
syn keyword ngxDirective fastcgi_buffer_size
+syn keyword ngxDirective fastcgi_buffering
syn keyword ngxDirective fastcgi_buffers
syn keyword ngxDirective fastcgi_busy_buffers_size
syn keyword ngxDirective fastcgi_cache
+syn keyword ngxDirective fastcgi_cache_bypass
syn keyword ngxDirective fastcgi_cache_key
+syn keyword ngxDirective fastcgi_cache_lock
+syn keyword ngxDirective fastcgi_cache_lock_timeout
syn keyword ngxDirective fastcgi_cache_methods
syn keyword ngxDirective fastcgi_cache_min_uses
syn keyword ngxDirective fastcgi_cache_path
+syn keyword ngxDirective fastcgi_cache_revalidate
syn keyword ngxDirective fastcgi_cache_use_stale
syn keyword ngxDirective fastcgi_cache_valid
syn keyword ngxDirective fastcgi_catch_stderr
syn keyword ngxDirective fastcgi_connect_timeout
+syn keyword ngxDirective fastcgi_force_ranges
syn keyword ngxDirective fastcgi_hide_header
syn keyword ngxDirective fastcgi_ignore_client_abort
syn keyword ngxDirective fastcgi_ignore_headers
syn keyword ngxDirective fastcgi_index
syn keyword ngxDirective fastcgi_intercept_errors
+syn keyword ngxDirective fastcgi_keep_conn
syn keyword ngxDirective fastcgi_max_temp_file_size
syn keyword ngxDirective fastcgi_next_upstream
+syn keyword ngxDirective fastcgi_next_upstream_timeout
+syn keyword ngxDirective fastcgi_next_upstream_tries
+syn keyword ngxDirective fastcgi_no_cache
syn keyword ngxDirective fastcgi_param
syn keyword ngxDirective fastcgi_pass_header
syn keyword ngxDirective fastcgi_pass_request_body
@@ -140,12 +161,15 @@ syn keyword ngxDirective fastcgi_store
syn keyword ngxDirective fastcgi_store_access
syn keyword ngxDirective fastcgi_temp_file_write_size
syn keyword ngxDirective fastcgi_temp_path
-syn keyword ngxDirective fastcgi_upstream_fail_timeout
-syn keyword ngxDirective fastcgi_upstream_max_fails
syn keyword ngxDirective flv
syn keyword ngxDirective geoip_city
syn keyword ngxDirective geoip_country
+syn keyword ngxDirective geoip_org
+syn keyword ngxDirective geoip_proxy
+syn keyword ngxDirective geoip_proxy_recursive
syn keyword ngxDirective google_perftools_profiles
+syn keyword ngxDirective gunzip
+syn keyword ngxDirective gunzip_buffers
syn keyword ngxDirective gzip
syn keyword ngxDirective gzip_buffers
syn keyword ngxDirective gzip_comp_level
@@ -159,30 +183,40 @@ syn keyword ngxDirective gzip_static
syn keyword ngxDirective gzip_types
syn keyword ngxDirective gzip_vary
syn keyword ngxDirective gzip_window
+syn keyword ngxDirective hash
syn keyword ngxDirective if_modified_since
syn keyword ngxDirective ignore_invalid_headers
syn keyword ngxDirective image_filter
syn keyword ngxDirective image_filter_buffer
+syn keyword ngxDirective image_filter_interlace
syn keyword ngxDirective image_filter_jpeg_quality
+syn keyword ngxDirective image_filter_sharpen
syn keyword ngxDirective image_filter_transparency
syn keyword ngxDirective imap_auth
syn keyword ngxDirective imap_capabilities
syn keyword ngxDirective imap_client_buffer
syn keyword ngxDirective index
+syn keyword ngxDirective iocp_threads
syn keyword ngxDirective ip_hash
+syn keyword ngxDirective keepalive
+syn keyword ngxDirective keepalive_disable
syn keyword ngxDirective keepalive_requests
syn keyword ngxDirective keepalive_timeout
syn keyword ngxDirective kqueue_changes
syn keyword ngxDirective kqueue_events
syn keyword ngxDirective large_client_header_buffers
+syn keyword ngxDirective least_conn
syn keyword ngxDirective limit_conn
syn keyword ngxDirective limit_conn_log_level
+syn keyword ngxDirective limit_conn_status
+syn keyword ngxDirective limit_conn_zone
syn keyword ngxDirective limit_rate
syn keyword ngxDirective limit_rate_after
syn keyword ngxDirective limit_req
syn keyword ngxDirective limit_req_log_level
+syn keyword ngxDirective limit_req_status
syn keyword ngxDirective limit_req_zone
-syn keyword ngxDirective limit_zone
+syn keyword ngxDirective lingering_close
syn keyword ngxDirective lingering_time
syn keyword ngxDirective lingering_timeout
syn keyword ngxDirective lock_file
@@ -192,21 +226,27 @@ syn keyword ngxDirective log_subrequest
syn keyword ngxDirective map_hash_bucket_size
syn keyword ngxDirective map_hash_max_size
syn keyword ngxDirective master_process
+syn keyword ngxDirective max_ranges
syn keyword ngxDirective memcached_bind
syn keyword ngxDirective memcached_buffer_size
syn keyword ngxDirective memcached_connect_timeout
+syn keyword ngxDirective memcached_gzip_flag
syn keyword ngxDirective memcached_next_upstream
+syn keyword ngxDirective memcached_next_upstream_timeout
+syn keyword ngxDirective memcached_next_upstream_tries
syn keyword ngxDirective memcached_read_timeout
syn keyword ngxDirective memcached_send_timeout
-syn keyword ngxDirective memcached_upstream_fail_timeout
-syn keyword ngxDirective memcached_upstream_max_fails
syn keyword ngxDirective merge_slashes
syn keyword ngxDirective min_delete_depth
syn keyword ngxDirective modern_browser
syn keyword ngxDirective modern_browser_value
+syn keyword ngxDirective mp4
+syn keyword ngxDirective mp4_buffer_size
+syn keyword ngxDirective mp4_max_buffer_size
syn keyword ngxDirective msie_padding
syn keyword ngxDirective msie_refresh
syn keyword ngxDirective multi_accept
+syn keyword ngxDirective mysql_test
syn keyword ngxDirective open_file_cache
syn keyword ngxDirective open_file_cache_errors
syn keyword ngxDirective open_file_cache_events
@@ -215,6 +255,7 @@ syn keyword ngxDirective open_file_cache_valid
syn keyword ngxDirective open_log_file_cache
syn keyword ngxDirective output_buffers
syn keyword ngxDirective override_charset
+syn keyword ngxDirective pcre_jit
syn keyword ngxDirective perl
syn keyword ngxDirective perl_modules
syn keyword ngxDirective perl_require
@@ -223,6 +264,7 @@ syn keyword ngxDirective pid
syn keyword ngxDirective pop3_auth
syn keyword ngxDirective pop3_capabilities
syn keyword ngxDirective port_in_redirect
+syn keyword ngxDirective post_acceptex
syn keyword ngxDirective postpone_gzipping
syn keyword ngxDirective postpone_output
syn keyword ngxDirective protocol
@@ -234,22 +276,33 @@ syn keyword ngxDirective proxy_buffering
syn keyword ngxDirective proxy_buffers
syn keyword ngxDirective proxy_busy_buffers_size
syn keyword ngxDirective proxy_cache
+syn keyword ngxDirective proxy_cache_bypass
syn keyword ngxDirective proxy_cache_key
+syn keyword ngxDirective proxy_cache_lock
+syn keyword ngxDirective proxy_cache_lock_timeout
syn keyword ngxDirective proxy_cache_methods
syn keyword ngxDirective proxy_cache_min_uses
syn keyword ngxDirective proxy_cache_path
+syn keyword ngxDirective proxy_cache_revalidate
syn keyword ngxDirective proxy_cache_use_stale
syn keyword ngxDirective proxy_cache_valid
syn keyword ngxDirective proxy_connect_timeout
+syn keyword ngxDirective proxy_cookie_domain
+syn keyword ngxDirective proxy_cookie_path
+syn keyword ngxDirective proxy_force_ranges
syn keyword ngxDirective proxy_headers_hash_bucket_size
syn keyword ngxDirective proxy_headers_hash_max_size
syn keyword ngxDirective proxy_hide_header
+syn keyword ngxDirective proxy_http_version
syn keyword ngxDirective proxy_ignore_client_abort
syn keyword ngxDirective proxy_ignore_headers
syn keyword ngxDirective proxy_intercept_errors
syn keyword ngxDirective proxy_max_temp_file_size
syn keyword ngxDirective proxy_method
syn keyword ngxDirective proxy_next_upstream
+syn keyword ngxDirective proxy_next_upstream_timeout
+syn keyword ngxDirective proxy_next_upstream_tries
+syn keyword ngxDirective proxy_no_cache
syn keyword ngxDirective proxy_pass_error_message
syn keyword ngxDirective proxy_pass_header
syn keyword ngxDirective proxy_pass_request_body
@@ -260,18 +313,27 @@ syn keyword ngxDirective proxy_send_lowat
syn keyword ngxDirective proxy_send_timeout
syn keyword ngxDirective proxy_set_body
syn keyword ngxDirective proxy_set_header
+syn keyword ngxDirective proxy_ssl_ciphers
+syn keyword ngxDirective proxy_ssl_crl
+syn keyword ngxDirective proxy_ssl_name
+syn keyword ngxDirective proxy_ssl_protocols
+syn keyword ngxDirective proxy_ssl_server_name
syn keyword ngxDirective proxy_ssl_session_reuse
+syn keyword ngxDirective proxy_ssl_trusted_certificate
+syn keyword ngxDirective proxy_ssl_verify
+syn keyword ngxDirective proxy_ssl_verify_depth
syn keyword ngxDirective proxy_store
syn keyword ngxDirective proxy_store_access
syn keyword ngxDirective proxy_temp_file_write_size
syn keyword ngxDirective proxy_temp_path
syn keyword ngxDirective proxy_timeout
-syn keyword ngxDirective proxy_upstream_fail_timeout
-syn keyword ngxDirective proxy_upstream_max_fails
syn keyword ngxDirective random_index
syn keyword ngxDirective read_ahead
syn keyword ngxDirective real_ip_header
+syn keyword ngxDirective real_ip_recursive
syn keyword ngxDirective recursive_error_pages
+syn keyword ngxDirective referer_hash_bucket_size
+syn keyword ngxDirective referer_hash_max_size
syn keyword ngxDirective request_pool_size
syn keyword ngxDirective reset_timedout_connection
syn keyword ngxDirective resolver
@@ -282,6 +344,45 @@ syn keyword ngxDirective rtsig_overflow_test
syn keyword ngxDirective rtsig_overflow_threshold
syn keyword ngxDirective rtsig_signo
syn keyword ngxDirective satisfy
+syn keyword ngxDirective scgi_bind
+syn keyword ngxDirective scgi_buffer_size
+syn keyword ngxDirective scgi_buffering
+syn keyword ngxDirective scgi_buffers
+syn keyword ngxDirective scgi_busy_buffers_size
+syn keyword ngxDirective scgi_cache
+syn keyword ngxDirective scgi_cache_bypass
+syn keyword ngxDirective scgi_cache_key
+syn keyword ngxDirective scgi_cache_lock
+syn keyword ngxDirective scgi_cache_lock_timeout
+syn keyword ngxDirective scgi_cache_methods
+syn keyword ngxDirective scgi_cache_min_uses
+syn keyword ngxDirective scgi_cache_path
+syn keyword ngxDirective scgi_cache_revalidate
+syn keyword ngxDirective scgi_cache_use_stale
+syn keyword ngxDirective scgi_cache_valid
+syn keyword ngxDirective scgi_connect_timeout
+syn keyword ngxDirective scgi_force_ranges
+syn keyword ngxDirective scgi_hide_header
+syn keyword ngxDirective scgi_ignore_client_abort
+syn keyword ngxDirective scgi_ignore_headers
+syn keyword ngxDirective scgi_intercept_errors
+syn keyword ngxDirective scgi_max_temp_file_size
+syn keyword ngxDirective scgi_next_upstream
+syn keyword ngxDirective scgi_next_upstream_timeout
+syn keyword ngxDirective scgi_next_upstream_tries
+syn keyword ngxDirective scgi_no_cache
+syn keyword ngxDirective scgi_param
+syn keyword ngxDirective scgi_pass_header
+syn keyword ngxDirective scgi_pass_request_body
+syn keyword ngxDirective scgi_pass_request_headers
+syn keyword ngxDirective scgi_read_timeout
+syn keyword ngxDirective scgi_send_timeout
+syn keyword ngxDirective scgi_store
+syn keyword ngxDirective scgi_store_access
+syn keyword ngxDirective scgi_temp_file_write_size
+syn keyword ngxDirective scgi_temp_path
+syn keyword ngxDirective secure_link
+syn keyword ngxDirective secure_link_md5
syn keyword ngxDirective secure_link_secret
syn keyword ngxDirective send_lowat
syn keyword ngxDirective send_timeout
@@ -296,31 +397,50 @@ syn keyword ngxDirective smtp_auth
syn keyword ngxDirective smtp_capabilities
syn keyword ngxDirective smtp_client_buffer
syn keyword ngxDirective smtp_greeting_delay
-syn keyword ngxDirective so_keepalive
syn keyword ngxDirective source_charset
+syn keyword ngxDirective spdy_chunk_size
+syn keyword ngxDirective spdy_headers_comp
+syn keyword ngxDirective spdy_keepalive_timeout
+syn keyword ngxDirective spdy_max_concurrent_streams
+syn keyword ngxDirective spdy_pool_size
+syn keyword ngxDirective spdy_recv_buffer_size
+syn keyword ngxDirective spdy_recv_timeout
+syn keyword ngxDirective spdy_streams_index_size
syn keyword ngxDirective ssi
syn keyword ngxDirective ssi_ignore_recycled_buffers
+syn keyword ngxDirective ssi_last_modified
syn keyword ngxDirective ssi_min_file_chunk
syn keyword ngxDirective ssi_silent_errors
syn keyword ngxDirective ssi_types
syn keyword ngxDirective ssi_value_length
syn keyword ngxDirective ssl
+syn keyword ngxDirective ssl_buffer_size
syn keyword ngxDirective ssl_certificate
syn keyword ngxDirective ssl_certificate_key
syn keyword ngxDirective ssl_ciphers
syn keyword ngxDirective ssl_client_certificate
syn keyword ngxDirective ssl_crl
syn keyword ngxDirective ssl_dhparam
+syn keyword ngxDirective ssl_ecdh_curve
syn keyword ngxDirective ssl_engine
+syn keyword ngxDirective ssl_password_file
syn keyword ngxDirective ssl_prefer_server_ciphers
syn keyword ngxDirective ssl_protocols
syn keyword ngxDirective ssl_session_cache
+syn keyword ngxDirective ssl_session_ticket_key
+syn keyword ngxDirective ssl_session_tickets
syn keyword ngxDirective ssl_session_timeout
+syn keyword ngxDirective ssl_stapling
+syn keyword ngxDirective ssl_stapling_file
+syn keyword ngxDirective ssl_stapling_responder
+syn keyword ngxDirective ssl_stapling_verify
+syn keyword ngxDirective ssl_trusted_certificate
syn keyword ngxDirective ssl_verify_client
syn keyword ngxDirective ssl_verify_depth
syn keyword ngxDirective starttls
syn keyword ngxDirective stub_status
syn keyword ngxDirective sub_filter
+syn keyword ngxDirective sub_filter_last_modified
syn keyword ngxDirective sub_filter_once
syn keyword ngxDirective sub_filter_types
syn keyword ngxDirective tcp_nodelay
@@ -342,9 +462,59 @@ syn keyword ngxDirective userid_name
syn keyword ngxDirective userid_p3p
syn keyword ngxDirective userid_path
syn keyword ngxDirective userid_service
+syn keyword ngxDirective uwsgi_bind
+syn keyword ngxDirective uwsgi_buffer_size
+syn keyword ngxDirective uwsgi_buffering
+syn keyword ngxDirective uwsgi_buffers
+syn keyword ngxDirective uwsgi_busy_buffers_size
+syn keyword ngxDirective uwsgi_cache
+syn keyword ngxDirective uwsgi_cache_bypass
+syn keyword ngxDirective uwsgi_cache_key
+syn keyword ngxDirective uwsgi_cache_lock
+syn keyword ngxDirective uwsgi_cache_lock_timeout
+syn keyword ngxDirective uwsgi_cache_methods
+syn keyword ngxDirective uwsgi_cache_min_uses
+syn keyword ngxDirective uwsgi_cache_path
+syn keyword ngxDirective uwsgi_cache_revalidate
+syn keyword ngxDirective uwsgi_cache_use_stale
+syn keyword ngxDirective uwsgi_cache_valid
+syn keyword ngxDirective uwsgi_connect_timeout
+syn keyword ngxDirective uwsgi_force_ranges
+syn keyword ngxDirective uwsgi_hide_header
+syn keyword ngxDirective uwsgi_ignore_client_abort
+syn keyword ngxDirective uwsgi_ignore_headers
+syn keyword ngxDirective uwsgi_intercept_errors
+syn keyword ngxDirective uwsgi_max_temp_file_size
+syn keyword ngxDirective uwsgi_modifier1
+syn keyword ngxDirective uwsgi_modifier2
+syn keyword ngxDirective uwsgi_next_upstream
+syn keyword ngxDirective uwsgi_next_upstream_timeout
+syn keyword ngxDirective uwsgi_next_upstream_tries
+syn keyword ngxDirective uwsgi_no_cache
+syn keyword ngxDirective uwsgi_param
+syn keyword ngxDirective uwsgi_pass_header
+syn keyword ngxDirective uwsgi_pass_request_body
+syn keyword ngxDirective uwsgi_pass_request_headers
+syn keyword ngxDirective uwsgi_read_timeout
+syn keyword ngxDirective uwsgi_send_timeout
+syn keyword ngxDirective uwsgi_ssl_ciphers
+syn keyword ngxDirective uwsgi_ssl_crl
+syn keyword ngxDirective uwsgi_ssl_name
+syn keyword ngxDirective uwsgi_ssl_protocols
+syn keyword ngxDirective uwsgi_ssl_server_name
+syn keyword ngxDirective uwsgi_ssl_session_reuse
+syn keyword ngxDirective uwsgi_ssl_trusted_certificate
+syn keyword ngxDirective uwsgi_ssl_verify
+syn keyword ngxDirective uwsgi_ssl_verify_depth
+syn keyword ngxDirective uwsgi_store
+syn keyword ngxDirective uwsgi_store_access
+syn keyword ngxDirective uwsgi_string
+syn keyword ngxDirective uwsgi_temp_file_write_size
+syn keyword ngxDirective uwsgi_temp_path
syn keyword ngxDirective valid_referers
syn keyword ngxDirective variables_hash_bucket_size
syn keyword ngxDirective variables_hash_max_size
+syn keyword ngxDirective worker_aio_requests
syn keyword ngxDirective worker_connections
syn keyword ngxDirective worker_cpu_affinity
syn keyword ngxDirective worker_priority
@@ -356,6 +526,9 @@ syn keyword ngxDirective worker_threads
syn keyword ngxDirective working_directory
syn keyword ngxDirective xclient
syn keyword ngxDirective xml_entities
+syn keyword ngxDirective xslt_last_modified
+syn keyword ngxDirective xslt_param
+syn keyword ngxDirective xslt_string_param
syn keyword ngxDirective xslt_stylesheet
syn keyword ngxDirective xslt_types
@@ -367,7 +540,7 @@ syn keyword ngxDirective xslt_types
syn keyword ngxDirectiveThirdParty set_from_accept_language
" Access Key Module <http://wiki.nginx.org/NginxHttpAccessKeyModule>
-" Denies access unless the request URL contains an access key.
+" Denies access unless the request URL contains an access key.
syn keyword ngxDirectiveThirdParty accesskey
syn keyword ngxDirectiveThirdParty accesskey_arg
syn keyword ngxDirectiveThirdParty accesskey_hashmethod
@@ -521,7 +694,7 @@ syn keyword ngxDirectiveThirdParty mogilefs_send_timeout
syn keyword ngxDirectiveThirdParty mogilefs_tracker
" MP4 Streaming Lite Module <http://wiki.nginx.org/NginxMP4StreamingLite>
-" Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL.
+" Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL.
syn keyword ngxDirectiveThirdParty mp4
" Nginx Notice Module <http://xph.us/software/nginx-notice/>
@@ -642,46 +815,6 @@ syn keyword ngxDirectiveThirdParty xss_get
syn keyword ngxDirectiveThirdParty xss_input_types
syn keyword ngxDirectiveThirdParty xss_output_type
-" uWSGI Module <http://wiki.nginx.org/HttpUwsgiModule>
-" Allows Nginx to interact with uWSGI processes and control what parameters are passed to the process.
-syn keyword ngxDirectiveThirdParty uwsgi_bind
-syn keyword ngxDirectiveThirdParty uwsgi_buffer_size
-syn keyword ngxDirectiveThirdParty uwsgi_buffering
-syn keyword ngxDirectiveThirdParty uwsgi_buffers
-syn keyword ngxDirectiveThirdParty uwsgi_busy_buffers_size
-syn keyword ngxDirectiveThirdParty uwsgi_cache
-syn keyword ngxDirectiveThirdParty uwsgi_cache_bypass
-syn keyword ngxDirectiveThirdParty uwsgi_cache_key
-syn keyword ngxDirectiveThirdParty uwsgi_cache_lock
-syn keyword ngxDirectiveThirdParty uwsgi_cache_lock_timeout
-syn keyword ngxDirectiveThirdParty uwsgi_cache_methods
-syn keyword ngxDirectiveThirdParty uwsgi_cache_min_uses
-syn keyword ngxDirectiveThirdParty uwsgi_cache_path
-syn keyword ngxDirectiveThirdParty uwsgi_cache_use_stale
-syn keyword ngxDirectiveThirdParty uwsgi_cache_valid
-syn keyword ngxDirectiveThirdParty uwsgi_connect_timeout
-syn keyword ngxDirectiveThirdParty uwsgi_hide_header
-syn keyword ngxDirectiveThirdParty uwsgi_ignore_client_abort
-syn keyword ngxDirectiveThirdParty uwsgi_ignore_headers
-syn keyword ngxDirectiveThirdParty uwsgi_intercept_errors
-syn keyword ngxDirectiveThirdParty uwsgi_max_temp_file_size
-syn keyword ngxDirectiveThirdParty uwsgi_modifier1
-syn keyword ngxDirectiveThirdParty uwsgi_modifier2
-syn keyword ngxDirectiveThirdParty uwsgi_next_upstream
-syn keyword ngxDirectiveThirdParty uwsgi_no_cache
-syn keyword ngxDirectiveThirdParty uwsgi_param
-syn keyword ngxDirectiveThirdParty uwsgi_pass
-syn keyword ngxDirectiveThirdParty uwsgi_pass_header
-syn keyword ngxDirectiveThirdParty uwsgi_pass_request_body
-syn keyword ngxDirectiveThirdParty uwsgi_pass_request_headers
-syn keyword ngxDirectiveThirdParty uwsgi_read_timeout
-syn keyword ngxDirectiveThirdParty uwsgi_send_timeout
-syn keyword ngxDirectiveThirdParty uwsgi_store
-syn keyword ngxDirectiveThirdParty uwsgi_store_access
-syn keyword ngxDirectiveThirdParty uwsgi_string
-syn keyword ngxDirectiveThirdParty uwsgi_temp_file_write_size
-syn keyword ngxDirectiveThirdParty uwsgi_temp_path
-
" highlight
hi link ngxComment Comment
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 2d923fb85..c9007a138 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1007007
-#define NGINX_VERSION "1.7.7"
+#define nginx_version 1007008
+#define NGINX_VERSION "1.7.8"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c
index 94a3d3f10..00b664458 100644
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -220,8 +220,50 @@ ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,
}
+off_t
+ngx_chain_coalesce_file(ngx_chain_t **in, off_t limit)
+{
+ off_t total, size, aligned, fprev;
+ ngx_fd_t fd;
+ ngx_chain_t *cl;
+
+ total = 0;
+
+ cl = *in;
+ fd = cl->buf->file->fd;
+
+ do {
+ size = cl->buf->file_last - cl->buf->file_pos;
+
+ if (size > limit - total) {
+ size = limit - total;
+
+ aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
+ & ~((off_t) ngx_pagesize - 1);
+
+ if (aligned <= cl->buf->file_last) {
+ size = aligned - cl->buf->file_pos;
+ }
+ }
+
+ total += size;
+ fprev = cl->buf->file_pos + size;
+ cl = cl->next;
+
+ } while (cl
+ && cl->buf->in_file
+ && total < limit
+ && fd == cl->buf->file->fd
+ && fprev == cl->buf->file_pos);
+
+ *in = cl;
+
+ return total;
+}
+
+
ngx_chain_t *
-ngx_handle_sent_chain(ngx_chain_t *in, off_t sent)
+ngx_chain_update_sent(ngx_chain_t *in, off_t sent)
{
off_t size;
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index cc28a3e15..13536a69a 100644
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -158,6 +158,8 @@ ngx_chain_t *ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free);
void ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free,
ngx_chain_t **busy, ngx_chain_t **out, ngx_buf_tag_t tag);
-ngx_chain_t *ngx_handle_sent_chain(ngx_chain_t *in, off_t sent);
+off_t ngx_chain_coalesce_file(ngx_chain_t **in, off_t limit);
+
+ngx_chain_t *ngx_chain_update_sent(ngx_chain_t *in, off_t sent);
#endif /* _NGX_BUF_H_INCLUDED_ */
diff --git a/src/core/ngx_crypt.c b/src/core/ngx_crypt.c
index e2376c6f1..d7d068c6a 100644
--- a/src/core/ngx_crypt.c
+++ b/src/core/ngx_crypt.c
@@ -66,7 +66,7 @@ ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
size_t saltlen, keylen;
ngx_md5_t md5, ctx1;
- /* Apache's apr1 crypt is Paul-Henning Kamp's md5 crypt with $apr1$ magic */
+ /* Apache's apr1 crypt is Poul-Henning Kamp's md5 crypt with $apr1$ magic */
keylen = ngx_strlen(key);
diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c
index 914ca7e88..6c66f4061 100644
--- a/src/core/ngx_rbtree.c
+++ b/src/core/ngx_rbtree.c
@@ -22,8 +22,7 @@ static ngx_inline void ngx_rbtree_right_rotate(ngx_rbtree_node_t **root,
void
-ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
- ngx_rbtree_node_t *node)
+ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)
{
ngx_rbtree_node_t **root, *temp, *sentinel;
@@ -155,8 +154,7 @@ ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
void
-ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
- ngx_rbtree_node_t *node)
+ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node)
{
ngx_uint_t red;
ngx_rbtree_node_t **root, *sentinel, *subst, *temp, *w;
diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h
index 6e47a5bbb..1d33e3f6e 100644
--- a/src/core/ngx_rbtree.h
+++ b/src/core/ngx_rbtree.h
@@ -48,10 +48,8 @@ struct ngx_rbtree_s {
(tree)->insert = i
-void ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
- ngx_rbtree_node_t *node);
-void ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
- ngx_rbtree_node_t *node);
+void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
+void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node,
ngx_rbtree_node_t *sentinel);
void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root,
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index a17793b13..4e9c85da2 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -48,6 +48,11 @@ typedef struct {
} ngx_resolver_an_t;
+#define ngx_resolver_node(n) \
+ (ngx_resolver_node_t *) \
+ ((u_char *) (n) - offsetof(ngx_resolver_node_t, node))
+
+
ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc);
@@ -288,7 +293,7 @@ ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)
while (tree->root != tree->sentinel) {
- rn = (ngx_resolver_node_t *) ngx_rbtree_min(tree->root, tree->sentinel);
+ rn = ngx_resolver_node(ngx_rbtree_min(tree->root, tree->sentinel));
ngx_queue_remove(&rn->queue);
@@ -666,7 +671,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
ctx->event->handler = ngx_resolver_timeout_handler;
ctx->event->data = rn;
ctx->event->log = r->log;
- ctx->ident = -1;
+ rn->ident = -1;
ngx_add_timer(ctx->event, ctx->timeout);
}
@@ -859,7 +864,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
ctx->event->handler = ngx_resolver_timeout_handler;
ctx->event->data = rn;
ctx->event->log = r->log;
- ctx->ident = -1;
+ rn->ident = -1;
ngx_add_timer(ctx->event, ctx->timeout);
@@ -1568,8 +1573,6 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_rbtree_delete(&r->name_rbtree, &rn->node);
- ngx_resolver_free_node(r, rn);
-
/* unlock name mutex */
while (next) {
@@ -1580,6 +1583,8 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ctx->handler(ctx);
}
+ ngx_resolver_free_node(r, rn);
+
return;
}
@@ -2143,8 +2148,6 @@ valid:
ngx_rbtree_delete(tree, &rn->node);
- ngx_resolver_free_node(r, rn);
-
/* unlock addr mutex */
while (next) {
@@ -2155,6 +2158,8 @@ valid:
ctx->handler(ctx);
}
+ ngx_resolver_free_node(r, rn);
+
return;
}
@@ -2290,7 +2295,7 @@ ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
/* hash == node->key */
- rn = (ngx_resolver_node_t *) node;
+ rn = ngx_resolver_node(node);
rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
@@ -2329,7 +2334,7 @@ ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
/* addr == node->key */
- return (ngx_resolver_node_t *) node;
+ return ngx_resolver_node(node);
}
/* not found */
@@ -2365,7 +2370,7 @@ ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
/* hash == node->key */
- rn = (ngx_resolver_node_t *) node;
+ rn = ngx_resolver_node(node);
rc = ngx_memcmp(addr, &rn->addr6, 16);
@@ -2403,8 +2408,8 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
} else { /* node->key == temp->key */
- rn = (ngx_resolver_node_t *) node;
- rn_temp = (ngx_resolver_node_t *) temp;
+ rn = ngx_resolver_node(node);
+ rn_temp = ngx_resolver_node(temp);
p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen)
< 0) ? &temp->left : &temp->right;
@@ -2446,8 +2451,8 @@ ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
} else { /* node->key == temp->key */
- rn = (ngx_resolver_node_t *) node;
- rn_temp = (ngx_resolver_node_t *) temp;
+ rn = ngx_resolver_node(node);
+ rn_temp = ngx_resolver_node(temp);
p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
< 0) ? &temp->left : &temp->right;
diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
index 264c8c42b..d3519fb6f 100644
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -51,12 +51,16 @@ typedef void (*ngx_resolver_handler_pt)(ngx_resolver_ctx_t *ctx);
typedef struct {
- ngx_rbtree_node_t node;
- ngx_queue_t queue;
-
/* PTR: resolved name, A: name to resolve */
u_char *name;
+ ngx_queue_t queue;
+
+ /* event ident must be after 3 pointers as in ngx_connection_t */
+ ngx_int_t ident;
+
+ ngx_rbtree_node_t node;
+
#if (NGX_HAVE_INET6)
/* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */
struct in6_addr addr6;
@@ -103,7 +107,7 @@ typedef struct {
void *dummy;
ngx_log_t *log;
- /* ident must be after 3 pointers */
+ /* event ident must be after 3 pointers as in ngx_connection_t */
ngx_int_t ident;
/* simple round robin DNS peers balancer */
@@ -143,9 +147,6 @@ struct ngx_resolver_ctx_s {
ngx_resolver_t *resolver;
ngx_udp_connection_t *udp_connection;
- /* ident must be after 3 pointers */
- ngx_int_t ident;
-
ngx_int_t state;
ngx_str_t name;
diff --git a/src/core/ngx_syslog.c b/src/core/ngx_syslog.c
index 616fd712e..d4e79f67d 100644
--- a/src/core/ngx_syslog.c
+++ b/src/core/ngx_syslog.c
@@ -182,10 +182,11 @@ ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
for (i = 4; i < len; i++) {
c = ngx_tolower(p[i]);
- if (c < '0' || (c > '9' && c < 'a') || c > 'z') {
+ if (c < '0' || (c > '9' && c < 'a' && c != '_') || c > 'z') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"syslog \"tag\" only allows "
- "alphanumeric characters");
+ "alphanumeric characters "
+ "and underscore");
return NGX_CONF_ERROR;
}
}
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 6531ec7ad..a1643a134 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -136,6 +136,8 @@ struct ngx_event_s {
unsigned channel:1;
unsigned resolver:1;
+ unsigned cancelable:1;
+
#if 0
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index f34565277..ab54d88c4 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -404,20 +404,9 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
}
if (--tries) {
- n = ERR_peek_error();
-
-#ifdef OPENSSL_IS_BORINGSSL
- if (ERR_GET_LIB(n) == ERR_LIB_CIPHER
- && ERR_GET_REASON(n) == CIPHER_R_BAD_DECRYPT)
-#else
- if (ERR_GET_LIB(n) == ERR_LIB_EVP
- && ERR_GET_REASON(n) == EVP_R_BAD_DECRYPT)
-#endif
- {
- ERR_clear_error();
- SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd);
- continue;
- }
+ ERR_clear_error();
+ SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd);
+ continue;
}
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
@@ -1869,6 +1858,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
#ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
|| n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING /* 345 */
#endif
+#ifdef SSL_R_INAPPROPRIATE_FALLBACK
+ || n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */
+#endif
|| n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
|| n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */
|| n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index 107558649..8f547b215 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -10,13 +10,8 @@
#include <ngx_event.h>
-#if (NGX_THREADS)
-ngx_mutex_t *ngx_event_timer_mutex;
-#endif
-
-
-ngx_thread_volatile ngx_rbtree_t ngx_event_timer_rbtree;
-static ngx_rbtree_node_t ngx_event_timer_sentinel;
+ngx_rbtree_t ngx_event_timer_rbtree;
+static ngx_rbtree_node_t ngx_event_timer_sentinel;
/*
* the event timer rbtree may contain the duplicate keys, however,
@@ -30,20 +25,6 @@ ngx_event_timer_init(ngx_log_t *log)
ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
ngx_rbtree_insert_timer_value);
-#if (NGX_THREADS)
-
- if (ngx_event_timer_mutex) {
- ngx_event_timer_mutex->log = log;
- return NGX_OK;
- }
-
- ngx_event_timer_mutex = ngx_mutex_init(log, 0);
- if (ngx_event_timer_mutex == NULL) {
- return NGX_ERROR;
- }
-
-#endif
-
return NGX_OK;
}
@@ -58,15 +39,11 @@ ngx_event_find_timer(void)
return NGX_TIMER_INFINITE;
}
- ngx_mutex_lock(ngx_event_timer_mutex);
-
root = ngx_event_timer_rbtree.root;
sentinel = ngx_event_timer_rbtree.sentinel;
node = ngx_rbtree_min(root, sentinel);
- ngx_mutex_unlock(ngx_event_timer_mutex);
-
timer = (ngx_msec_int_t) (node->key - ngx_current_msec);
return (ngx_msec_t) (timer > 0 ? timer : 0);
@@ -82,9 +59,6 @@ ngx_event_expire_timers(void)
sentinel = ngx_event_timer_rbtree.sentinel;
for ( ;; ) {
-
- ngx_mutex_lock(ngx_event_timer_mutex);
-
root = ngx_event_timer_rbtree.root;
if (root == sentinel) {
@@ -93,36 +67,72 @@ ngx_event_expire_timers(void)
node = ngx_rbtree_min(root, sentinel);
- /* node->key <= ngx_current_time */
+ /* node->key > ngx_current_time */
- if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) {
- ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
+ if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) {
+ return;
+ }
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
- "event timer del: %d: %M",
- ngx_event_ident(ev->data), ev->timer.key);
+ ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
- ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+ "event timer del: %d: %M",
+ ngx_event_ident(ev->data), ev->timer.key);
- ngx_mutex_unlock(ngx_event_timer_mutex);
+ ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
#if (NGX_DEBUG)
- ev->timer.left = NULL;
- ev->timer.right = NULL;
- ev->timer.parent = NULL;
+ ev->timer.left = NULL;
+ ev->timer.right = NULL;
+ ev->timer.parent = NULL;
#endif
- ev->timer_set = 0;
+ ev->timer_set = 0;
+
+ ev->timedout = 1;
+
+ ev->handler(ev);
+ }
+}
+
+
+void
+ngx_event_cancel_timers(void)
+{
+ ngx_event_t *ev;
+ ngx_rbtree_node_t *node, *root, *sentinel;
- ev->timedout = 1;
+ sentinel = ngx_event_timer_rbtree.sentinel;
- ev->handler(ev);
+ for ( ;; ) {
+ root = ngx_event_timer_rbtree.root;
- continue;
+ if (root == sentinel) {
+ return;
}
- break;
- }
+ node = ngx_rbtree_min(root, sentinel);
- ngx_mutex_unlock(ngx_event_timer_mutex);
+ ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
+
+ if (!ev->cancelable) {
+ return;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+ "event timer cancel: %d: %M",
+ ngx_event_ident(ev->data), ev->timer.key);
+
+ ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
+
+#if (NGX_DEBUG)
+ ev->timer.left = NULL;
+ ev->timer.right = NULL;
+ ev->timer.parent = NULL;
+#endif
+
+ ev->timer_set = 0;
+
+ ev->handler(ev);
+ }
}
diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h
index ec9b316bd..99f8a48fb 100644
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -22,14 +22,10 @@
ngx_int_t ngx_event_timer_init(ngx_log_t *log);
ngx_msec_t ngx_event_find_timer(void);
void ngx_event_expire_timers(void);
+void ngx_event_cancel_timers(void);
-#if (NGX_THREADS)
-extern ngx_mutex_t *ngx_event_timer_mutex;
-#endif
-
-
-extern ngx_thread_volatile ngx_rbtree_t ngx_event_timer_rbtree;
+extern ngx_rbtree_t ngx_event_timer_rbtree;
static ngx_inline void
@@ -39,12 +35,8 @@ ngx_event_del_timer(ngx_event_t *ev)
"event timer del: %d: %M",
ngx_event_ident(ev->data), ev->timer.key);
- ngx_mutex_lock(ngx_event_timer_mutex);
-
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
- ngx_mutex_unlock(ngx_event_timer_mutex);
-
#if (NGX_DEBUG)
ev->timer.left = NULL;
ev->timer.right = NULL;
@@ -89,12 +81,8 @@ ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
"event timer add: %d: %M:%M",
ngx_event_ident(ev->data), timer, ev->timer.key);
- ngx_mutex_lock(ngx_event_timer_mutex);
-
ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev->timer);
- ngx_mutex_unlock(ngx_event_timer_mutex);
-
ev->timer_set = 1;
}
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index b7f7ea14a..cc93570b1 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -11,22 +11,30 @@
typedef struct {
+ ngx_array_t *flushes;
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+ ngx_uint_t number;
+ ngx_hash_t hash;
+} ngx_http_fastcgi_params_t;
+
+
+typedef struct {
ngx_http_upstream_conf_t upstream;
ngx_str_t index;
- ngx_array_t *flushes;
- ngx_array_t *params_len;
- ngx_array_t *params;
+ ngx_http_fastcgi_params_t params;
+#if (NGX_HTTP_CACHE)
+ ngx_http_fastcgi_params_t params_cache;
+#endif
+
ngx_array_t *params_source;
ngx_array_t *catch_stderr;
ngx_array_t *fastcgi_lengths;
ngx_array_t *fastcgi_values;
- ngx_hash_t headers_hash;
- ngx_uint_t header_params;
-
ngx_flag_t keep_conn;
#if (NGX_HTTP_CACHE)
@@ -150,8 +158,9 @@ static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf);
static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
-static ngx_int_t ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
- ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_loc_conf_t *prev);
+static ngx_int_t ngx_http_fastcgi_init_params(ngx_conf_t *cf,
+ ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_params_t *params,
+ ngx_keyval_t *default_params);
static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -419,6 +428,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
NULL },
+ { ngx_string("fastcgi_cache_lock_age"),
+ 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_fastcgi_loc_conf_t, upstream.cache_lock_age),
+ NULL },
+
{ ngx_string("fastcgi_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -773,6 +789,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
ngx_http_script_code_pt code;
ngx_http_script_engine_t e, le;
ngx_http_fastcgi_header_t *h;
+ ngx_http_fastcgi_params_t *params;
ngx_http_fastcgi_loc_conf_t *flcf;
ngx_http_script_len_code_pt lcode;
@@ -782,13 +799,19 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
- if (flcf->params_len) {
+#if (NGX_HTTP_CACHE)
+ params = r->upstream->cacheable ? &flcf->params_cache : &flcf->params;
+#else
+ params = &flcf->params;
+#endif
+
+ if (params->lengths) {
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
- ngx_http_script_flush_no_cacheable_variables(r, flcf->flushes);
+ ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
le.flushed = 1;
- le.ip = flcf->params_len->elts;
+ le.ip = params->lengths->elts;
le.request = r;
while (*(uintptr_t *) le.ip) {
@@ -817,7 +840,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
allocated = 0;
lowcase_key = NULL;
- if (flcf->header_params) {
+ if (params->number) {
n = 0;
part = &r->headers_in.headers.part;
@@ -847,7 +870,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
i = 0;
}
- if (flcf->header_params) {
+ if (params->number) {
if (allocated < header[i].key.len) {
allocated = header[i].key.len + 16;
lowcase_key = ngx_pnalloc(r->pool, allocated);
@@ -872,7 +895,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
lowcase_key[n] = ch;
}
- if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {
+ if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
ignored[header_params++] = &header[i];
continue;
}
@@ -942,15 +965,15 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
+ sizeof(ngx_http_fastcgi_header_t);
- if (flcf->params_len) {
+ if (params->lengths) {
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- e.ip = flcf->params->elts;
+ e.ip = params->values->elts;
e.pos = b->last;
e.request = r;
e.flushed = 1;
- le.ip = flcf->params_len->elts;
+ le.ip = params->lengths->elts;
while (*(uintptr_t *) le.ip) {
@@ -2374,6 +2397,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
+ conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif
@@ -2404,6 +2428,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_fastcgi_loc_conf_t *conf = child;
size_t size;
+ ngx_int_t rc;
ngx_hash_init_t hash;
ngx_http_core_loc_conf_t *clcf;
@@ -2638,6 +2663,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000);
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
+ prev->upstream.cache_lock_age, 5000);
+
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
@@ -2692,69 +2720,67 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
#endif
- if (ngx_http_fastcgi_merge_params(cf, conf, prev) != NGX_OK) {
+ if (conf->params_source == NULL) {
+ conf->params = prev->params;
+#if (NGX_HTTP_CACHE)
+ conf->params_cache = prev->params_cache;
+#endif
+ conf->params_source = prev->params_source;
+ }
+
+ rc = ngx_http_fastcgi_init_params(cf, conf, &conf->params, NULL);
+ if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
+#if (NGX_HTTP_CACHE)
+
+ if (conf->upstream.cache) {
+ rc = ngx_http_fastcgi_init_params(cf, conf, &conf->params_cache,
+ ngx_http_fastcgi_cache_headers);
+ if (rc != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+#endif
+
return NGX_CONF_OK;
}
static ngx_int_t
-ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
- ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_loc_conf_t *prev)
+ngx_http_fastcgi_init_params(ngx_conf_t *cf, ngx_http_fastcgi_loc_conf_t *conf,
+ ngx_http_fastcgi_params_t *params, ngx_keyval_t *default_params)
{
u_char *p;
size_t size;
uintptr_t *code;
ngx_uint_t i, nsrc;
- ngx_array_t headers_names;
-#if (NGX_HTTP_CACHE)
- ngx_array_t params_merged;
-#endif
+ ngx_array_t headers_names, params_merged;
+ ngx_keyval_t *h;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
- ngx_http_upstream_param_t *src;
+ ngx_http_upstream_param_t *src, *s;
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
- if (conf->params_source == NULL) {
- conf->params_source = prev->params_source;
-
- if (prev->headers_hash.buckets
-#if (NGX_HTTP_CACHE)
- && ((conf->upstream.cache == NULL)
- == (prev->upstream.cache == NULL))
-#endif
- )
- {
- conf->flushes = prev->flushes;
- conf->params_len = prev->params_len;
- conf->params = prev->params;
- conf->headers_hash = prev->headers_hash;
- conf->header_params = prev->header_params;
-
- return NGX_OK;
- }
+ if (params->hash.buckets) {
+ return NGX_OK;
}
- if (conf->params_source == NULL
-#if (NGX_HTTP_CACHE)
- && (conf->upstream.cache == NULL)
-#endif
- )
- {
- conf->headers_hash.buckets = (void *) 1;
+ if (conf->params_source == NULL && default_params == NULL) {
+ params->hash.buckets = (void *) 1;
return NGX_OK;
}
- conf->params_len = ngx_array_create(cf->pool, 64, 1);
- if (conf->params_len == NULL) {
+ params->lengths = ngx_array_create(cf->pool, 64, 1);
+ if (params->lengths == NULL) {
return NGX_ERROR;
}
- conf->params = ngx_array_create(cf->pool, 512, 1);
- if (conf->params == NULL) {
+ params->values = ngx_array_create(cf->pool, 512, 1);
+ if (params->values == NULL) {
return NGX_ERROR;
}
@@ -2773,12 +2799,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
nsrc = 0;
}
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- ngx_keyval_t *h;
- ngx_http_upstream_param_t *s;
-
+ if (default_params) {
if (ngx_array_init(&params_merged, cf->temp_pool, 4,
sizeof(ngx_http_upstream_param_t))
!= NGX_OK)
@@ -2796,7 +2817,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
*s = src[i];
}
- h = ngx_http_fastcgi_cache_headers;
+ h = default_params;
while (h->key.len) {
@@ -2827,8 +2848,6 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
nsrc = params_merged.nelts;
}
-#endif
-
for (i = 0; i < nsrc; i++) {
if (src[i].key.len > sizeof("HTTP_") - 1
@@ -2849,7 +2868,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
}
}
- copy = ngx_array_push_n(conf->params_len,
+ copy = ngx_array_push_n(params->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -2858,7 +2877,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
- copy = ngx_array_push_n(conf->params_len,
+ copy = ngx_array_push_n(params->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -2872,7 +2891,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
+ src[i].key.len + sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
- copy = ngx_array_push_n(conf->params, size);
+ copy = ngx_array_push_n(params->values, size);
if (copy == NULL) {
return NGX_ERROR;
}
@@ -2888,15 +2907,15 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
sc.cf = cf;
sc.source = &src[i].value;
- sc.flushes = &conf->flushes;
- sc.lengths = &conf->params_len;
- sc.values = &conf->params;
+ sc.flushes = &params->flushes;
+ sc.lengths = &params->lengths;
+ sc.values = &params->values;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_ERROR;
}
- code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -2904,7 +2923,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
*code = (uintptr_t) NULL;
- code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->values, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -2912,16 +2931,16 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
*code = (uintptr_t) NULL;
}
- code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
*code = (uintptr_t) NULL;
- conf->header_params = headers_names.nelts;
+ params->number = headers_names.nelts;
- hash.hash = &conf->headers_hash;
+ hash.hash = &params->hash;
hash.key = ngx_hash_key_lc;
hash.max_size = 512;
hash.bucket_size = 64;
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index cec77e749..df9424f83 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -152,7 +152,7 @@ static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
static ngx_command_t ngx_http_log_commands[] = {
{ ngx_string("log_format"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
+ NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
ngx_http_log_set_format,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
@@ -744,10 +744,23 @@ ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
static void
ngx_http_log_flush_handler(ngx_event_t *ev)
{
+ ngx_open_file_t *file;
+ ngx_http_log_buf_t *buffer;
+
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"http log buffer flush handler");
- ngx_http_log_flush(ev->data, ev->log);
+ if (ev->timedout) {
+ ngx_http_log_flush(ev->data, ev->log);
+ return;
+ }
+
+ /* cancel the flush timer for graceful shutdown */
+
+ file = ev->data;
+ buffer = file->data;
+
+ buffer->event = NULL;
}
@@ -1411,6 +1424,7 @@ process_formats:
buffer->event->data = log->file;
buffer->event->handler = ngx_http_log_flush_handler;
buffer->event->log = &cf->cycle->new_log;
+ buffer->event->cancelable = 1;
buffer->flush = flush;
}
@@ -1434,12 +1448,6 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_uint_t i;
ngx_http_log_fmt_t *fmt;
- if (cf->cmd_type != NGX_HTTP_MAIN_CONF) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "the \"log_format\" directive may be used "
- "only on \"http\" level");
- }
-
value = cf->args->elts;
fmt = lmcf->formats.elts;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index ea4109c77..41bf1c91f 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -40,15 +40,25 @@ typedef struct {
typedef struct {
+ ngx_array_t *flushes;
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+ ngx_hash_t hash;
+} ngx_http_proxy_headers_t;
+
+
+typedef struct {
ngx_http_upstream_conf_t upstream;
- ngx_array_t *flushes;
- ngx_array_t *body_set_len;
- ngx_array_t *body_set;
- ngx_array_t *headers_set_len;
- ngx_array_t *headers_set;
- ngx_hash_t headers_set_hash;
+ ngx_array_t *body_flushes;
+ ngx_array_t *body_lengths;
+ ngx_array_t *body_values;
+ ngx_str_t body_source;
+ ngx_http_proxy_headers_t headers;
+#if (NGX_HTTP_CACHE)
+ ngx_http_proxy_headers_t headers_cache;
+#endif
ngx_array_t *headers_source;
ngx_array_t *proxy_lengths;
@@ -58,8 +68,6 @@ typedef struct {
ngx_array_t *cookie_domains;
ngx_array_t *cookie_paths;
- ngx_str_t body_source;
-
ngx_str_t method;
ngx_str_t location;
ngx_str_t url;
@@ -84,6 +92,9 @@ typedef struct {
ngx_uint_t ssl_verify_depth;
ngx_str_t ssl_trusted_certificate;
ngx_str_t ssl_crl;
+ ngx_str_t ssl_certificate;
+ ngx_str_t ssl_certificate_key;
+ ngx_array_t *ssl_passwords;
#endif
} ngx_http_proxy_loc_conf_t;
@@ -143,8 +154,9 @@ static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
-static ngx_int_t ngx_http_proxy_merge_headers(ngx_conf_t *cf,
- ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev);
+static ngx_int_t ngx_http_proxy_init_headers(ngx_conf_t *cf,
+ ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_headers_t *headers,
+ ngx_keyval_t *default_headers);
static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -162,6 +174,10 @@ static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
+#if (NGX_HTTP_SSL)
+static char *ngx_http_proxy_ssl_password_file(ngx_conf_t *cf,
+ ngx_command_t *cmd, void *conf);
+#endif
static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
@@ -482,6 +498,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
NULL },
+ { ngx_string("proxy_cache_lock_age"),
+ 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_proxy_loc_conf_t, upstream.cache_lock_age),
+ NULL },
+
{ ngx_string("proxy_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -626,6 +649,27 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, ssl_crl),
NULL },
+ { ngx_string("proxy_ssl_certificate"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate),
+ NULL },
+
+ { ngx_string("proxy_ssl_certificate_key"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key),
+ NULL },
+
+ { ngx_string("proxy_ssl_password_file"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_proxy_ssl_password_file,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
#endif
ngx_null_command
@@ -1045,6 +1089,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
ngx_http_upstream_t *u;
ngx_http_proxy_ctx_t *ctx;
ngx_http_script_code_pt code;
+ ngx_http_proxy_headers_t *headers;
ngx_http_script_engine_t e, le;
ngx_http_proxy_loc_conf_t *plcf;
ngx_http_script_len_code_pt lcode;
@@ -1053,6 +1098,12 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+#if (NGX_HTTP_CACHE)
+ headers = u->cacheable ? &plcf->headers_cache : &plcf->headers;
+#else
+ headers = &plcf->headers;
+#endif
+
if (u->method.len) {
/* HEAD was changed to GET to cache response */
method = u->method;
@@ -1111,10 +1162,11 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
- ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
+ ngx_http_script_flush_no_cacheable_variables(r, plcf->body_flushes);
+ ngx_http_script_flush_no_cacheable_variables(r, headers->flushes);
- if (plcf->body_set_len) {
- le.ip = plcf->body_set_len->elts;
+ if (plcf->body_lengths) {
+ le.ip = plcf->body_lengths->elts;
le.request = r;
le.flushed = 1;
body_len = 0;
@@ -1131,7 +1183,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
ctx->internal_body_length = r->headers_in.content_length_n;
}
- le.ip = plcf->headers_set_len->elts;
+ le.ip = headers->lengths->elts;
le.request = r;
le.flushed = 1;
@@ -1160,7 +1212,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
i = 0;
}
- if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
+ if (ngx_hash_find(&headers->hash, header[i].hash,
header[i].lowcase_key, header[i].key.len))
{
continue;
@@ -1231,12 +1283,12 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- e.ip = plcf->headers_set->elts;
+ e.ip = headers->values->elts;
e.pos = b->last;
e.request = r;
e.flushed = 1;
- le.ip = plcf->headers_set_len->elts;
+ le.ip = headers->lengths->elts;
while (*(uintptr_t *) le.ip) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
@@ -1284,7 +1336,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
i = 0;
}
- if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
+ if (ngx_hash_find(&headers->hash, header[i].hash,
header[i].lowcase_key, header[i].key.len))
{
continue;
@@ -1309,8 +1361,8 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
/* add "\r\n" at the header end */
*b->last++ = CR; *b->last++ = LF;
- if (plcf->body_set) {
- e.ip = plcf->body_set->elts;
+ if (plcf->body_values) {
+ e.ip = plcf->body_values->elts;
e.pos = b->last;
while (*(uintptr_t *) e.ip) {
@@ -1325,7 +1377,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
"http proxy header:%N\"%*s\"",
(size_t) (b->last - b->pos), b->pos);
- if (plcf->body_set == NULL && plcf->upstream.pass_request_body) {
+ if (plcf->body_values == NULL && plcf->upstream.pass_request_body) {
body = u->request_bufs;
u->request_bufs = cl;
@@ -2467,11 +2519,14 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
*
* conf->method = { 0, NULL };
* conf->headers_source = NULL;
- * conf->headers_set_len = NULL;
- * conf->headers_set = NULL;
- * conf->headers_set_hash = NULL;
- * conf->body_set_len = NULL;
- * conf->body_set = NULL;
+ * conf->headers.lengths = NULL;
+ * conf->headers.values = NULL;
+ * conf->headers.hash = { NULL, 0 };
+ * conf->headers_cache.lengths = NULL;
+ * conf->headers_cache.values = NULL;
+ * conf->headers_cache.hash = { NULL, 0 };
+ * conf->body_lengths = NULL;
+ * conf->body_values = NULL;
* conf->body_source = { 0, NULL };
* conf->redirects = NULL;
* conf->ssl = 0;
@@ -2479,6 +2534,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
* conf->ssl_ciphers = { 0, NULL };
* conf->ssl_trusted_certificate = { 0, NULL };
* conf->ssl_crl = { 0, NULL };
+ * conf->ssl_certificate = { 0, NULL };
+ * conf->ssl_certificate_key = { 0, NULL };
*/
conf->upstream.store = NGX_CONF_UNSET;
@@ -2514,6 +2571,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
+ conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif
@@ -2527,6 +2585,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.ssl_server_name = NGX_CONF_UNSET;
conf->upstream.ssl_verify = NGX_CONF_UNSET;
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
+ conf->ssl_passwords = NGX_CONF_UNSET_PTR;
#endif
/* "proxy_cyclic_temp_file" is disabled */
@@ -2557,6 +2616,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
u_char *p;
size_t size;
+ ngx_int_t rc;
ngx_hash_init_t hash;
ngx_http_core_loc_conf_t *clcf;
ngx_http_proxy_rewrite_t *pr;
@@ -2787,6 +2847,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000);
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
+ prev->upstream.cache_lock_age, 5000);
+
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
@@ -2836,6 +2899,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
prev->ssl_trusted_certificate, "");
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
+ ngx_conf_merge_str_value(conf->ssl_certificate,
+ prev->ssl_certificate, "");
+ ngx_conf_merge_str_value(conf->ssl_certificate_key,
+ prev->ssl_certificate_key, "");
+ ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
+
if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -2945,20 +3014,21 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
if (conf->body_source.data == NULL) {
+ conf->body_flushes = prev->body_flushes;
conf->body_source = prev->body_source;
- conf->body_set_len = prev->body_set_len;
- conf->body_set = prev->body_set;
+ conf->body_lengths = prev->body_lengths;
+ conf->body_values = prev->body_values;
}
- if (conf->body_source.data && conf->body_set_len == NULL) {
+ if (conf->body_source.data && conf->body_lengths == NULL) {
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
sc.cf = cf;
sc.source = &conf->body_source;
- sc.flushes = &conf->flushes;
- sc.lengths = &conf->body_set_len;
- sc.values = &conf->body_set;
+ sc.flushes = &conf->body_flushes;
+ sc.lengths = &conf->body_lengths;
+ sc.values = &conf->body_values;
sc.complete_lengths = 1;
sc.complete_values = 1;
@@ -2967,17 +3037,39 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
}
- if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) {
+ if (conf->headers_source == NULL) {
+ conf->headers = prev->headers;
+#if (NGX_HTTP_CACHE)
+ conf->headers_cache = prev->headers_cache;
+#endif
+ conf->headers_source = prev->headers_source;
+ }
+
+ rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers,
+ ngx_http_proxy_headers);
+ if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
+#if (NGX_HTTP_CACHE)
+
+ if (conf->upstream.cache) {
+ rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers_cache,
+ ngx_http_proxy_cache_headers);
+ if (rc != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+#endif
+
return NGX_CONF_OK;
}
static ngx_int_t
-ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
- ngx_http_proxy_loc_conf_t *prev)
+ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
+ ngx_http_proxy_headers_t *headers, ngx_keyval_t *default_headers)
{
u_char *p;
size_t size;
@@ -2990,24 +3082,10 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
- if (conf->headers_source == NULL) {
- conf->flushes = prev->flushes;
- conf->headers_set_len = prev->headers_set_len;
- conf->headers_set = prev->headers_set;
- conf->headers_set_hash = prev->headers_set_hash;
- conf->headers_source = prev->headers_source;
- }
-
- if (conf->headers_set_hash.buckets
-#if (NGX_HTTP_CACHE)
- && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
-#endif
- )
- {
+ if (headers->hash.buckets) {
return NGX_OK;
}
-
if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
!= NGX_OK)
{
@@ -3028,27 +3106,16 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
}
}
- conf->headers_set_len = ngx_array_create(cf->pool, 64, 1);
- if (conf->headers_set_len == NULL) {
+ headers->lengths = ngx_array_create(cf->pool, 64, 1);
+ if (headers->lengths == NULL) {
return NGX_ERROR;
}
- conf->headers_set = ngx_array_create(cf->pool, 512, 1);
- if (conf->headers_set == NULL) {
+ headers->values = ngx_array_create(cf->pool, 512, 1);
+ if (headers->values == NULL) {
return NGX_ERROR;
}
-
-#if (NGX_HTTP_CACHE)
-
- h = conf->upstream.cache ? ngx_http_proxy_cache_headers:
- ngx_http_proxy_headers;
-#else
-
- h = ngx_http_proxy_headers;
-
-#endif
-
src = conf->headers_source->elts;
for (i = 0; i < conf->headers_source->nelts; i++) {
@@ -3060,6 +3127,8 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
*s = src[i];
}
+ h = default_headers;
+
while (h->key.len) {
src = headers_merged.elts;
@@ -3099,7 +3168,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
}
if (ngx_http_script_variables_count(&src[i].value) == 0) {
- copy = ngx_array_push_n(conf->headers_set_len,
+ copy = ngx_array_push_n(headers->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -3117,7 +3186,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
+ sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
- copy = ngx_array_push_n(conf->headers_set, size);
+ copy = ngx_array_push_n(headers->values, size);
if (copy == NULL) {
return NGX_ERROR;
}
@@ -3134,7 +3203,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
*p++ = CR; *p = LF;
} else {
- copy = ngx_array_push_n(conf->headers_set_len,
+ copy = ngx_array_push_n(headers->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -3149,7 +3218,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
+ src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
- copy = ngx_array_push_n(conf->headers_set, size);
+ copy = ngx_array_push_n(headers->values, size);
if (copy == NULL) {
return NGX_ERROR;
}
@@ -3166,16 +3235,16 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
sc.cf = cf;
sc.source = &src[i].value;
- sc.flushes = &conf->flushes;
- sc.lengths = &conf->headers_set_len;
- sc.values = &conf->headers_set;
+ sc.flushes = &headers->flushes;
+ sc.lengths = &headers->lengths;
+ sc.values = &headers->values;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_ERROR;
}
- copy = ngx_array_push_n(conf->headers_set_len,
+ copy = ngx_array_push_n(headers->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -3190,7 +3259,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
+ sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
- copy = ngx_array_push_n(conf->headers_set, size);
+ copy = ngx_array_push_n(headers->values, size);
if (copy == NULL) {
return NGX_ERROR;
}
@@ -3202,14 +3271,14 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
*p++ = CR; *p = LF;
}
- code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
*code = (uintptr_t) NULL;
- code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t));
+ code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -3217,7 +3286,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
*code = (uintptr_t) NULL;
}
- code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -3225,7 +3294,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
*code = (uintptr_t) NULL;
- hash.hash = &conf->headers_set_hash;
+ hash.hash = &headers->hash;
hash.key = ngx_hash_key_lc;
hash.max_size = conf->headers_hash_max_size;
hash.bucket_size = conf->headers_hash_bucket_size;
@@ -3837,6 +3906,33 @@ ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
+#if (NGX_HTTP_SSL)
+
+static char *
+ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_proxy_loc_conf_t *plcf = conf;
+
+ ngx_str_t *value;
+
+ if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
+
+ if (plcf->ssl_passwords == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+#endif
+
+
static char *
ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
{
@@ -3894,6 +3990,23 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = plcf->upstream.ssl;
+ if (plcf->ssl_certificate.len) {
+
+ if (plcf->ssl_certificate_key.len == 0) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"proxy_ssl_certificate_key\" is defined "
+ "for certificate \"%V\"", &plcf->ssl_certificate);
+ return NGX_ERROR;
+ }
+
+ if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate,
+ &plcf->ssl_certificate_key, plcf->ssl_passwords)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
if (SSL_CTX_set_cipher_list(plcf->upstream.ssl->ctx,
(const char *) plcf->ssl_ciphers.data)
== 0)
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 71dcd34f9..53a90d99a 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -12,16 +12,23 @@
typedef struct {
+ ngx_array_t *flushes;
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+ ngx_uint_t number;
+ ngx_hash_t hash;
+} ngx_http_scgi_params_t;
+
+
+typedef struct {
ngx_http_upstream_conf_t upstream;
- ngx_array_t *flushes;
- ngx_array_t *params_len;
- ngx_array_t *params;
+ ngx_http_scgi_params_t params;
+#if (NGX_HTTP_CACHE)
+ ngx_http_scgi_params_t params_cache;
+#endif
ngx_array_t *params_source;
- ngx_hash_t headers_hash;
- ngx_uint_t header_params;
-
ngx_array_t *scgi_lengths;
ngx_array_t *scgi_values;
@@ -43,8 +50,9 @@ static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);
-static ngx_int_t ngx_http_scgi_merge_params(ngx_conf_t *cf,
- ngx_http_scgi_loc_conf_t *conf, ngx_http_scgi_loc_conf_t *prev);
+static ngx_int_t ngx_http_scgi_init_params(ngx_conf_t *cf,
+ ngx_http_scgi_loc_conf_t *conf, ngx_http_scgi_params_t *params,
+ ngx_keyval_t *default_params);
static char *ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -276,6 +284,13 @@ static ngx_command_t ngx_http_scgi_commands[] = {
offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
NULL },
+ { ngx_string("scgi_cache_lock_age"),
+ 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_scgi_loc_conf_t, upstream.cache_lock_age),
+ NULL },
+
{ ngx_string("scgi_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -572,6 +587,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
ngx_chain_t *cl, *body;
ngx_list_part_t *part;
ngx_table_elt_t *header, **ignored;
+ ngx_http_scgi_params_t *params;
ngx_http_script_code_pt code;
ngx_http_script_engine_t e, le;
ngx_http_scgi_loc_conf_t *scf;
@@ -596,13 +612,19 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module);
- if (scf->params_len) {
+#if (NGX_HTTP_CACHE)
+ params = r->upstream->cacheable ? &scf->params_cache : &scf->params;
+#else
+ params = &scf->params;
+#endif
+
+ if (params->lengths) {
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
- ngx_http_script_flush_no_cacheable_variables(r, scf->flushes);
+ ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
le.flushed = 1;
- le.ip = scf->params_len->elts;
+ le.ip = params->lengths->elts;
le.request = r;
while (*(uintptr_t *) le.ip) {
@@ -631,7 +653,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
allocated = 0;
lowcase_key = NULL;
- if (scf->header_params) {
+ if (params->number) {
n = 0;
part = &r->headers_in.headers.part;
@@ -661,7 +683,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
i = 0;
}
- if (scf->header_params) {
+ if (params->number) {
if (allocated < header[i].key.len) {
allocated = header[i].key.len + 16;
lowcase_key = ngx_pnalloc(r->pool, allocated);
@@ -686,7 +708,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
lowcase_key[n] = ch;
}
- if (ngx_hash_find(&scf->headers_hash, hash, lowcase_key, n)) {
+ if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
ignored[header_params++] = &header[i];
continue;
}
@@ -714,15 +736,15 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
b->last = ngx_sprintf(b->last, "%ui:CONTENT_LENGTH%Z%V%Z",
len, &content_length);
- if (scf->params_len) {
+ if (params->lengths) {
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- e.ip = scf->params->elts;
+ e.ip = params->values->elts;
e.pos = b->last;
e.request = r;
e.flushed = 1;
- le.ip = scf->params_len->elts;
+ le.ip = params->lengths->elts;
while (*(uintptr_t *) le.ip) {
@@ -1133,6 +1155,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
+ conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif
@@ -1159,6 +1182,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_scgi_loc_conf_t *conf = child;
size_t size;
+ ngx_int_t rc;
ngx_hash_init_t hash;
ngx_http_core_loc_conf_t *clcf;
@@ -1392,6 +1416,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000);
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
+ prev->upstream.cache_lock_age, 5000);
+
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
@@ -1432,69 +1459,67 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
}
- if (ngx_http_scgi_merge_params(cf, conf, prev) != NGX_OK) {
+ if (conf->params_source == NULL) {
+ conf->params = prev->params;
+#if (NGX_HTTP_CACHE)
+ conf->params_cache = prev->params_cache;
+#endif
+ conf->params_source = prev->params_source;
+ }
+
+ rc = ngx_http_scgi_init_params(cf, conf, &conf->params, NULL);
+ if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
+#if (NGX_HTTP_CACHE)
+
+ if (conf->upstream.cache) {
+ rc = ngx_http_scgi_init_params(cf, conf, &conf->params_cache,
+ ngx_http_scgi_cache_headers);
+ if (rc != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+#endif
+
return NGX_CONF_OK;
}
static ngx_int_t
-ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
- ngx_http_scgi_loc_conf_t *prev)
+ngx_http_scgi_init_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
+ ngx_http_scgi_params_t *params, ngx_keyval_t *default_params)
{
u_char *p;
size_t size;
uintptr_t *code;
ngx_uint_t i, nsrc;
- ngx_array_t headers_names;
-#if (NGX_HTTP_CACHE)
- ngx_array_t params_merged;
-#endif
+ ngx_array_t headers_names, params_merged;
+ ngx_keyval_t *h;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
- ngx_http_upstream_param_t *src;
+ ngx_http_upstream_param_t *src, *s;
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
- if (conf->params_source == NULL) {
- conf->params_source = prev->params_source;
-
- if (prev->headers_hash.buckets
-#if (NGX_HTTP_CACHE)
- && ((conf->upstream.cache == NULL)
- == (prev->upstream.cache == NULL))
-#endif
- )
- {
- conf->flushes = prev->flushes;
- conf->params_len = prev->params_len;
- conf->params = prev->params;
- conf->headers_hash = prev->headers_hash;
- conf->header_params = prev->header_params;
-
- return NGX_OK;
- }
+ if (params->hash.buckets) {
+ return NGX_OK;
}
- if (conf->params_source == NULL
-#if (NGX_HTTP_CACHE)
- && (conf->upstream.cache == NULL)
-#endif
- )
- {
- conf->headers_hash.buckets = (void *) 1;
+ if (conf->params_source == NULL && default_params == NULL) {
+ params->hash.buckets = (void *) 1;
return NGX_OK;
}
- conf->params_len = ngx_array_create(cf->pool, 64, 1);
- if (conf->params_len == NULL) {
+ params->lengths = ngx_array_create(cf->pool, 64, 1);
+ if (params->lengths == NULL) {
return NGX_ERROR;
}
- conf->params = ngx_array_create(cf->pool, 512, 1);
- if (conf->params == NULL) {
+ params->values = ngx_array_create(cf->pool, 512, 1);
+ if (params->values == NULL) {
return NGX_ERROR;
}
@@ -1513,12 +1538,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
nsrc = 0;
}
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- ngx_keyval_t *h;
- ngx_http_upstream_param_t *s;
-
+ if (default_params) {
if (ngx_array_init(&params_merged, cf->temp_pool, 4,
sizeof(ngx_http_upstream_param_t))
!= NGX_OK)
@@ -1536,7 +1556,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
*s = src[i];
}
- h = ngx_http_scgi_cache_headers;
+ h = default_params;
while (h->key.len) {
@@ -1567,8 +1587,6 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
nsrc = params_merged.nelts;
}
-#endif
-
for (i = 0; i < nsrc; i++) {
if (src[i].key.len > sizeof("HTTP_") - 1
@@ -1589,7 +1607,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
}
}
- copy = ngx_array_push_n(conf->params_len,
+ copy = ngx_array_push_n(params->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -1598,7 +1616,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->len = src[i].key.len + 1;
- copy = ngx_array_push_n(conf->params_len,
+ copy = ngx_array_push_n(params->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -1612,7 +1630,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
+ src[i].key.len + 1 + sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
- copy = ngx_array_push_n(conf->params, size);
+ copy = ngx_array_push_n(params->values, size);
if (copy == NULL) {
return NGX_ERROR;
}
@@ -1628,15 +1646,15 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
sc.cf = cf;
sc.source = &src[i].value;
- sc.flushes = &conf->flushes;
- sc.lengths = &conf->params_len;
- sc.values = &conf->params;
+ sc.flushes = &params->flushes;
+ sc.lengths = &params->lengths;
+ sc.values = &params->values;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_ERROR;
}
- code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -1644,7 +1662,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
*code = (uintptr_t) NULL;
- code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->values, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -1652,23 +1670,16 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
*code = (uintptr_t) NULL;
}
- code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
*code = (uintptr_t) NULL;
- conf->header_params = headers_names.nelts;
+ params->number = headers_names.nelts;
- hash.hash = &conf->headers_hash;
+ hash.hash = &params->hash;
hash.key = ngx_hash_key_lc;
hash.max_size = 512;
hash.bucket_size = 64;
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 5114782b6..d12fbdf7b 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -13,16 +13,23 @@
typedef struct {
+ ngx_array_t *flushes;
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+ ngx_uint_t number;
+ ngx_hash_t hash;
+} ngx_http_uwsgi_params_t;
+
+
+typedef struct {
ngx_http_upstream_conf_t upstream;
- ngx_array_t *flushes;
- ngx_array_t *params_len;
- ngx_array_t *params;
+ ngx_http_uwsgi_params_t params;
+#if (NGX_HTTP_CACHE)
+ ngx_http_uwsgi_params_t params_cache;
+#endif
ngx_array_t *params_source;
- ngx_hash_t headers_hash;
- ngx_uint_t header_params;
-
ngx_array_t *uwsgi_lengths;
ngx_array_t *uwsgi_values;
@@ -42,6 +49,9 @@ typedef struct {
ngx_uint_t ssl_verify_depth;
ngx_str_t ssl_trusted_certificate;
ngx_str_t ssl_crl;
+ ngx_str_t ssl_certificate;
+ ngx_str_t ssl_certificate_key;
+ ngx_array_t *ssl_passwords;
#endif
} ngx_http_uwsgi_loc_conf_t;
@@ -59,8 +69,9 @@ static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);
-static ngx_int_t ngx_http_uwsgi_merge_params(ngx_conf_t *cf,
- ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev);
+static ngx_int_t ngx_http_uwsgi_init_params(ngx_conf_t *cf,
+ ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_params_t *params,
+ ngx_keyval_t *default_params);
static char *ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -76,6 +87,8 @@ static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
#endif
#if (NGX_HTTP_SSL)
+static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf,
+ ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
ngx_http_uwsgi_loc_conf_t *uwcf);
#endif
@@ -331,6 +344,13 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
NULL },
+ { ngx_string("uwsgi_cache_lock_age"),
+ 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_uwsgi_loc_conf_t, upstream.cache_lock_age),
+ NULL },
+
{ ngx_string("uwsgi_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -482,6 +502,27 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, ssl_crl),
NULL },
+ { ngx_string("uwsgi_ssl_certificate"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate),
+ NULL },
+
+ { ngx_string("uwsgi_ssl_certificate_key"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key),
+ NULL },
+
+ { ngx_string("uwsgi_ssl_password_file"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_uwsgi_ssl_password_file,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
#endif
ngx_null_command
@@ -746,6 +787,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
ngx_chain_t *cl, *body;
ngx_list_part_t *part;
ngx_table_elt_t *header, **ignored;
+ ngx_http_uwsgi_params_t *params;
ngx_http_script_code_pt code;
ngx_http_script_engine_t e, le;
ngx_http_uwsgi_loc_conf_t *uwcf;
@@ -757,13 +799,19 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
- if (uwcf->params_len) {
+#if (NGX_HTTP_CACHE)
+ params = r->upstream->cacheable ? &uwcf->params_cache : &uwcf->params;
+#else
+ params = &uwcf->params;
+#endif
+
+ if (params->lengths) {
ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
- ngx_http_script_flush_no_cacheable_variables(r, uwcf->flushes);
+ ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
le.flushed = 1;
- le.ip = uwcf->params_len->elts;
+ le.ip = params->lengths->elts;
le.request = r;
while (*(uintptr_t *) le.ip) {
@@ -792,7 +840,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
allocated = 0;
lowcase_key = NULL;
- if (uwcf->header_params) {
+ if (params->number) {
n = 0;
part = &r->headers_in.headers.part;
@@ -822,7 +870,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
i = 0;
}
- if (uwcf->header_params) {
+ if (params->number) {
if (allocated < header[i].key.len) {
allocated = header[i].key.len + 16;
lowcase_key = ngx_pnalloc(r->pool, allocated);
@@ -847,7 +895,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
lowcase_key[n] = ch;
}
- if (ngx_hash_find(&uwcf->headers_hash, hash, lowcase_key, n)) {
+ if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
ignored[header_params++] = &header[i];
continue;
}
@@ -886,15 +934,15 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
*b->last++ = (u_char) ((len >> 8) & 0xff);
*b->last++ = (u_char) uwcf->modifier2;
- if (uwcf->params_len) {
+ if (params->lengths) {
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- e.ip = uwcf->params->elts;
+ e.ip = params->values->elts;
e.pos = b->last;
e.request = r;
e.flushed = 1;
- le.ip = uwcf->params_len->elts;
+ le.ip = params->lengths->elts;
while (*(uintptr_t *) le.ip) {
@@ -1313,6 +1361,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
+ conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif
@@ -1326,6 +1375,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.ssl_server_name = NGX_CONF_UNSET;
conf->upstream.ssl_verify = NGX_CONF_UNSET;
conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
+ conf->ssl_passwords = NGX_CONF_UNSET_PTR;
#endif
/* "uwsgi_cyclic_temp_file" is disabled */
@@ -1346,6 +1396,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_uwsgi_loc_conf_t *conf = child;
size_t size;
+ ngx_int_t rc;
ngx_hash_init_t hash;
ngx_http_core_loc_conf_t *clcf;
@@ -1579,6 +1630,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000);
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
+ prev->upstream.cache_lock_age, 5000);
+
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
@@ -1619,6 +1673,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
prev->ssl_trusted_certificate, "");
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
+ ngx_conf_merge_str_value(conf->ssl_certificate,
+ prev->ssl_certificate, "");
+ ngx_conf_merge_str_value(conf->ssl_certificate_key,
+ prev->ssl_certificate_key, "");
+ ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
+
if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -1661,69 +1721,67 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);
- if (ngx_http_uwsgi_merge_params(cf, conf, prev) != NGX_OK) {
+ if (conf->params_source == NULL) {
+ conf->params = prev->params;
+#if (NGX_HTTP_CACHE)
+ conf->params_cache = prev->params_cache;
+#endif
+ conf->params_source = prev->params_source;
+ }
+
+ rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params, NULL);
+ if (rc != NGX_OK) {
return NGX_CONF_ERROR;
}
+#if (NGX_HTTP_CACHE)
+
+ if (conf->upstream.cache) {
+ rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params_cache,
+ ngx_http_uwsgi_cache_headers);
+ if (rc != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+#endif
+
return NGX_CONF_OK;
}
static ngx_int_t
-ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
- ngx_http_uwsgi_loc_conf_t *prev)
+ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
+ ngx_http_uwsgi_params_t *params, ngx_keyval_t *default_params)
{
u_char *p;
size_t size;
uintptr_t *code;
ngx_uint_t i, nsrc;
- ngx_array_t headers_names;
-#if (NGX_HTTP_CACHE)
- ngx_array_t params_merged;
-#endif
+ ngx_array_t headers_names, params_merged;
+ ngx_keyval_t *h;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
- ngx_http_upstream_param_t *src;
+ ngx_http_upstream_param_t *src, *s;
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
- if (conf->params_source == NULL) {
- conf->params_source = prev->params_source;
-
- if (prev->headers_hash.buckets
-#if (NGX_HTTP_CACHE)
- && ((conf->upstream.cache == NULL)
- == (prev->upstream.cache == NULL))
-#endif
- )
- {
- conf->flushes = prev->flushes;
- conf->params_len = prev->params_len;
- conf->params = prev->params;
- conf->headers_hash = prev->headers_hash;
- conf->header_params = prev->header_params;
-
- return NGX_OK;
- }
+ if (params->hash.buckets) {
+ return NGX_OK;
}
- if (conf->params_source == NULL
-#if (NGX_HTTP_CACHE)
- && (conf->upstream.cache == NULL)
-#endif
- )
- {
- conf->headers_hash.buckets = (void *) 1;
+ if (conf->params_source == NULL && default_params == NULL) {
+ params->hash.buckets = (void *) 1;
return NGX_OK;
}
- conf->params_len = ngx_array_create(cf->pool, 64, 1);
- if (conf->params_len == NULL) {
+ params->lengths = ngx_array_create(cf->pool, 64, 1);
+ if (params->lengths == NULL) {
return NGX_ERROR;
}
- conf->params = ngx_array_create(cf->pool, 512, 1);
- if (conf->params == NULL) {
+ params->values = ngx_array_create(cf->pool, 512, 1);
+ if (params->values == NULL) {
return NGX_ERROR;
}
@@ -1742,12 +1800,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
nsrc = 0;
}
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- ngx_keyval_t *h;
- ngx_http_upstream_param_t *s;
-
+ if (default_params) {
if (ngx_array_init(&params_merged, cf->temp_pool, 4,
sizeof(ngx_http_upstream_param_t))
!= NGX_OK)
@@ -1765,7 +1818,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
*s = src[i];
}
- h = ngx_http_uwsgi_cache_headers;
+ h = default_params;
while (h->key.len) {
@@ -1796,8 +1849,6 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
nsrc = params_merged.nelts;
}
-#endif
-
for (i = 0; i < nsrc; i++) {
if (src[i].key.len > sizeof("HTTP_") - 1
@@ -1818,7 +1869,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
}
}
- copy = ngx_array_push_n(conf->params_len,
+ copy = ngx_array_push_n(params->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -1827,7 +1878,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
- copy = ngx_array_push_n(conf->params_len,
+ copy = ngx_array_push_n(params->lengths,
sizeof(ngx_http_script_copy_code_t));
if (copy == NULL) {
return NGX_ERROR;
@@ -1841,7 +1892,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
+ src[i].key.len + sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
- copy = ngx_array_push_n(conf->params, size);
+ copy = ngx_array_push_n(params->values, size);
if (copy == NULL) {
return NGX_ERROR;
}
@@ -1857,15 +1908,15 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
sc.cf = cf;
sc.source = &src[i].value;
- sc.flushes = &conf->flushes;
- sc.lengths = &conf->params_len;
- sc.values = &conf->params;
+ sc.flushes = &params->flushes;
+ sc.lengths = &params->lengths;
+ sc.values = &params->values;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_ERROR;
}
- code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -1873,7 +1924,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
*code = (uintptr_t) NULL;
- code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->values, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
@@ -1881,16 +1932,16 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
*code = (uintptr_t) NULL;
}
- code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
if (code == NULL) {
return NGX_ERROR;
}
*code = (uintptr_t) NULL;
- conf->header_params = headers_names.nelts;
+ params->number = headers_names.nelts;
- hash.hash = &conf->headers_hash;
+ hash.hash = &params->hash;
hash.key = ngx_hash_key_lc;
hash.max_size = 512;
hash.bucket_size = 64;
@@ -2109,6 +2160,29 @@ ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_HTTP_SSL)
+static char *
+ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_uwsgi_loc_conf_t *uwcf = conf;
+
+ ngx_str_t *value;
+
+ if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
+
+ if (uwcf->ssl_passwords == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
static ngx_int_t
ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
{
@@ -2135,6 +2209,23 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
cln->handler = ngx_ssl_cleanup_ctx;
cln->data = uwcf->upstream.ssl;
+ if (uwcf->ssl_certificate.len) {
+
+ if (uwcf->ssl_certificate_key.len == 0) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no \"uwsgi_ssl_certificate_key\" is defined "
+ "for certificate \"%V\"", &uwcf->ssl_certificate);
+ return NGX_ERROR;
+ }
+
+ if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate,
+ &uwcf->ssl_certificate_key, uwcf->ssl_passwords)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
if (SSL_CTX_set_cipher_list(uwcf->upstream.ssl->ctx,
(const char *) uwcf->ssl_ciphers.data)
== 0)
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index f89766d58..033882e53 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -57,6 +57,7 @@ typedef struct {
time_t valid_sec;
size_t body_start;
off_t fs_size;
+ ngx_msec_t lock_time;
} ngx_http_file_cache_node_t;
@@ -91,6 +92,8 @@ struct ngx_http_cache_s {
ngx_http_file_cache_node_t *node;
ngx_msec_t lock_timeout;
+ ngx_msec_t lock_age;
+ ngx_msec_t lock_time;
ngx_msec_t wait_time;
ngx_event_t wait_event;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 3b36f4a19..d8ff53bfe 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1973,6 +1973,10 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
+ if (r->post_action) {
+ return NGX_OK;
+ }
+
if (r->header_sent) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"header already sent");
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index bc4c80602..c3f4f05d2 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -14,6 +14,8 @@
static ngx_int_t ngx_http_file_cache_lock(ngx_http_request_t *r,
ngx_http_cache_t *c);
static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev);
+static void ngx_http_file_cache_lock_wait(ngx_http_request_t *r,
+ ngx_http_cache_t *c);
static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r,
ngx_http_cache_t *c);
static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r,
@@ -396,13 +398,19 @@ ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
return NGX_DECLINED;
}
+ now = ngx_current_msec;
+
cache = c->file_cache;
ngx_shmtx_lock(&cache->shpool->mutex);
- if (!c->node->updating) {
+ timer = c->node->lock_time - now;
+
+ if (!c->node->updating || (ngx_msec_int_t) timer <= 0) {
c->node->updating = 1;
+ c->node->lock_time = now + c->lock_age;
c->updating = 1;
+ c->lock_time = c->node->lock_time;
}
ngx_shmtx_unlock(&cache->shpool->mutex);
@@ -415,9 +423,11 @@ ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
return NGX_DECLINED;
}
- c->waiting = 1;
+ if (c->lock_timeout == 0) {
+ return NGX_HTTP_CACHE_SCARCE;
+ }
- now = ngx_current_msec;
+ c->waiting = 1;
if (c->wait_time == 0) {
c->wait_time = now + c->lock_timeout;
@@ -440,24 +450,38 @@ ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
static void
ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev)
{
- ngx_uint_t wait;
- ngx_msec_t timer;
- ngx_http_cache_t *c;
- ngx_http_request_t *r;
- ngx_http_file_cache_t *cache;
+ ngx_connection_t *c;
+ ngx_http_request_t *r;
r = ev->data;
- c = r->cache;
+ c = r->connection;
+
+ ngx_http_set_log_request(c->log, r);
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http file cache wait handler wt:%M cur:%M",
- c->wait_time, ngx_current_msec);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http file cache wait: \"%V?%V\"", &r->uri, &r->args);
- timer = c->wait_time - ngx_current_msec;
+ ngx_http_file_cache_lock_wait(r, r->cache);
+
+ ngx_http_run_posted_requests(c);
+}
+
+
+static void
+ngx_http_file_cache_lock_wait(ngx_http_request_t *r, ngx_http_cache_t *c)
+{
+ ngx_uint_t wait;
+ ngx_msec_t now, timer;
+ ngx_http_file_cache_t *cache;
+
+ now = ngx_current_msec;
+
+ timer = c->wait_time - now;
if ((ngx_msec_int_t) timer <= 0) {
- ngx_log_error(NGX_LOG_INFO, ev->log, 0, "cache lock timeout");
- c->lock = 0;
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "cache lock timeout");
+ c->lock_timeout = 0;
goto wakeup;
}
@@ -466,14 +490,16 @@ ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev)
ngx_shmtx_lock(&cache->shpool->mutex);
- if (c->node->updating) {
+ timer = c->node->lock_time - now;
+
+ if (c->node->updating && (ngx_msec_int_t) timer > 0) {
wait = 1;
}
ngx_shmtx_unlock(&cache->shpool->mutex);
if (wait) {
- ngx_add_timer(ev, (timer > 500) ? 500 : timer);
+ ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer);
return;
}
@@ -481,7 +507,7 @@ wakeup:
c->waiting = 0;
r->main->blocked--;
- r->connection->write->handler(r->connection->write);
+ r->write_event_handler(r);
}
@@ -588,6 +614,7 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
} else {
c->node->updating = 1;
c->updating = 1;
+ c->lock_time = c->node->lock_time;
rc = NGX_HTTP_CACHE_STALE;
}
@@ -652,15 +679,24 @@ static void
ngx_http_cache_aio_event_handler(ngx_event_t *ev)
{
ngx_event_aio_t *aio;
+ ngx_connection_t *c;
ngx_http_request_t *r;
aio = ev->data;
r = aio->data;
+ c = r->connection;
+
+ ngx_http_set_log_request(c->log, r);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http file cache aio: \"%V?%V\"", &r->uri, &r->args);
r->main->blocked--;
r->aio = 0;
- r->connection->write->handler(r->connection->write);
+ r->write_event_handler(r);
+
+ ngx_http_run_posted_requests(c);
}
#endif
@@ -1022,7 +1058,6 @@ ngx_http_file_cache_vary_header(ngx_http_request_t *r, ngx_md5_t *md5,
/* normalize spaces */
p = header[i].value.data;
- start = p;
last = p + header[i].value.len;
while (p < last) {
@@ -1454,7 +1489,7 @@ ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
fcn = c->node;
fcn->count--;
- if (c->updating) {
+ if (c->updating && fcn->lock_time == c->lock_time) {
fcn->updating = 0;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 18c3b04e4..a07d5e47f 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2169,13 +2169,11 @@ ngx_http_request_handler(ngx_event_t *ev)
{
ngx_connection_t *c;
ngx_http_request_t *r;
- ngx_http_log_ctx_t *ctx;
c = ev->data;
r = c->data;
- ctx = c->log->data;
- ctx->current_request = r;
+ ngx_http_set_log_request(c->log, r);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http run request: \"%V?%V\"", &r->uri, &r->args);
@@ -2195,7 +2193,6 @@ void
ngx_http_run_posted_requests(ngx_connection_t *c)
{
ngx_http_request_t *r;
- ngx_http_log_ctx_t *ctx;
ngx_http_posted_request_t *pr;
for ( ;; ) {
@@ -2215,8 +2212,7 @@ ngx_http_run_posted_requests(ngx_connection_t *c)
r = pr->request;
- ctx = c->log->data;
- ctx->current_request = r;
+ ngx_http_set_log_request(c->log, r);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http posted request: \"%V?%V\"", &r->uri, &r->args);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index f6ea6fb56..cffab9a69 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -595,4 +595,8 @@ extern ngx_http_header_out_t ngx_http_headers_out[];
}
+#define ngx_http_set_log_request(log, r) \
+ ((ngx_http_log_ctx_t *) log->data)->current_request = r
+
+
#endif /* _NGX_HTTP_REQUEST_H_INCLUDED_ */
diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c
index 3c57882a6..6eac9326a 100644
--- a/src/http/ngx_http_spdy.c
+++ b/src/http/ngx_http_spdy.c
@@ -1065,16 +1065,16 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
: Z_OK;
}
- if (z != Z_OK) {
- return ngx_http_spdy_state_inflate_error(sc, z);
- }
-
ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
sc->zstream_in.next_in, sc->zstream_in.next_out,
sc->zstream_in.avail_in, sc->zstream_in.avail_out,
z);
+ if (z != Z_OK) {
+ return ngx_http_spdy_state_inflate_error(sc, z);
+ }
+
sc->length -= sc->zstream_in.next_in - pos;
pos = sc->zstream_in.next_in;
@@ -1164,6 +1164,12 @@ ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos,
z = inflate(&sc->zstream_in, Z_NO_FLUSH);
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
+ sc->zstream_in.next_in, sc->zstream_in.next_out,
+ sc->zstream_in.avail_in, sc->zstream_in.avail_out,
+ z);
+
if (z != Z_OK) {
return ngx_http_spdy_state_inflate_error(sc, z);
}
@@ -1265,6 +1271,12 @@ ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, u_char *pos,
n = inflate(&sc->zstream_in, Z_NO_FLUSH);
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
+ "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
+ sc->zstream_in.next_in, sc->zstream_in.next_out,
+ sc->zstream_in.avail_in, sc->zstream_in.avail_out,
+ n);
+
if (n != Z_OK) {
return ngx_http_spdy_state_inflate_error(sc, n);
}
@@ -2648,19 +2660,18 @@ ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r)
rest = r->header_in->last - r->header_in->pos;
/*
- * equality is prohibited since one more byte is needed
- * for null-termination
+ * One more byte is needed for null-termination
+ * and another one for further progress.
*/
- if (rest >= cscf->large_client_header_buffers.size) {
+ if (rest > cscf->large_client_header_buffers.size - 2) {
p = r->header_in->pos;
if (rest > NGX_MAX_ERROR_STR - 300) {
rest = NGX_MAX_ERROR_STR - 300;
- p[rest++] = '.'; p[rest++] = '.'; p[rest++] = '.';
}
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent too long header name or value: \"%*s\"",
+ "client sent too long header name or value: \"%*s...\"",
rest, p);
return NGX_DECLINED;
@@ -3306,8 +3317,10 @@ ngx_http_spdy_close_stream_handler(ngx_event_t *ev)
void
ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
{
+ int tcp_nodelay;
ngx_event_t *ev;
- ngx_connection_t *fc;
+ ngx_connection_t *c, *fc;
+ ngx_http_core_loc_conf_t *clcf;
ngx_http_spdy_stream_t **index, *s;
ngx_http_spdy_srv_conf_t *sscf;
ngx_http_spdy_connection_t *sc;
@@ -3333,6 +3346,54 @@ ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
{
sc->connection->error = 1;
}
+
+ } else {
+ c = sc->connection;
+
+ if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
+ if (ngx_tcp_push(c->fd) == -1) {
+ ngx_connection_error(c, ngx_socket_errno,
+ ngx_tcp_push_n " failed");
+ c->error = 1;
+ tcp_nodelay = 0;
+
+ } else {
+ c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
+ tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
+ }
+
+ } else {
+ tcp_nodelay = 1;
+ }
+
+ clcf = ngx_http_get_module_loc_conf(stream->request,
+ ngx_http_core_module);
+
+ if (tcp_nodelay
+ && clcf->tcp_nodelay
+ && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
+ {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
+
+ if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
+ (const void *) &tcp_nodelay, sizeof(int))
+ == -1)
+ {
+#if (NGX_SOLARIS)
+ /* Solaris returns EINVAL if a socket has been shut down */
+ c->log_error = NGX_ERROR_IGNORE_EINVAL;
+#endif
+
+ ngx_connection_error(c, ngx_socket_errno,
+ "setsockopt(TCP_NODELAY) failed");
+
+ c->log_error = NGX_ERROR_INFO;
+ c->error = 1;
+
+ } else {
+ c->tcp_nodelay = NGX_TCP_NODELAY_SET;
+ }
+ }
}
if (sc->stream == stream) {
diff --git a/src/http/ngx_http_spdy_filter_module.c b/src/http/ngx_http_spdy_filter_module.c
index d1406a665..377e93520 100644
--- a/src/http/ngx_http_spdy_filter_module.c
+++ b/src/http/ngx_http_spdy_filter_module.c
@@ -493,9 +493,13 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
continue;
}
- *last++ = '\0';
+ if (h[j].value.len) {
+ if (last != p) {
+ *last++ = '\0';
+ }
- last = ngx_cpymem(last, h[j].value.data, h[j].value.len);
+ last = ngx_cpymem(last, h[j].value.data, h[j].value.len);
+ }
h[j].hash = 2;
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 3e8ce09e1..4c768b1bc 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -784,6 +784,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->lock = u->conf->cache_lock;
c->lock_timeout = u->conf->cache_lock_timeout;
+ c->lock_age = u->conf->cache_lock_age;
u->cache_status = NGX_HTTP_CACHE_MISS;
}
@@ -941,6 +942,11 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
u = r->upstream;
ur = u->resolved;
+ ngx_http_set_log_request(c->log, r);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http upstream resolve: \"%V?%V\"", &r->uri, &r->args);
+
if (ctx->state) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"%V could not be resolved (%i: %s)",
@@ -1002,7 +1008,6 @@ ngx_http_upstream_handler(ngx_event_t *ev)
{
ngx_connection_t *c;
ngx_http_request_t *r;
- ngx_http_log_ctx_t *ctx;
ngx_http_upstream_t *u;
c = ev->data;
@@ -1011,8 +1016,7 @@ ngx_http_upstream_handler(ngx_event_t *ev)
u = r->upstream;
c = r->connection;
- ctx = c->log->data;
- ctx->current_request = r;
+ ngx_http_set_log_request(c->log, r);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream request: \"%V?%V\"", &r->uri, &r->args);
@@ -1446,6 +1450,8 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
r = c->data;
u = r->upstream;
+ ngx_http_set_log_request(c->log, r);
+
if (c->ssl->handshaked) {
if (u->conf->ssl_verify) {
@@ -2218,19 +2224,26 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
uri = u->headers_in.x_accel_redirect->value;
- ngx_str_null(&args);
- flags = NGX_HTTP_LOG_UNSAFE;
- if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
- return NGX_DONE;
- }
+ if (uri.data[0] == '@') {
+ ngx_http_named_location(r, &uri);
+
+ } else {
+ ngx_str_null(&args);
+ flags = NGX_HTTP_LOG_UNSAFE;
+
+ if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
+ ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
+ return NGX_DONE;
+ }
- if (r->method != NGX_HTTP_HEAD) {
- r->method = NGX_HTTP_GET;
+ if (r->method != NGX_HTTP_HEAD) {
+ r->method = NGX_HTTP_GET;
+ }
+
+ ngx_http_internal_redirect(r, &uri, &args);
}
- ngx_http_internal_redirect(r, &uri, &args);
ngx_http_finalize_request(r, NGX_DONE);
return NGX_DONE;
}
@@ -3926,7 +3939,7 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
#if (NGX_HTTP_CACHE)
{
- u_char *p, *last;
+ u_char *p, *start, *last;
ngx_int_t n;
if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) {
@@ -3941,18 +3954,24 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
return NGX_OK;
}
- p = h->value.data;
- last = p + h->value.len;
+ start = h->value.data;
+ last = start + h->value.len;
- if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
- || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
- || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
+ if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL
+ || ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL
+ || ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL)
{
u->cacheable = 0;
return NGX_OK;
}
- p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
+ p = ngx_strlcasestrn(start, last, (u_char *) "s-maxage=", 9 - 1);
+ offset = 9;
+
+ if (p == NULL) {
+ p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1);
+ offset = 8;
+ }
if (p == NULL) {
return NGX_OK;
@@ -3960,7 +3979,7 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
n = 0;
- for (p += 8; p < last; p++) {
+ for (p += offset; p < last; p++) {
if (*p == ',' || *p == ';' || *p == ' ') {
break;
}
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 0032c2c22..d04b66906 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -183,6 +183,7 @@ typedef struct {
ngx_flag_t cache_lock;
ngx_msec_t cache_lock_timeout;
+ ngx_msec_t cache_lock_age;
ngx_flag_t cache_revalidate;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index b19f75bda..a2db53024 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -48,7 +48,7 @@ ngx_int_t
ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
off_t size, sent, nsent, limit;
- ngx_uint_t last, flush;
+ ngx_uint_t last, flush, sync;
ngx_msec_t delay;
ngx_chain_t *cl, *ln, **ll, *chain;
ngx_connection_t *c;
@@ -62,6 +62,7 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
size = 0;
flush = 0;
+ sync = 0;
last = 0;
ll = &r->out;
@@ -105,6 +106,10 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
flush = 1;
}
+ if (cl->buf->sync) {
+ sync = 1;
+ }
+
if (cl->buf->last_buf) {
last = 1;
}
@@ -157,6 +162,10 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
flush = 1;
}
+ if (cl->buf->sync) {
+ sync = 1;
+ }
+
if (cl->buf->last_buf) {
last = 1;
}
@@ -188,7 +197,7 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
&& !(c->buffered & NGX_LOWLEVEL_BUFFERED)
&& !(last && c->need_last_buf))
{
- if (last || flush) {
+ if (last || flush || sync) {
for (cl = r->out; cl; /* void */) {
ln = cl;
cl = cl->next;
diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c
index 8485f9749..f01651a11 100644
--- a/src/os/unix/ngx_darwin_sendfile_chain.c
+++ b/src/os/unix/ngx_darwin_sendfile_chain.c
@@ -31,17 +31,16 @@ ngx_chain_t *
ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
int rc;
- u_char *prev;
- off_t size, send, prev_send, aligned, sent, fprev;
- off_t header_size, file_size;
+ off_t send, prev_send, sent;
+ off_t file_size;
+ ssize_t n;
ngx_uint_t eintr;
ngx_err_t err;
ngx_buf_t *file;
- ngx_array_t header, trailer;
ngx_event_t *wev;
ngx_chain_t *cl;
+ ngx_iovec_t header, trailer;
struct sf_hdtr hdtr;
- struct iovec *iov;
struct iovec headers[NGX_IOVS_PREALLOCATE];
struct iovec trailers[NGX_IOVS_PREALLOCATE];
@@ -70,165 +69,65 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
send = 0;
- header.elts = headers;
- header.size = sizeof(struct iovec);
+ header.iovs = headers;
header.nalloc = NGX_IOVS_PREALLOCATE;
- header.pool = c->pool;
- trailer.elts = trailers;
- trailer.size = sizeof(struct iovec);
+ trailer.iovs = trailers;
trailer.nalloc = NGX_IOVS_PREALLOCATE;
- trailer.pool = c->pool;
for ( ;; ) {
- file = NULL;
- file_size = 0;
- header_size = 0;
eintr = 0;
prev_send = send;
- header.nelts = 0;
- trailer.nelts = 0;
-
/* create the header iovec and coalesce the neighbouring bufs */
- prev = NULL;
- iov = NULL;
-
- for (cl = in; cl && send < limit; cl = cl->next) {
-
- if (ngx_buf_special(cl->buf)) {
- continue;
- }
-
- if (!ngx_buf_in_memory_only(cl->buf)) {
- break;
- }
-
- size = cl->buf->last - cl->buf->pos;
-
- if (send + size > limit) {
- size = limit - send;
- }
-
- if (prev == cl->buf->pos) {
- iov->iov_len += (size_t) size;
-
- } else {
- if (header.nelts >= IOV_MAX) {
- break;
- }
-
- iov = ngx_array_push(&header);
- if (iov == NULL) {
- return NGX_CHAIN_ERROR;
- }
-
- iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = (size_t) size;
- }
+ cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log);
- prev = cl->buf->pos + (size_t) size;
- header_size += size;
- send += size;
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
}
+ send += header.size;
if (cl && cl->buf->in_file && send < limit) {
file = cl->buf;
/* coalesce the neighbouring file bufs */
- do {
- size = cl->buf->file_last - cl->buf->file_pos;
-
- if (send + size > limit) {
- size = limit - send;
-
- aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
- & ~((off_t) ngx_pagesize - 1);
-
- if (aligned <= cl->buf->file_last) {
- size = aligned - cl->buf->file_pos;
- }
- }
-
- file_size += size;
- send += size;
- fprev = cl->buf->file_pos + size;
- cl = cl->next;
-
- } while (cl
- && cl->buf->in_file
- && send < limit
- && file->file->fd == cl->buf->file->fd
- && fprev == cl->buf->file_pos);
- }
-
- if (file && header.nelts == 0) {
-
- /* create the trailer iovec and coalesce the neighbouring bufs */
-
- prev = NULL;
- iov = NULL;
-
- while (cl && send < limit) {
-
- if (ngx_buf_special(cl->buf)) {
- cl = cl->next;
- continue;
- }
-
- if (!ngx_buf_in_memory_only(cl->buf)) {
- break;
- }
+ file_size = ngx_chain_coalesce_file(&cl, limit - send);
- size = cl->buf->last - cl->buf->pos;
+ send += file_size;
- if (send + size > limit) {
- size = limit - send;
- }
-
- if (prev == cl->buf->pos) {
- iov->iov_len += (size_t) size;
+ if (header.count == 0) {
- } else {
- if (trailer.nelts >= IOV_MAX) {
- break;
- }
-
- iov = ngx_array_push(&trailer);
- if (iov == NULL) {
- return NGX_CHAIN_ERROR;
- }
+ /*
+ * create the trailer iovec and coalesce the neighbouring bufs
+ */
- iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = (size_t) size;
+ cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send,
+ c->log);
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
}
- prev = cl->buf->pos + (size_t) size;
- send += size;
- cl = cl->next;
+ send += trailer.size;
}
- }
-
- if (file) {
/*
* sendfile() returns EINVAL if sf_hdtr's count is 0,
* but corresponding pointer is not NULL
*/
- hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL;
- hdtr.hdr_cnt = header.nelts;
- hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL;
- hdtr.trl_cnt = trailer.nelts;
+ hdtr.headers = header.count ? header.iovs : NULL;
+ hdtr.hdr_cnt = header.count;
+ hdtr.trailers = trailer.count ? trailer.iovs : NULL;
+ hdtr.trl_cnt = trailer.count;
- sent = header_size + file_size;
+ sent = header.size + file_size;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "sendfile: @%O %O h:%O",
- file->file_pos, sent, header_size);
+ "sendfile: @%O %O h:%uz",
+ file->file_pos, sent, header.size);
rc = sendfile(file->file->fd, c->fd, file->file_pos,
&sent, &hdtr, 0);
@@ -271,41 +170,21 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"sendfile: %d, @%O %O:%O",
- rc, file->file_pos, sent, file_size + header_size);
+ rc, file->file_pos, sent, file_size + header.size);
} else {
- rc = writev(c->fd, header.elts, header.nelts);
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "writev: %d of %O", rc, header_size);
-
- if (rc == -1) {
- err = ngx_errno;
-
- switch (err) {
- case NGX_EAGAIN:
- break;
+ n = ngx_writev(c, &header);
- case NGX_EINTR:
- eintr = 1;
- break;
-
- default:
- wev->error = 1;
- ngx_connection_error(c, err, "writev() failed");
- return NGX_CHAIN_ERROR;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
- "writev() not ready");
+ if (n == NGX_ERROR) {
+ return NGX_CHAIN_ERROR;
}
- sent = rc > 0 ? rc : 0;
+ sent = (n == NGX_AGAIN) ? 0 : n;
}
c->sent += sent;
- in = ngx_handle_sent_chain(in, sent);
+ in = ngx_chain_update_sent(in, sent);
if (eintr) {
send = prev_send + sent;
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 88eacc2d1..7199c8654 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -33,17 +33,16 @@ ngx_chain_t *
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
int rc, flags;
- u_char *prev;
- off_t size, send, prev_send, aligned, sent, fprev;
- size_t header_size, file_size;
+ off_t send, prev_send, sent;
+ size_t file_size;
+ ssize_t n;
ngx_uint_t eintr, eagain;
ngx_err_t err;
ngx_buf_t *file;
- ngx_array_t header, trailer;
ngx_event_t *wev;
ngx_chain_t *cl;
+ ngx_iovec_t header, trailer;
struct sf_hdtr hdtr;
- struct iovec *iov;
struct iovec headers[NGX_IOVS_PREALLOCATE];
struct iovec trailers[NGX_IOVS_PREALLOCATE];
@@ -74,150 +73,44 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
eagain = 0;
flags = 0;
- header.elts = headers;
- header.size = sizeof(struct iovec);
+ header.iovs = headers;
header.nalloc = NGX_IOVS_PREALLOCATE;
- header.pool = c->pool;
- trailer.elts = trailers;
- trailer.size = sizeof(struct iovec);
+ trailer.iovs = trailers;
trailer.nalloc = NGX_IOVS_PREALLOCATE;
- trailer.pool = c->pool;
for ( ;; ) {
- file = NULL;
- file_size = 0;
- header_size = 0;
eintr = 0;
prev_send = send;
- header.nelts = 0;
- trailer.nelts = 0;
-
/* create the header iovec and coalesce the neighbouring bufs */
- prev = NULL;
- iov = NULL;
-
- for (cl = in; cl && send < limit; cl = cl->next) {
-
- if (ngx_buf_special(cl->buf)) {
- continue;
- }
-
- if (!ngx_buf_in_memory_only(cl->buf)) {
- break;
- }
-
- size = cl->buf->last - cl->buf->pos;
-
- if (send + size > limit) {
- size = limit - send;
- }
+ cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log);
- if (prev == cl->buf->pos) {
- iov->iov_len += (size_t) size;
-
- } else {
- if (header.nelts >= IOV_MAX){
- break;
- }
-
- iov = ngx_array_push(&header);
- if (iov == NULL) {
- return NGX_CHAIN_ERROR;
- }
-
- iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = (size_t) size;
- }
-
- prev = cl->buf->pos + (size_t) size;
- header_size += (size_t) size;
- send += size;
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
}
+ send += header.size;
if (cl && cl->buf->in_file && send < limit) {
file = cl->buf;
/* coalesce the neighbouring file bufs */
- do {
- size = cl->buf->file_last - cl->buf->file_pos;
-
- if (send + size > limit) {
- size = limit - send;
-
- aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
- & ~((off_t) ngx_pagesize - 1);
-
- if (aligned <= cl->buf->file_last) {
- size = aligned - cl->buf->file_pos;
- }
- }
-
- file_size += (size_t) size;
- send += size;
- fprev = cl->buf->file_pos + size;
- cl = cl->next;
-
- } while (cl
- && cl->buf->in_file
- && send < limit
- && file->file->fd == cl->buf->file->fd
- && fprev == cl->buf->file_pos);
- }
-
+ file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send);
- if (file) {
+ send += file_size;
/* create the trailer iovec and coalesce the neighbouring bufs */
- prev = NULL;
- iov = NULL;
-
- while (cl && send < limit) {
-
- if (ngx_buf_special(cl->buf)) {
- cl = cl->next;
- continue;
- }
-
- if (!ngx_buf_in_memory_only(cl->buf)) {
- break;
- }
+ cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, c->log);
- size = cl->buf->last - cl->buf->pos;
-
- if (send + size > limit) {
- size = limit - send;
- }
-
- if (prev == cl->buf->pos) {
- iov->iov_len += (size_t) size;
-
- } else {
- if (trailer.nelts >= IOV_MAX){
- break;
- }
-
- iov = ngx_array_push(&trailer);
- if (iov == NULL) {
- return NGX_CHAIN_ERROR;
- }
-
- iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = (size_t) size;
- }
-
- prev = cl->buf->pos + (size_t) size;
- send += size;
- cl = cl->next;
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
}
- }
- if (file) {
+ send += trailer.size;
if (ngx_freebsd_use_tcp_nopush
&& c->tcp_nopush == NGX_TCP_NOPUSH_UNSET)
@@ -250,10 +143,10 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
* but corresponding pointer is not NULL
*/
- hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL;
- hdtr.hdr_cnt = header.nelts;
- hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL;
- hdtr.trl_cnt = trailer.nelts;
+ hdtr.headers = header.count ? header.iovs : NULL;
+ hdtr.hdr_cnt = header.count;
+ hdtr.trailers = trailer.count ? trailer.iovs : NULL;
+ hdtr.trl_cnt = trailer.count;
/*
* the "nbytes bug" of the old sendfile() syscall:
@@ -261,7 +154,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
*/
if (!ngx_freebsd_sendfile_nbytes_bug) {
- header_size = 0;
+ header.size = 0;
}
sent = 0;
@@ -271,7 +164,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
#endif
rc = sendfile(file->file->fd, c->fd, file->file_pos,
- file_size + header_size, &hdtr, &sent, flags);
+ file_size + header.size, &hdtr, &sent, flags);
if (rc == -1) {
err = ngx_errno;
@@ -322,41 +215,21 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"sendfile: %d, @%O %O:%uz",
- rc, file->file_pos, sent, file_size + header_size);
+ rc, file->file_pos, sent, file_size + header.size);
} else {
- rc = writev(c->fd, header.elts, header.nelts);
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "writev: %d of %uz", rc, header_size);
-
- if (rc == -1) {
- err = ngx_errno;
-
- switch (err) {
- case NGX_EAGAIN:
- break;
-
- case NGX_EINTR:
- eintr = 1;
- break;
-
- default:
- wev->error = 1;
- ngx_connection_error(c, err, "writev() failed");
- return NGX_CHAIN_ERROR;
- }
+ n = ngx_writev(c, &header);
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
- "writev() not ready");
+ if (n == NGX_ERROR) {
+ return NGX_CHAIN_ERROR;
}
- sent = rc > 0 ? rc : 0;
+ sent = (n == NGX_AGAIN) ? 0 : n;
}
c->sent += sent;
- in = ngx_handle_sent_chain(in, sent);
+ in = ngx_chain_update_sent(in, sent);
#if (NGX_HAVE_AIO_SENDFILE)
if (c->busy_sendfile) {
diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c
index 60867c51e..d696438be 100644
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -30,17 +30,17 @@
ngx_chain_t *
ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
- int rc, tcp_nodelay;
- off_t size, send, prev_send, aligned, sent, fprev;
- u_char *prev;
+ int tcp_nodelay;
+ off_t send, prev_send, sent;
size_t file_size;
+ ssize_t n;
ngx_err_t err;
ngx_buf_t *file;
ngx_uint_t eintr;
- ngx_array_t header;
ngx_event_t *wev;
ngx_chain_t *cl;
- struct iovec *iov, headers[NGX_IOVS_PREALLOCATE];
+ ngx_iovec_t header;
+ struct iovec headers[NGX_IOVS_PREALLOCATE];
#if (NGX_HAVE_SENDFILE64)
off_t offset;
#else
@@ -63,86 +63,27 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
send = 0;
- header.elts = headers;
- header.size = sizeof(struct iovec);
+ header.iovs = headers;
header.nalloc = NGX_IOVS_PREALLOCATE;
- header.pool = c->pool;
for ( ;; ) {
- file = NULL;
- file_size = 0;
eintr = 0;
prev_send = send;
- header.nelts = 0;
-
- prev = NULL;
- iov = NULL;
-
/* create the iovec and coalesce the neighbouring bufs */
- for (cl = in; cl && send < limit; cl = cl->next) {
-
- if (ngx_buf_special(cl->buf)) {
- continue;
- }
-
-#if 1
- if (!ngx_buf_in_memory(cl->buf) && !cl->buf->in_file) {
- ngx_log_error(NGX_LOG_ALERT, c->log, 0,
- "zero size buf in sendfile "
- "t:%d r:%d f:%d %p %p-%p %p %O-%O",
- cl->buf->temporary,
- cl->buf->recycled,
- cl->buf->in_file,
- cl->buf->start,
- cl->buf->pos,
- cl->buf->last,
- cl->buf->file,
- cl->buf->file_pos,
- cl->buf->file_last);
-
- ngx_debug_point();
-
- return NGX_CHAIN_ERROR;
- }
-#endif
-
- if (!ngx_buf_in_memory_only(cl->buf)) {
- break;
- }
+ cl = ngx_output_chain_to_iovec(&header, in, limit - send, c->log);
- size = cl->buf->last - cl->buf->pos;
-
- if (send + size > limit) {
- size = limit - send;
- }
-
- if (prev == cl->buf->pos) {
- iov->iov_len += (size_t) size;
-
- } else {
- if (header.nelts >= IOV_MAX) {
- break;
- }
-
- iov = ngx_array_push(&header);
- if (iov == NULL) {
- return NGX_CHAIN_ERROR;
- }
-
- iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = (size_t) size;
- }
-
- prev = cl->buf->pos + (size_t) size;
- send += size;
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
}
+ send += header.size;
+
/* set TCP_CORK if there is a header before a file */
if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET
- && header.nelts != 0
+ && header.count != 0
&& cl
&& cl->buf->in_file)
{
@@ -206,38 +147,14 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
/* get the file buf */
- if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) {
+ if (header.count == 0 && cl && cl->buf->in_file && send < limit) {
file = cl->buf;
/* coalesce the neighbouring file bufs */
- do {
- size = cl->buf->file_last - cl->buf->file_pos;
+ file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send);
- if (send + size > limit) {
- size = limit - send;
-
- aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
- & ~((off_t) ngx_pagesize - 1);
-
- if (aligned <= cl->buf->file_last) {
- size = aligned - cl->buf->file_pos;
- }
- }
-
- file_size += (size_t) size;
- send += size;
- fprev = cl->buf->file_pos + size;
- cl = cl->next;
-
- } while (cl
- && cl->buf->in_file
- && send < limit
- && file->file->fd == cl->buf->file->fd
- && fprev == cl->buf->file_pos);
- }
-
- if (file) {
+ send += file_size;
#if 1
if (file_size == 0) {
ngx_debug_point();
@@ -253,9 +170,9 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"sendfile: @%O %uz", file->file_pos, file_size);
- rc = sendfile(c->fd, file->file->fd, &offset, file_size);
+ n = sendfile(c->fd, file->file->fd, &offset, file_size);
- if (rc == -1) {
+ if (n == -1) {
err = ngx_errno;
switch (err) {
@@ -276,44 +193,25 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
"sendfile() is not ready");
}
- sent = rc > 0 ? rc : 0;
+ sent = n > 0 ? n : 0;
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "sendfile: %d, @%O %O:%uz",
- rc, file->file_pos, sent, file_size);
+ "sendfile: %z, @%O %O:%uz",
+ n, file->file_pos, sent, file_size);
} else {
- rc = writev(c->fd, header.elts, header.nelts);
-
- if (rc == -1) {
- err = ngx_errno;
-
- switch (err) {
- case NGX_EAGAIN:
- break;
+ n = ngx_writev(c, &header);
- case NGX_EINTR:
- eintr = 1;
- break;
-
- default:
- wev->error = 1;
- ngx_connection_error(c, err, "writev() failed");
- return NGX_CHAIN_ERROR;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
- "writev() not ready");
+ if (n == NGX_ERROR) {
+ return NGX_CHAIN_ERROR;
}
- sent = rc > 0 ? rc : 0;
-
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent);
+ sent = (n == NGX_AGAIN) ? 0 : n;
}
c->sent += sent;
- in = ngx_handle_sent_chain(in, sent);
+ in = ngx_chain_update_sent(in, sent);
if (eintr) {
send = prev_send;
diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h
index a1586426c..09f79175e 100644
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -64,6 +64,20 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in,
#endif
+typedef struct {
+ struct iovec *iovs;
+ ngx_uint_t count;
+ size_t size;
+ ngx_uint_t nalloc;
+} ngx_iovec_t;
+
+ngx_chain_t *ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in,
+ size_t limit, ngx_log_t *log);
+
+
+ssize_t ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec);
+
+
extern ngx_os_io_t ngx_os_io;
extern ngx_int_t ngx_ncpu;
extern ngx_int_t ngx_max_sockets;
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 6c84ba8bd..51cf72544 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -809,6 +809,8 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
}
}
+ ngx_event_cancel_timers();
+
if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
{
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
@@ -1213,7 +1215,6 @@ ngx_wakeup_worker_threads(ngx_cycle_t *cycle)
/* STUB */
ngx_done_events(cycle);
- ngx_mutex_destroy(ngx_event_timer_mutex);
return;
}
diff --git a/src/os/unix/ngx_solaris_sendfilev_chain.c b/src/os/unix/ngx_solaris_sendfilev_chain.c
index 1b71f1dd8..7504239d0 100644
--- a/src/os/unix/ngx_solaris_sendfilev_chain.c
+++ b/src/os/unix/ngx_solaris_sendfilev_chain.c
@@ -48,8 +48,8 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ssize_t n;
ngx_int_t eintr;
ngx_err_t err;
+ ngx_uint_t nsfv;
sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS];
- ngx_array_t vec;
ngx_event_t *wev;
ngx_chain_t *cl;
@@ -73,11 +73,6 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
send = 0;
- vec.elts = sfvs;
- vec.size = sizeof(sendfilevec_t);
- vec.nalloc = NGX_SENDFILEVECS;
- vec.pool = c->pool;
-
for ( ;; ) {
fd = SFV_FD_SELF;
prev = NULL;
@@ -87,7 +82,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
sent = 0;
prev_send = send;
- vec.nelts = 0;
+ nsfv = 0;
/* create the sendfilevec and coalesce the neighbouring bufs */
@@ -110,14 +105,11 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
sfv->sfv_len += (size_t) size;
} else {
- if (vec.nelts >= IOV_MAX) {
+ if (nsfv == NGX_SENDFILEVECS) {
break;
}
- sfv = ngx_array_push(&vec);
- if (sfv == NULL) {
- return NGX_CHAIN_ERROR;
- }
+ sfv = &sfvs[nsfv++];
sfv->sfv_fd = SFV_FD_SELF;
sfv->sfv_flag = 0;
@@ -148,14 +140,11 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
sfv->sfv_len += (size_t) size;
} else {
- if (vec.nelts >= IOV_MAX) {
+ if (nsfv == NGX_SENDFILEVECS) {
break;
}
- sfv = ngx_array_push(&vec);
- if (sfv == NULL) {
- return NGX_CHAIN_ERROR;
- }
+ sfv = &sfvs[nsfv++];
fd = cl->buf->file->fd;
sfv->sfv_fd = fd;
@@ -169,7 +158,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
}
}
- n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
+ n = sendfilev(c->fd, sfvs, nsfv, &sent);
if (n == -1) {
err = ngx_errno;
@@ -197,7 +186,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
c->sent += sent;
- in = ngx_handle_sent_chain(in, sent);
+ in = ngx_chain_update_sent(in, sent);
if (eintr) {
send = prev_send + sent;
diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c
index c7b6ebf7c..e38a3aae0 100644
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -13,15 +13,12 @@
ngx_chain_t *
ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
- u_char *prev;
- ssize_t n, size, sent;
+ ssize_t n, sent;
off_t send, prev_send;
- ngx_uint_t eintr;
- ngx_err_t err;
- ngx_array_t vec;
ngx_chain_t *cl;
ngx_event_t *wev;
- struct iovec *iov, iovs[NGX_IOVS_PREALLOCATE];
+ ngx_iovec_t vec;
+ struct iovec iovs[NGX_IOVS_PREALLOCATE];
wev = c->write;
@@ -48,103 +45,172 @@ ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
send = 0;
- vec.elts = iovs;
- vec.size = sizeof(struct iovec);
+ vec.iovs = iovs;
vec.nalloc = NGX_IOVS_PREALLOCATE;
- vec.pool = c->pool;
for ( ;; ) {
- prev = NULL;
- iov = NULL;
- eintr = 0;
prev_send = send;
- vec.nelts = 0;
-
/* create the iovec and coalesce the neighbouring bufs */
- for (cl = in; cl && send < limit; cl = cl->next) {
+ cl = ngx_output_chain_to_iovec(&vec, in, limit - send, c->log);
- if (ngx_buf_special(cl->buf)) {
- continue;
- }
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
+ }
-#if 1
- if (!ngx_buf_in_memory(cl->buf)) {
- ngx_debug_point();
- }
-#endif
+ if (cl && cl->buf->in_file) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "file buf in writev "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ cl->buf->temporary,
+ cl->buf->recycled,
+ cl->buf->in_file,
+ cl->buf->start,
+ cl->buf->pos,
+ cl->buf->last,
+ cl->buf->file,
+ cl->buf->file_pos,
+ cl->buf->file_last);
+
+ ngx_debug_point();
+
+ return NGX_CHAIN_ERROR;
+ }
- size = cl->buf->last - cl->buf->pos;
+ send += vec.size;
- if (send + size > limit) {
- size = (ssize_t) (limit - send);
- }
+ n = ngx_writev(c, &vec);
- if (prev == cl->buf->pos) {
- iov->iov_len += size;
+ if (n == NGX_ERROR) {
+ return NGX_CHAIN_ERROR;
+ }
- } else {
- if (vec.nelts >= IOV_MAX) {
- break;
- }
+ sent = (n == NGX_AGAIN) ? 0 : n;
- iov = ngx_array_push(&vec);
- if (iov == NULL) {
- return NGX_CHAIN_ERROR;
- }
+ c->sent += sent;
- iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = size;
- }
+ in = ngx_chain_update_sent(in, sent);
- prev = cl->buf->pos + size;
- send += size;
+ if (send - prev_send != sent) {
+ wev->ready = 0;
+ return in;
}
- n = writev(c->fd, vec.elts, vec.nelts);
+ if (send >= limit || in == NULL) {
+ return in;
+ }
+ }
+}
- if (n == -1) {
- err = ngx_errno;
- switch (err) {
- case NGX_EAGAIN:
- break;
+ngx_chain_t *
+ngx_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, size_t limit,
+ ngx_log_t *log)
+{
+ size_t total, size;
+ u_char *prev;
+ ngx_uint_t n;
+ struct iovec *iov;
- case NGX_EINTR:
- eintr = 1;
- break;
+ iov = NULL;
+ prev = NULL;
+ total = 0;
+ n = 0;
- default:
- wev->error = 1;
- (void) ngx_connection_error(c, err, "writev() failed");
- return NGX_CHAIN_ERROR;
- }
+ for ( /* void */ ; in && total < limit; in = in->next) {
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
- "writev() not ready");
+ if (ngx_buf_special(in->buf)) {
+ continue;
}
- sent = n > 0 ? n : 0;
-
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent);
+ if (in->buf->in_file) {
+ break;
+ }
- c->sent += sent;
+ if (!ngx_buf_in_memory(in->buf)) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "bad buf in output chain "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ in->buf->temporary,
+ in->buf->recycled,
+ in->buf->in_file,
+ in->buf->start,
+ in->buf->pos,
+ in->buf->last,
+ in->buf->file,
+ in->buf->file_pos,
+ in->buf->file_last);
+
+ ngx_debug_point();
+
+ return NGX_CHAIN_ERROR;
+ }
- in = ngx_handle_sent_chain(in, sent);
+ size = in->buf->last - in->buf->pos;
- if (eintr) {
- send = prev_send;
- continue;
+ if (size > limit - total) {
+ size = limit - total;
}
- if (send - prev_send != sent) {
- wev->ready = 0;
- return in;
+ if (prev == in->buf->pos) {
+ iov->iov_len += size;
+
+ } else {
+ if (n == vec->nalloc) {
+ break;
+ }
+
+ iov = &vec->iovs[n++];
+
+ iov->iov_base = (void *) in->buf->pos;
+ iov->iov_len = size;
}
- if (send >= limit || in == NULL) {
- return in;
+ prev = in->buf->pos + size;
+ total += size;
+ }
+
+ vec->count = n;
+ vec->size = total;
+
+ return in;
+}
+
+
+ssize_t
+ngx_writev(ngx_connection_t *c, ngx_iovec_t *vec)
+{
+ ssize_t n;
+ ngx_err_t err;
+
+eintr:
+
+ n = writev(c->fd, vec->iovs, vec->count);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "writev: %z of %uz", n, vec->size);
+
+ if (n == -1) {
+ err = ngx_errno;
+
+ switch (err) {
+ case NGX_EAGAIN:
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+ "writev() not ready");
+ return NGX_AGAIN;
+
+ case NGX_EINTR:
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+ "writev() was interrupted");
+ goto eintr;
+
+ default:
+ c->write->error = 1;
+ ngx_connection_error(c, err, "writev() failed");
+ return NGX_ERROR;
}
}
+
+ return n;
}