diff options
author | nginx <nginx@nginx.org> | 2014-12-02 13:06:18 +0000 |
---|---|---|
committer | Jon Kolb <kolbyjack@gmail.com> | 2014-12-02 13:06:18 +0000 |
commit | 4392f036d18cab537bbafce809b7a923d8eb0828 (patch) | |
tree | 5af3407b6a374a3ac7f8d4ff33e322a3b06df578 | |
parent | 9a11306bd73c32aeea6f1d6587215dd8054559bb (diff) | |
download | nginx-4392f036d18cab537bbafce809b7a923d8eb0828.tar.gz |
Changes with nginx 1.7.8 02 Dec 2014v1.7.8
*) 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.
38 files changed, 1442 insertions, 1065 deletions
@@ -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(¶ms->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(¶ms_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 = ¶ms->flushes; + sc.lengths = ¶ms->lengths; + sc.values = ¶ms->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 = ¶ms->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(¶ms->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(¶ms_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 = ¶ms->flushes; + sc.lengths = ¶ms->lengths; + sc.values = ¶ms->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 = ¶ms->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(¶ms->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(¶ms_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 = ¶ms->flushes; + sc.lengths = ¶ms->lengths; + sc.values = ¶ms->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 = ¶ms->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; } |