changeset 578:f3a9e57d2e17

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 11 Mar 2010 21:27:17 +0300
parents 5f4de8cf0d9d (current diff) dd7104f21940 (diff)
children e67b227c8dbb
files auto/modules auto/sources src/http/ngx_http_request.h
diffstat 126 files changed, 4320 insertions(+), 1728 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Sep 15 03:43:40 2009 +0400
+++ b/.hgtags	Thu Mar 11 21:27:17 2010 +0300
@@ -262,3 +262,22 @@
 1bc8c12d80ecec4f7f88c35359585ca5139248e3 NGINX_0_8_13
 80f7156c296569546cf57fa286749d84e0cc8b9d NGINX_0_8_14
 0161f31978175e258b8bb4989262b2ccb5fa9207 NGINX_0_8_15
+005a70f9573bc6bcf760786cb0573a62f1e570f3 NGINX_0_8_16
+4c5d2c627a6c0ad577b5e930782128fc7b082599 NGINX_0_8_17
+f7ec98e3caeb844c9401027b092837eee63dccab NGINX_0_8_18
+a52c99698e7f7001336116600d8bb40bdfdc59e0 NGINX_0_8_19
+0dc162a5f3e89e9d967f4aa30b2add942d895083 NGINX_0_8_20
+1dcf6adad48485e10aec666e0774634c318a9d76 NGINX_0_8_21
+c04fa65fe604240cbf3b29f4dddfc7683514fa5a NGINX_0_8_22
+2b9e388c61f18f47f2a26639c1bdf836db7ef41e NGINX_0_8_23
+40c366b3535c1c7c93baedb2ee910c1de0180e62 NGINX_0_8_24
+e19e5f54287869c93f4dc51035231772e5dca61c NGINX_0_8_25
+ab7d265273edb2eb721cb032870c23ffeda0ce60 NGINX_0_8_26
+697030d79811b68a1541986a16d39b8a9bd705c9 NGINX_0_8_27
+43e02819c5cf4e5124486eed8a338cfc2e868f18 NGINX_0_8_28
+5c576ea5dbd969cb73e9c6672723eeb11ddda2ac NGINX_0_8_29
+25255878df91eae733aead855caa35aaf8275671 NGINX_0_8_30
+2da4537168f879f528f09d0e0ce80abe68adf05e NGINX_0_8_31
+daf4847b43ff5f01a6cd52111fc8d747e2db0d72 NGINX_0_8_32
+7fa8dc2315bd08cb5329d94763ea7475d8c4d46d NGINX_0_8_33
+da3c99095432591583f4fde189906f6b860002f7 NGINX_0_8_34
--- a/CHANGES	Tue Sep 15 03:43:40 2009 +0400
+++ b/CHANGES	Thu Mar 11 21:27:17 2010 +0300
@@ -1,4 +1,383 @@
 
+Changes with nginx 0.8.34                                        03 Mar 2010
+
+    *) Bugfix: nginx did not support all ciphers and digests used in client 
+       certificates.
+       Thanks to Innocenty Enikeew.
+
+    *) Bugfix: nginx cached incorrectly FastCGI responses if there was 
+       large stderr output before response.
+
+    *) Bugfix: nginx did not support HTTPS referrers.
+
+    *) Bugfix: nginx/Windows might not find file if path in configuration 
+       was given in other character case; the bug had appeared in 0.8.34.
+
+    *) Bugfix: the $date_local variable has an incorrect value, if the "%s" 
+       format was used.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: if ssl_session_cache was not set or was set to "none", then 
+       during client certificate verify the error "session id context 
+       uninitialized" might occur; the bug had appeared in 0.7.1.
+
+    *) Bugfix: a geo range returned default value if the range included two 
+       or more /16 networks and did not begin at /16 network boundary.
+
+    *) Bugfix: a block used in a "stub" parameter of an "include" SSI 
+       directive was output with "text/plain" MIME type.
+
+    *) Bugfix: $r->sleep() did not work; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.33                                        01 Feb 2010
+
+    *) Security: now nginx/Windows ignores trailing spaces in URI.
+       Thanks to Dan Crowley, Core Security Technologies.
+
+    *) Security: now nginx/Windows ignores short files names.
+       Thanks to Dan Crowley, Core Security Technologies.
+
+    *) Change: now keepalive connections after POST requests are not 
+       disabled for MSIE 7.0+.
+       Thanks to Adam Lounds.
+
+    *) Workaround: now keepalive connections are disabled for Safari.
+       Thanks to Joshua Sierles.
+
+    *) Bugfix: if a proxied or FastCGI request was internally redirected to 
+       another proxied or FastCGI location, then $upstream_response_time 
+       variable may have abnormally large value; the bug had appeared in 
+       0.8.7.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, while 
+       discarding a request body; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.32                                        11 Jan 2010
+
+    *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: regular expression named captures worked for two names only. 
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: now the "localhost" name is used in the "Host" request 
+       header line, if an unix domain socket is defined in the "auth_http" 
+       directive.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx did not support chunked transfer encoding for 201 
+       responses.
+       Thanks to Julian Reich.
+
+    *) Bugfix: if the "expires modified" set date in the past, then a 
+       negative number was set in the "Cache-Control" response header line. 
+       Thanks to Alex Kapranoff.
+
+
+Changes with nginx 0.8.31                                        23 Dec 2009
+
+    *) Feature: now the "error_page" directive may redirect the 301 and 302 
+       responses.
+
+    *) Feature: the $geoip_city_continent_code, $geoip_latitude, and 
+       $geoip_longitude variables.
+       Thanks to Arvind Sundararajan.
+
+    *) Feature: now the ngx_http_image_filter_module deletes always EXIF 
+       and other application specific data if the data consume more than 5% 
+       of a JPEG file.
+
+    *) Bugfix: nginx closed a connection if a cached response had an empty 
+       body.
+       Thanks to Piotr Sikora.
+
+    *) Bugfix: nginx might not be built by gcc 4.x if the -O2 or higher 
+       optimization option was used.
+       Thanks to Maxim Dounin and Denis F. Latypoff.
+
+    *) Bugfix: regular expressions in location were always tested in 
+       case-sensitive mode; the bug had appeared in 0.8.25.
+
+    *) Bugfix: nginx cached a 304 response if there was the "If-None-Match" 
+       header line in a proxied request.
+       Thanks to Tim Dettrick and David Kostal.
+
+    *) Bugfix: nginx/Windows tried to delete a temporary file twice if the 
+       file should replace an already existent file.
+
+
+Changes with nginx 0.8.30                                        15 Dec 2009
+
+    *) Change: now the default buffer size of the 
+       "large_client_header_buffers" directive is 8K.
+       Thanks to Andrew Cholakian.
+
+    *) Feature: the conf/fastcgi.conf for simple FastCGI configurations.
+
+    *) Bugfix: nginx/Windows tried to rename a temporary file twice if the 
+       file should replace an already existent file.
+
+    *) Bugfix: of "double free or corruption" error issued if host could 
+       not be resolved; the bug had appeared in 0.8.22.
+       Thanks to Konstantin Svist.
+
+    *) Bugfix: in libatomic usage on some platforms.
+       Thanks to W-Mark Kubacki.
+
+
+Changes with nginx 0.8.29                                        30 Nov 2009
+
+    *) Change: now the "009" status code is written to an access log for 
+       proxied HTTP/0.9 responses.
+
+    *) Feature: the "addition_types", "charset_types", "gzip_types", 
+       "ssi_types", "sub_filter_types", and "xslt_types" directives support 
+       an "*" parameter.
+
+    *) Feature: GCC 4.1+ built-in atomic operations usage.
+       Thanks to W-Mark Kubacki.
+
+    *) Feature: the --with-libatomic[=DIR] option in the configure.
+       Thanks to W-Mark Kubacki.
+
+    *) Bugfix: listen unix domain socket had limited access rights.
+
+    *) Bugfix: cached HTTP/0.9 responses were handled incorrectly.
+
+    *) Bugfix: regular expression named captures given by "?P<...>" did not 
+       work in a "server_name" directive.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.8.28                                        23 Nov 2009
+
+    *) Bugfix: nginx could not be built with the --without-pcre parameter; 
+       the bug had appeared in 0.8.25.
+
+
+Changes with nginx 0.8.27                                        17 Nov 2009
+
+    *) Bugfix: regular expressions did not work in nginx/Windows; the bug 
+       had appeared in 0.8.25.
+
+
+Changes with nginx 0.8.26                                        16 Nov 2009
+
+    *) Bugfix: in captures usage in "rewrite" directive; the bug had 
+       appeared in 0.8.25.
+
+    *) Bugfix: nginx could not be built without the --with-debug option; 
+       the bug had appeared in 0.8.25.
+
+
+Changes with nginx 0.8.25                                        16 Nov 2009
+
+    *) Change: now no message is written in an error log if a variable is 
+       not found by $r->variable() method.
+
+    *) Feature: the ngx_http_degradation_module.
+
+    *) Feature: regular expression named captures.
+
+    *) Feature: now URI part is not required a "proxy_pass" directive if 
+       variables are used.
+
+    *) Feature: now the "msie_padding" directive works for Chrome too.
+
+    *) Bugfix: a segmentation fault occurred in a worker process on low 
+       memory condition; the bug had appeared in 0.8.18.
+
+    *) Bugfix: nginx sent gzipped responses to clients those do not support 
+       gzip, if "gzip_static on" and "gzip_vary off"; the bug had appeared 
+       in 0.8.16.
+
+
+Changes with nginx 0.8.24                                        11 Nov 2009
+
+    *) Bugfix: nginx always added "Content-Encoding: gzip" response header 
+       line in 304 responses sent by ngx_http_gzip_static_module.
+
+    *) Bugfix: nginx could not be built without the --with-debug option; 
+       the bug had appeared in 0.8.23.
+
+    *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive 
+       inherited incorrectly from previous level.
+
+    *) Bugfix: in resolving empty name.
+
+
+Changes with nginx 0.8.23                                        11 Nov 2009
+
+    *) Security: now SSL/TLS renegotiation is disabled.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: listen unix domain socket did not inherit while online 
+       upgrade.
+
+    *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive 
+       did not without yet another directive with any IP address.
+
+    *) Bugfix: segmentation fault and infinite looping in resolver.
+
+    *) Bugfix: in resolver.
+       Thanks to Artem Bokhan.
+
+
+Changes with nginx 0.8.22                                        03 Nov 2009
+
+    *) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind" 
+       directives.
+
+    *) Feature: the "access" and the "deny" directives support IPv6.
+
+    *) Feature: the "set_real_ip_from" directive supports IPv6 addresses in 
+       request headers.
+
+    *) Feature: the "unix:" parameter of the "set_real_ip_from" directive.
+
+    *) Bugfix: nginx did not delete unix domain socket after configuration 
+       testing.
+
+    *) Bugfix: nginx deleted unix domain socket while online upgrade.
+
+    *) Bugfix: the "!-x" operator did not work.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if 
+       limit_rate was used in HTTPS server.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault might occur in a worker process while 
+       $limit_rate logging.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if 
+       there was no "listen" directive in "server" block; the bug had 
+       appeared in 0.8.21.
+
+
+Changes with nginx 0.8.21                                        26 Oct 2009
+
+    *) Feature: now the "-V" switch shows TLS SNI support.
+
+    *) Feature: the "listen" directive of the HTTP module supports unix 
+       domain sockets.
+       Thanks to Hongli Lai.
+
+    *) Feature: the "default_server" parameter of the "listen" directive.
+
+    *) Feature: now a "default" parameter is not required to set listen 
+       socket options.
+
+    *) Bugfix: nginx did not support dates in 2038 year on 32-bit platforms;
+
+    *) Bugfix: socket leak; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.20                                        14 Oct 2009
+
+    *) Change: now default SSL ciphers are "HIGH:!ADH:!MD5".
+
+    *) Bugfix: the ngx_http_autoindex_module did not show the trailing 
+       slash in links to a directory; the bug had appeared in 0.7.15.
+
+    *) Bugfix: nginx did not close a log file set by the --error-log-path 
+       configuration option; the bug had appeared in 0.7.53.
+
+    *) Bugfix: nginx did not treat a comma as separator in the 
+       "Cache-Control" backend response header line.
+
+    *) Bugfix: nginx/Windows might not create temporary file, a cache file, 
+       or "proxy/fastcgi_store"d file if a worker had no enough access 
+       rights for top level directories.
+
+    *) Bugfix: the "Set-Cookie" and "P3P" FastCGI response header lines 
+       were not hidden while caching if no "fastcgi_hide_header" directives 
+       were used with any parameters.
+
+    *) Bugfix: nginx counted incorrectly disk cache size.
+
+
+Changes with nginx 0.8.19                                        06 Oct 2009
+
+    *) Change: now SSLv2 protocol is disabled by default.
+
+    *) Change: now default SSL ciphers are "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM".
+
+    *) Bugfix: a "limit_req" directive did not work; the bug had appeared 
+       in 0.8.18.
+
+
+Changes with nginx 0.8.18                                        06 Oct 2009
+
+    *) Feature: the "read_ahead" directive.
+
+    *) Feature: now several "perl_modules" directives may be used.
+
+    *) Feature: the "limit_req_log_level" and "limit_conn_log_level" 
+       directives.
+
+    *) Bugfix: now "limit_req" directive conforms to the leaky bucket 
+       algorithm.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx did not work on Linux/sparc.
+       Thanks to Marcus Ramberg.
+
+    *) Bugfix: nginx sent '\0' in a "Location" response header line on 
+       MKCOL request.
+       Thanks to Xie Zhenye.
+
+    *) Bugfix: zero status code was logged instead of 499 status code; the 
+       bug had appeared in 0.8.11.
+
+    *) Bugfix: socket leak; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.17                                        28 Sep 2009
+
+    *) Security: now "/../" are disabled in "Destination" request header 
+       line.
+
+    *) Change: now $host variable value is always low case.
+
+    *) Feature: the $ssl_session_id variable.
+
+    *) Bugfix: socket leak; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.16                                        22 Sep 2009
+
+    *) Feature: the "image_filter_transparency" directive.
+
+    *) Bugfix: "addition_types" directive was incorrectly named 
+       "addtion_types".
+
+    *) Bugfix: resolver cache poisoning.
+       Thanks to Matthew Dempsky.
+
+    *) Bugfix: memory leak in resolver.
+       Thanks to Matthew Dempsky.
+
+    *) Bugfix: invalid request line in $request variable was written in 
+       access_log only if error_log was set to "info" or "debug" level.
+
+    *) Bugfix: in PNG alpha-channel support in the 
+       ngx_http_image_filter_module.
+
+    *) Bugfix: nginx always added "Vary: Accept-Encoding" response header 
+       line, if both "gzip_static" and "gzip_vary" were on.
+
+    *) Bugfix: in UTF-8 encoding support by "try_files" directive in 
+       nginx/Windows.
+
+    *) Bugfix: in "post_action" directive usage; the bug had appeared in 
+       0.8.11.
+       Thanks to Igor Artemiev.
+
+
 Changes with nginx 0.8.15                                        14 Sep 2009
 
     *) Security: a segmentation fault might occur in worker process while 
--- a/CHANGES.ru	Tue Sep 15 03:43:40 2009 +0400
+++ b/CHANGES.ru	Thu Mar 11 21:27:17 2010 +0300
@@ -1,4 +1,394 @@
 
+Изменения в nginx 0.8.34                                          03.03.2010
+
+    *) Исправление: nginx не поддерживал все шифры, используемые в 
+       клиентских сертификатах.
+       Спасибо Иннокентию Еникееву.
+
+    *) Исправление: nginx неправильно кэшировал FastCGI-ответы, если перед 
+       ответом было много вывода в stderr.
+
+    *) Исправление: nginx не поддерживал HTTPS-рефереры.
+
+    *) Исправление: nginx/Windows мог не находить файлы, если путь в 
+       конфигурации был задан в другом регистре; ошибка появилась в 0.8.34.
+
+    *) Исправление: переменная $date_local выдавала неверное время, если 
+       использовался формат "%s".
+       Спасибо Максиму Дунину.
+
+    *) Исправление: если ssl_session_cache не был установлен или установлен 
+       в none, то при проверке клиентского сертификаты могла происходить 
+       ошибка "session id context uninitialized"; ошибка появилась в 0.7.1.
+
+    *) Исправление: geo-диапазон возвращал значение по умолчанию, если 
+       диапазон включал в себя одну и более сетей размером /16 и не 
+       начинался на границе сети размером /16.
+
+    *) Исправление: блок, используемый в параметре stub в SSI-директиве 
+       include, выводился с MIME-типом "text/plain".
+
+    *) Исправление: $r->sleep() не работал; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.33                                          01.02.2010
+
+    *) Безопасность: теперь nginx/Windows игнорирует пробелы в конце URI. 
+       Спасибо Dan Crowley, Core Security Technologies.
+
+    *) Безопасность: теперь nginx/Windows игнорирует короткие имена файлов. 
+       Спасибо Dan Crowley, Core Security Technologies.
+
+    *) Изменение: теперь keepalive соединения после запросов POST не 
+       запрещаются для MSIE 7.0+.
+       Спасибо Adam Lounds.
+
+    *) Изменение: теперь keepalive соединения запрещены для Safari.
+       Спасибо Joshua Sierles.
+
+    *) Исправление: если проксированный или FastCGI запрос внутренне 
+       перенаправлялся в другой проксированный или FastCGI location, то 
+       переменная $upstream_response_time могла иметь ненормально большое 
+       значение; ошибка появилась в 0.8.7.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault при 
+       отбрасывания тела запроса; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.32                                          11.01.2010
+
+    *) Исправление: ошибки при использовании кодировки UTF-8 в 
+       ngx_http_autoindex_module.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: именованные выделения в регулярных выражениях работали 
+       только для двух переменных.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: теперь в строке заголовка запроса "Host" используется 
+       имя "localhost", если в директиве auth_http указан unix domain 
+       сокет.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не поддерживал передачу chunk'ами для 201-ых 
+       ответов.
+       Спасибо Julian Reich.
+
+    *) Исправление: если директива "expires modified" выставляла дату в 
+       прошлом, то в строке заголовка ответа "Cache-Control" выдавалось 
+       отрицательное число.
+       Спасибо Алексею Капранову.
+
+
+Изменения в nginx 0.8.31                                          23.12.2009
+
+    *) Добавление: теперь директива error_page может перенаправлять ответы 
+       со статусом 301 и 302.
+
+    *) Добавление: переменные $geoip_city_continent_code, $geoip_latitude и 
+       $geoip_longitude.
+       Спасибо Arvind Sundararajan.
+
+    *) Добавление: модуль ngx_http_image_filter_module теперь всегда 
+       удаляет EXIF и другие данные, если они занимают больше 5% в 
+       JPEG-файле.
+
+    *) Исправление: nginx закрывал соединение при запросе закэшированного 
+       ответа с пустым телом.
+       Спасибо Piotr Sikora.
+
+    *) Исправление: nginx мог не собираться gcc 4.x при использовании 
+       оптимизации -O2 и выше.
+       Спасибо Максиму Дунину и Денису Латыпову.
+
+    *) Исправление: регулярные выражения в location всегда тестировались с 
+       учётом регистра; ошибка появилась в 0.8.25.
+
+    *) Исправление: nginx кэшировал 304 ответ, если в заголовке 
+       проксируемого запроса была строка "If-None-Match".
+       Спасибо Tim Dettrick и David Kostal.
+
+    *) Исправление: nginx/Windows пытался дважды удалить временный файл при 
+       перезаписи уже существующего файла.
+
+
+Изменения в nginx 0.8.30                                          15.12.2009
+
+    *) Изменение: теперь по умолчанию размер буфера директивы 
+       large_client_header_buffers равен 8K.
+       Спасибо Andrew Cholakian.
+
+    *) Добавление: файл conf/fastcgi.conf для простых конфигураций FastCGI.
+
+    *) Исправление: nginx/Windows пытался дважды переименовать временный 
+       файл при перезаписи уже существующего файла.
+
+    *) Исправление: ошибки double free or corruption, возникающей, если имя 
+       хоста не было найдено; ошибка появилась в 0.8.22.
+       Спасибо Константину Свисту.
+
+    *) Исправление: в использовании libatomic на некоторых платформах.
+       Спасибо W-Mark Kubacki.
+
+
+Изменения в nginx 0.8.29                                          30.11.2009
+
+    *) Изменение: теперь для проксируемых ответов HTTP/0.9 в лог пишется 
+       код ответа "009".
+
+    *) Добавление: директивы addition_types, charset_types, gzip_types, 
+       ssi_types, sub_filter_types и xslt_types поддерживают параметр "*".
+
+    *) Добавление: использование встроенных атомарных операций GCC 4.1+.
+       Спасибо W-Mark Kubacki.
+
+    *) Добавление: параметр --with-libatomic[=DIR] в configure.
+       Спасибо W-Mark Kubacki.
+
+    *) Исправление: listen unix domain сокет имели ограниченные права 
+       доступа.
+
+    *) Исправление: закэшированные ответы ответов HTTP/0.9 неправильно 
+       обрабатывались.
+
+    *) Исправление: именованные выделения в регулярных выражениях, заданные 
+       как "?P<...>", не работали в директиве server_name.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.8.28                                          23.11.2009
+
+    *) Исправление: nginx не собирался с параметром --without-pcre; ошибка 
+       появилась в 0.8.25.
+
+
+Изменения в nginx 0.8.27                                          17.11.2009
+
+    *) Исправление: регулярные выражения не работали в nginx/Windows; 
+       ошибка появилась в 0.8.25.
+
+
+Изменения в nginx 0.8.26                                          16.11.2009
+
+    *) Исправление: ошибки при использовании выделений в директиве rewrite; 
+       ошибка появилась в 0.8.25.
+
+    *) Исправление: nginx не собирался без параметра --with-debug; ошибка 
+       появилась в 0.8.25.
+
+
+Изменения в nginx 0.8.25                                          16.11.2009
+
+    *) Изменение: теперь в лог ошибок не пишется сообщение, если переменная 
+       не найдена с помощью метода $r->variable().
+
+    *) Добавление: модуль ngx_http_degradation_module.
+
+    *) Добавление: именованные выделения в регулярных выражениях.
+
+    *) Добавление: теперь при использовании переменных в директиве 
+       proxy_pass не требуется задавать URI.
+
+    *) Добавление: теперь директива msie_padding работает и для Chrome.
+
+    *) Исправление: в рабочем процессе происходил segmentation fault при 
+       недостатке памяти; ошибка появилась в 0.8.18.
+
+    *) Исправление: nginx передавал сжатые ответы клиентам, не 
+       поддерживающим сжатие, при настройках gzip_static on и gzip_vary 
+       off; ошибка появилась в 0.8.16.
+
+
+Изменения в nginx 0.8.24                                          11.11.2009
+
+    *) Исправление: nginx всегда добавлял строку "Content-Encoding: gzip" в 
+       заголовок 304-ых ответов модуля ngx_http_gzip_static_module.
+
+    *) Исправление: nginx не собирался без параметра --with-debug; ошибка 
+       появилась в 0.8.23.
+
+    *) Исправление: параметр "unix:" в директиве set_real_ip_from 
+       неправильно наследовался с предыдущего уровня.
+
+    *) Исправление: в resolver'е при определении пустого имени.
+
+
+Изменения в nginx 0.8.23                                          11.11.2009
+
+    *) Безопасность: теперь SSL/TLS renegotiation запрещён.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: listen unix domain сокет не наследовались во время 
+       обновления без перерыва.
+
+    *) Исправление: параметр "unix:" в директиве set_real_ip_from не 
+       работал без ещё одной директивы с любым IP-адресом.
+
+    *) Исправление: segmentation fault и зацикливания в resolver'е.
+
+    *) Исправление: в resolver'е.
+       Спасибо Артёму Бохану.
+
+
+Изменения в nginx 0.8.22                                          03.11.2009
+
+    *) Добавление: директивы proxy_bind, fastcgi_bind и memcached_bind.
+
+    *) Добавление: директивы access и deny поддерживают IPv6.
+
+    *) Добавление: директива set_real_ip_from поддерживает IPv6 адреса в 
+       заголовках запроса.
+
+    *) Добавление: параметр "unix:" в директиве set_real_ip_from.
+
+    *) Исправление: nginx не удалял unix domain сокет после тестирования 
+       конфигурации.
+
+    *) Исправление: nginx удалял unix domain сокет во время обновления без 
+       перерыва.
+
+    *) Исправление: оператор "!-x" не работал.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault при 
+       использовании limit_rate в HTTPS сервере.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: при записи в лог переменной $limit_rate в рабочем 
+       процессе происходил segmentation fault.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault, 
+       если внутри блока server не было директивы listen; ошибка появилась 
+       в 0.8.21.
+
+
+Изменения в nginx 0.8.21                                          26.10.2009
+
+    *) Добавление: теперь ключ -V показывает статус поддержки TLS SNI.
+
+    *) Добавление: директива listen модуля HTTP поддерживает unix domain 
+       сокеты.
+       Спасибо Hongli Lai.
+
+    *) Добавление: параметр "default_server" в директиве listen.
+
+    *) Добавление: теперь параметр "default" не обязателен для установки 
+       параметров listen-сокета.
+
+    *) Исправление: nginx не поддерживал даты в 2038 году на 32-битных 
+       платформах;
+
+    *) Исправление: утечки сокетов; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.20                                          14.10.2009
+
+    *) Изменение: теперь по умолчанию используются следующие шифры SSL: 
+       "HIGH:!ADH:!MD5".
+
+    *) Исправление: модуль ngx_http_autoindex_module не показывал последний 
+       слэш для линков на каталоги; ошибка появилась в 0.7.15.
+
+    *) Исправление: nginx не закрывал лог, заданный параметром конфигурации 
+       --error-log-path; ошибка появилась в 0.7.53.
+
+    *) Исправление: nginx не считал запятую разделителем в строке 
+       "Cache-Control" в строке заголовка бэкенда.
+
+    *) Исправление: nginx/Windows мог не создать временный файл, файл в 
+       кэше или файл с помощью директив proxy/fastcgi_store, если рабочий 
+       процесс не имел достаточно прав для работы с каталогами верхнего 
+       уровня.
+
+    *) Исправление: строки "Set-Cookie" и "P3P" в заголовке ответа 
+       FastCGI-сервера не скрывались при кэшировании, если не 
+       использовались директивы fastcgi_hide_header с любыми параметрами.
+
+    *) Исправление: nginx неверно считал размер кэша на диске.
+
+
+Изменения в nginx 0.8.19                                          06.10.2009
+
+    *) Изменение: теперь протокол SSLv2 по умолчанию запрещён.
+
+    *) Изменение: теперь по умолчанию используются следующие шифры SSL: 
+       "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM".
+
+    *) Исправление: директива limit_req не работала; ошибка появилась в 
+       0.8.18.
+
+
+Изменения в nginx 0.8.18                                          06.10.2009
+
+    *) Добавление: директива read_ahead.
+
+    *) Добавление: теперь можно использовать несколько директив 
+       perl_modules.
+
+    *) Добавление: директивы limit_req_log_level и limit_conn_log_level.
+
+    *) Исправление: Теперь директива limit_req соответствует алгоритму 
+       leaky bucket.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не работал на Linux/sparc.
+       Спасибо Marcus Ramberg.
+
+    *) Исправление: nginx слал символ '\0' в строке "Location" в заголовке 
+       в ответе на запрос MKCOL.
+       Спасибо Xie Zhenye.
+
+    *) Исправление: вместо кода ответа 499 в лог записывался код 0; ошибка 
+       появилась в 0.8.11.
+
+    *) Исправление: утечки сокетов; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.17                                          28.09.2009
+
+    *) Безопасность: теперь символы "/../" запрещены в строке "Destination" 
+       в заголовке запроса.
+
+    *) Изменение: теперь значение переменной $host всегда в нижнем регистре.
+
+    *) Добавление: переменная $ssl_session_id.
+
+    *) Исправление: утечки сокетов; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.16                                          22.09.2009
+
+    *) Добавление: директива image_filter_transparency.
+
+    *) Исправление: директива "addition_types" была неверно названа 
+       "addtion_types".
+
+    *) Исправление: порчи кэша resolver'а.
+       Спасибо Matthew Dempsky.
+
+    *) Исправление: утечки памяти в resolver'е.
+       Спасибо Matthew Dempsky.
+
+    *) Исправление: неверная строка запроса в переменной $request 
+       записывалась в access_log только при использовании error_log на 
+       уровне info или debug.
+
+    *) Исправление: в поддержке альфа-канала PNG в модуле 
+       ngx_http_image_filter_module.
+
+    *) Исправление: nginx всегда добавлял строку "Vary: Accept-Encoding" в 
+       заголовок ответа, если обе директивы gzip_static и gzip_vary были 
+       включены.
+
+    *) Исправление: в поддержке кодировки UTF-8 директивой try_files в 
+       nginx/Windows.
+
+    *) Исправление: ошибки при использовании post_action; ошибка появилась 
+       в 0.8.11.
+       Спасибо Игорю Артемьеву.
+
+
 Изменения в nginx 0.8.15                                          14.09.2009
 
     *) Безопасность: при обработке специально созданного запроса в рабочем 
@@ -125,7 +515,7 @@
        Спасибо Максиму Дунину.
 
     *) Исправление: в обработке строк "Last-Modified" и "Accept-Ranges" в 
-       заголовке ответа бэкенда; ошибка появилась в 0.7.44
+       заголовке ответа бэкенда; ошибка появилась в 0.7.44.
        Спасибо Максиму Дунину.
 
     *) Исправление: ошибки "[alert] zero size buf" при получении пустых 
--- a/LICENSE	Tue Sep 15 03:43:40 2009 +0400
+++ b/LICENSE	Thu Mar 11 21:27:17 2010 +0300
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002-2009 Igor Sysoev
+ * Copyright (C) 2002-2010 Igor Sysoev
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
--- a/auto/cc/conf	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/cc/conf	Thu Mar 11 21:27:17 2010 +0300
@@ -104,7 +104,7 @@
 fi
 
 CFLAGS="$CFLAGS $NGX_CC_OPT"
-
+NGX_TEST_LD_OPT="$NGX_LD_OPT"
 
 if [ "$NGX_PLATFORM" != win32 ]; then
 
@@ -125,6 +125,24 @@
         fi
     fi
 
+
+    ngx_feature="gcc builtin atomic operations"
+    ngx_feature_name=NGX_HAVE_GCC_ATOMIC
+    ngx_feature_run=yes
+    ngx_feature_incs=
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test="long  n = 0;
+                      if (!__sync_bool_compare_and_swap(&n, 0, 1))
+                          return 1;
+                      if (__sync_fetch_and_add(&n, 1) != 1)
+                          return 1;
+                      if (n != 2)
+                          return 1;
+                      __sync_synchronize();"
+    . auto/feature
+
+
     ngx_feature="gcc variadic macros"
     ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
     ngx_feature_run=yes
--- a/auto/cc/gcc	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/cc/gcc	Thu Mar 11 21:27:17 2010 +0300
@@ -51,8 +51,6 @@
 #NGX_GCC_OPT="-Os"
 NGX_GCC_OPT="-O"
 
-CFLAGS="$CFLAGS $NGX_GCC_OPT"
-
 #CFLAGS="$CFLAGS -fomit-frame-pointer"
 
 case $CPU in
@@ -90,7 +88,6 @@
         # build 32-bit UltraSparc binary
         CPU_OPT="-m32"
         CORE_LINK="$CORE_LINK -m32"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m32"
         NGX_CPU_CACHE_LINE=64
     ;;
 
@@ -98,7 +95,6 @@
         # build 64-bit UltraSparc binary
         CPU_OPT="-m64"
         CORE_LINK="$CORE_LINK -m64"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m64"
         NGX_CPU_CACHE_LINE=64
     ;;
 
@@ -108,12 +104,12 @@
         CPU_OPT="$CPU_OPT -falign-functions=32 -falign-labels=32"
         CPU_OPT="$CPU_OPT -falign-loops=32 -falign-jumps=32"
         CORE_LINK="$CORE_LINK -m64"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m64"
         NGX_CPU_CACHE_LINE=128
     ;;
 
 esac
 
+CC_AUX_FLAGS="$CC_AUX_FLAGS $CPU_OPT"
 
 case "$NGX_GCC_VER" in
     2.7*)
--- a/auto/feature	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/feature	Thu Mar 11 21:27:17 2010 +0300
@@ -39,7 +39,7 @@
 
 
 ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
+          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"
 
 ngx_feature_inc_path=
 
--- a/auto/install	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/install	Thu Mar 11 21:27:17 2010 +0300
@@ -101,6 +101,10 @@
 	cp conf/fastcgi_params \
 		'\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params.default'
 
+	test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf' \
+		|| cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX'
+	cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf.default'
+
 	test -f '\$(DESTDIR)$NGX_CONF_PATH' \
 		|| cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PATH'
 	cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX/nginx.conf.default'
@@ -144,19 +148,4 @@
 	test -f $NGX_PID_PATH.oldbin
 
 	kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
-
-upgrade1:
-	# upgrade 0.1.x to 0.2+
-
-	$NGX_SBIN_PATH -t
-
-	cp $NGX_PID_PATH $NGX_PID_PATH.oldbin
-
-	kill -USR2 \`cat $NGX_PID_PATH\`
-	sleep 1
-	test -f $NGX_PID_PATH.oldbin
-
-	cp $NGX_PID_PATH $NGX_PID_PATH.newbin
-
-	kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
 END
--- a/auto/lib/conf	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/lib/conf	Thu Mar 11 21:27:17 2010 +0300
@@ -70,6 +70,11 @@
 if [ $HTTP_GEOIP = YES ]; then
     . auto/lib/geoip/conf
 fi
+
 if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then
     . auto/lib/google-perftools/conf
 fi
+
+if [ $NGX_LIBATOMIC != NO ]; then
+    . auto/lib/libatomic/conf
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auto/lib/libatomic/conf	Thu Mar 11 21:27:17 2010 +0300
@@ -0,0 +1,42 @@
+
+# Copyright (C) Igor Sysoev
+
+
+if [ $NGX_LIBATOMIC != YES ]; then
+
+    have=NGX_HAVE_LIBATOMIC . auto/have
+    CORE_INCS="$CORE_INCS $NGX_LIBATOMIC/src"
+    LINK_DEPS="$LINK_DEPS $NGX_LIBATOMIC/src/libatomic_ops.a"
+    CORE_LIBS="$CORE_LIBS $NGX_LIBATOMIC/src/libatomic_ops.a"
+
+else
+
+    ngx_feature="atomic_ops library"
+    ngx_feature_name=NGX_HAVE_LIBATOMIC
+    ngx_feature_run=yes
+    ngx_feature_incs="#define AO_REQUIRE_CAS
+                      #include <atomic_ops.h>"
+    ngx_feature_path=
+    ngx_feature_libs="-latomic_ops"
+    ngx_feature_test="long  n = 0;
+                      if (!AO_compare_and_swap(&n, 0, 1))
+                          return 1;
+                      if (AO_fetch_and_add(&n, 1) != 1)
+                          return 1;
+                      if (n != 2)
+                          return 1;
+                      AO_nop();"
+    . auto/feature
+
+    if [ $ngx_found = yes ]; then
+        CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+    else
+
+cat << END
+
+$0: error: libatomic_ops library was not found.
+
+END
+        exit 1
+    fi
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auto/lib/libatomic/make	Thu Mar 11 21:27:17 2010 +0300
@@ -0,0 +1,13 @@
+
+# Copyright (C) Igor Sysoev
+
+
+    cat << END                                            >> $NGX_MAKEFILE
+
+$NGX_LIBATOMIC/src/libatomic_ops.a:	$NGX_LIBATOMIC/Makefile
+	cd $NGX_LIBATOMIC && make
+
+$NGX_LIBATOMIC/Makefile:	$NGX_MAKEFILE
+	cd $NGX_LIBATOMIC && ./configure
+
+END
--- a/auto/lib/make	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/lib/make	Thu Mar 11 21:27:17 2010 +0300
@@ -22,6 +22,10 @@
     . auto/lib/zlib/make
 fi
 
+if [ $NGX_LIBATOMIC != NO -a $NGX_LIBATOMIC != YES ]; then
+    . auto/lib/libatomic/make
+fi
+
 if [ $USE_PERL = YES ]; then
     . auto/lib/perl/make
 fi
--- a/auto/lib/openssl/conf	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/lib/openssl/conf	Thu Mar 11 21:27:17 2010 +0300
@@ -25,10 +25,10 @@
             have=NGX_OPENSSL . auto/have
             have=NGX_SSL . auto/have
 
-            CORE_INCS="$CORE_INCS $OPENSSL/openssl/include"
-            CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h"
-            CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libssl.a"
-            CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libcrypto.a"
+            CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include"
+            CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a"
             CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
         ;;
     esac
--- a/auto/lib/openssl/make	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/lib/openssl/make	Thu Mar 11 21:27:17 2010 +0300
@@ -46,13 +46,13 @@
         esac
 
         case $OPENSSL in
-            /*) ngx_prefix="$OPENSSL/openssl" ;;
-            *)  ngx_prefix="$PWD/$OPENSSL/openssl" ;;
+            /*) ngx_prefix="$OPENSSL/.openssl" ;;
+            *)  ngx_prefix="$PWD/$OPENSSL/.openssl" ;;
         esac
 
         cat << END                                            >> $NGX_MAKEFILE
 
-$OPENSSL/openssl/include/openssl/ssl.h:	$NGX_MAKEFILE
+$OPENSSL/.openssl/include/openssl/ssl.h:	$NGX_MAKEFILE
 	cd $OPENSSL \\
 	&& \$(MAKE) clean \\
 	&& ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\
--- a/auto/modules	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/modules	Thu Mar 11 21:27:17 2010 +0300
@@ -318,6 +318,11 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_SECURE_LINK_SRCS"
 fi
 
+if [ $HTTP_DEGRADATION = YES ]; then
+    HTTP_MODULES="$HTTP_MODULES $HTTP_DEGRADATION_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_DEGRADATION_SRCS"
+fi
+
 if [ $HTTP_FLV = YES ]; then
     HTTP_MODULES="$HTTP_MODULES $HTTP_FLV_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_FLV_SRCS"
--- a/auto/options	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/options	Thu Mar 11 21:27:17 2010 +0300
@@ -85,6 +85,7 @@
 HTTP_EMPTY_GIF=YES
 HTTP_BROWSER=YES
 HTTP_SECURE_LINK=NO
+HTTP_DEGRADATION=NO
 HTTP_FLV=NO
 HTTP_GZIP_STATIC=NO
 HTTP_UPSTREAM_IP_HASH=YES
@@ -131,6 +132,8 @@
 NGX_GOOGLE_PERFTOOLS=NO
 NGX_CPP_TEST=NO
 
+NGX_LIBATOMIC=NO
+
 NGX_CPU_CACHE_LINE=
 
 opt=
@@ -194,6 +197,7 @@
         --with-http_gzip_static_module)  HTTP_GZIP_STATIC=YES       ;;
         --with-http_random_index_module) HTTP_RANDOM_INDEX=YES      ;;
         --with-http_secure_link_module)  HTTP_SECURE_LINK=YES       ;;
+        --with-http_degradation_module)  HTTP_DEGRADATION=YES       ;;
 
         --without-http_charset_module)   HTTP_CHARSET=NO            ;;
         --without-http_gzip_module)      HTTP_GZIP=NO               ;;
@@ -264,6 +268,9 @@
         --with-zlib-opt=*)               ZLIB_OPT="$value"          ;;
         --with-zlib-asm=*)               ZLIB_ASM="$value"          ;;
 
+        --with-libatomic)                NGX_LIBATOMIC=YES          ;;
+        --with-libatomic=*)              NGX_LIBATOMIC="$value"     ;;
+
         --test-build-devpoll)            NGX_TEST_BUILD_DEVPOLL=YES ;;
         --test-build-eventport)          NGX_TEST_BUILD_EVENTPORT=YES ;;
         --test-build-epoll)              NGX_TEST_BUILD_EPOLL=YES   ;;
@@ -322,6 +329,7 @@
   --with-http_gzip_static_module     enable ngx_http_gzip_static_module
   --with-http_random_index_module    enable ngx_http_random_index_module
   --with-http_secure_link_module     enable ngx_http_secure_link_module
+  --with-http_degradation_module     enable ngx_http_degradation_module
   --with-http_stub_status_module     enable ngx_http_stub_status_module
 
   --without-http_charset_module      disable ngx_http_charset_module
@@ -397,6 +405,9 @@
                                      for specified CPU, the valid values:
                                      pentium, pentiumpro
 
+  --with-libatomic                   force libatomic_ops library usage
+  --with-libatomic=DIR               set path to libatomic_ops library sources
+
   --with-openssl=DIR                 set path to OpenSSL library sources
   --with-openssl-opt=OPTIONS         set additional options for OpenSSL building
 
--- a/auto/os/features	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/os/features	Thu Mar 11 21:27:17 2010 +0300
@@ -172,6 +172,26 @@
 fi
 
 
+ngx_feature="F_READAHEAD"
+ngx_feature_name="NGX_HAVE_F_READAHEAD"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="fcntl(0, F_READAHEAD, 1);"
+. auto/feature
+
+
+ngx_feature="posix_fadvise()"
+ngx_feature_name="NGX_HAVE_POSIX_FADVISE"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL);"
+. auto/feature
+
+
 ngx_feature="O_DIRECT"
 ngx_feature_name="NGX_HAVE_O_DIRECT"
 ngx_feature_run=no
--- a/auto/os/linux	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/os/linux	Thu Mar 11 21:27:17 2010 +0300
@@ -35,6 +35,12 @@
 fi
 
 
+# posix_fadvise64() had been implemented in 2.5.60
+
+if [ $version -lt 132412 ]; then
+    have=NGX_HAVE_POSIX_FADVISE . auto/nohave
+fi
+
 # epoll, EPOLLET version
 
 ngx_feature="epoll"
--- a/auto/sources	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/sources	Thu Mar 11 21:27:17 2010 +0300
@@ -439,6 +439,10 @@
 HTTP_SECURE_LINK_SRCS=src/http/modules/ngx_http_secure_link_module.c
 
 
+HTTP_DEGRADATION_MODULE=ngx_http_degradation_module
+HTTP_DEGRADATION_SRCS=src/http/modules/ngx_http_degradation_module.c
+
+
 HTTP_FLV_MODULE=ngx_http_flv_module
 HTTP_FLV_SRCS=src/http/modules/ngx_http_flv_module.c
 
--- a/auto/summary	Tue Sep 15 03:43:40 2009 +0400
+++ b/auto/summary	Thu Mar 11 21:27:17 2010 +0300
@@ -71,6 +71,12 @@
     *)     echo "  + using zlib library: $ZLIB" ;;
 esac
 
+case $NGX_LIBATOMIC in
+    YES)   echo "  + using system libatomic_ops library" ;;
+    NO)    ;; # not used
+    *)     echo "  + using libatomic_ops library: $NGX_LIBATOMIC" ;;
+esac
+
 echo
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conf/fastcgi.conf	Thu Mar 11 21:27:17 2010 +0300
@@ -0,0 +1,24 @@
+
+fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
+fastcgi_param  QUERY_STRING       $query_string;
+fastcgi_param  REQUEST_METHOD     $request_method;
+fastcgi_param  CONTENT_TYPE       $content_type;
+fastcgi_param  CONTENT_LENGTH     $content_length;
+
+fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
+fastcgi_param  REQUEST_URI        $request_uri;
+fastcgi_param  DOCUMENT_URI       $document_uri;
+fastcgi_param  DOCUMENT_ROOT      $document_root;
+fastcgi_param  SERVER_PROTOCOL    $server_protocol;
+
+fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
+fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
+
+fastcgi_param  REMOTE_ADDR        $remote_addr;
+fastcgi_param  REMOTE_PORT        $remote_port;
+fastcgi_param  SERVER_ADDR        $server_addr;
+fastcgi_param  SERVER_PORT        $server_port;
+fastcgi_param  SERVER_NAME        $server_name;
+
+# PHP only, required if PHP was built with --enable-force-cgi-redirect
+fastcgi_param  REDIRECT_STATUS    200;
--- a/conf/mime.types	Tue Sep 15 03:43:40 2009 +0400
+++ b/conf/mime.types	Thu Mar 11 21:27:17 2010 +0300
@@ -35,6 +35,7 @@
     application/vnd.wap.xhtml+xml         xhtml;
     application/vnd.google-earth.kml+xml  kml;
     application/vnd.google-earth.kmz      kmz;
+    application/x-7z-compressed           7z;
     application/x-cocoa                   cco;
     application/x-java-archive-diff       jardiff;
     application/x-java-jnlp-file          jnlp;
--- a/src/core/nginx.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/nginx.c	Thu Mar 11 21:27:17 2010 +0300
@@ -239,6 +239,13 @@
 #ifdef NGX_COMPILER
             ngx_log_stderr(0, "built by " NGX_COMPILER);
 #endif
+#if (NGX_SSL)
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+            ngx_log_stderr(0, "TLS SNI support enabled");
+#else
+            ngx_log_stderr(0, "TLS SNI support disabled");
+#endif
+#endif
             ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE);
         }
 
@@ -373,6 +380,13 @@
         }
     }
 
+    if (log->file->fd != ngx_stderr) {
+        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          ngx_close_file_n " built-in log failed");
+        }
+    }
+
     ngx_use_stderr = 0;
 
     if (ngx_process == NGX_PROCESS_SINGLE) {
--- a/src/core/nginx.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/nginx.h	Thu Mar 11 21:27:17 2010 +0300
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8015
-#define NGINX_VERSION      "0.8.15"
+#define nginx_version         8034
+#define NGINX_VERSION      "0.8.34"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_conf_file.c	Thu Mar 11 21:27:17 2010 +0300
@@ -261,7 +261,7 @@
         if (ngx_close_file(fd) == NGX_FILE_ERROR) {
             ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                           ngx_close_file_n " %s failed",
-                          cf->conf_file->file.name.data);
+                          filename->data);
             return NGX_CONF_ERROR;
         }
 
@@ -1006,7 +1006,7 @@
 
 void ngx_cdecl
 ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
-    char *fmt, ...)
+    const char *fmt, ...)
 {
     u_char   errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
     va_list  args;
--- a/src/core/ngx_conf_file.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_conf_file.h	Thu Mar 11 21:27:17 2010 +0300
@@ -322,7 +322,7 @@
     ngx_uint_t conf_prefix);
 ngx_open_file_t *ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name);
 void ngx_cdecl ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf,
-    ngx_err_t err, char *fmt, ...);
+    ngx_err_t err, const char *fmt, ...);
 
 
 char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
--- a/src/core/ngx_connection.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_connection.c	Thu Mar 11 21:27:17 2010 +0300
@@ -15,6 +15,7 @@
 ngx_listening_t *
 ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
 {
+    size_t            len;
     ngx_listening_t  *ls;
     struct sockaddr  *sa;
     u_char            text[NGX_SOCKADDR_STRLEN];
@@ -36,17 +37,8 @@
     ls->sockaddr = sa;
     ls->socklen = socklen;
 
-    ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
-
-    ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
-    if (ls->addr_text.data == NULL) {
-        return NULL;
-    }
-
-    ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
-
-    ls->fd = (ngx_socket_t) -1;
-    ls->type = SOCK_STREAM;
+    len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
+    ls->addr_text.len = len;
 
     switch (ls->sockaddr->sa_family) {
 #if (NGX_HAVE_INET6)
@@ -54,6 +46,12 @@
          ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
          break;
 #endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+    case AF_UNIX:
+         ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
+         len++;
+         break;
+#endif
     case AF_INET:
          ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
          break;
@@ -62,6 +60,16 @@
          break;
     }
 
+    ls->addr_text.data = ngx_pnalloc(cf->pool, len);
+    if (ls->addr_text.data == NULL) {
+        return NULL;
+    }
+
+    ngx_memcpy(ls->addr_text.data, text, len);
+
+    ls->fd = (ngx_socket_t) -1;
+    ls->type = SOCK_STREAM;
+
     ls->backlog = NGX_LISTEN_BACKLOG;
     ls->rcvbuf = -1;
     ls->sndbuf = -1;
@@ -109,11 +117,20 @@
 #if (NGX_HAVE_INET6)
         case AF_INET6:
              ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
+             len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
+             break;
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+        case AF_UNIX:
+             ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
+             len = NGX_UNIX_ADDRSTRLEN;
              break;
 #endif
 
         case AF_INET:
              ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
+             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
              break;
 
         default:
@@ -124,8 +141,6 @@
             continue;
         }
 
-        len = ls[i].addr_text_max_len + sizeof(":65535") - 1;
-
         ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
         if (ls[i].addr_text.data == NULL) {
             return NGX_ERROR;
@@ -357,6 +372,29 @@
                 continue;
             }
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+            if (ls[i].sockaddr->sa_family == AF_UNIX) {
+                mode_t   mode;
+                u_char  *name;
+
+                name = ls[i].addr_text.data + sizeof("unix:") - 1;
+                mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+
+                if (chmod((char *) name, mode) == -1) {
+                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                                  "chmod() \"%s\" failed", name);
+                }
+
+                if (ngx_test_config) {
+                    if (ngx_delete_file(name) == -1) {
+                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                                      ngx_delete_file_n " %s failed", name);
+                    }
+                }
+            }
+#endif
+
             if (listen(s, ls[i].backlog) == -1) {
                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
                               "listen() to %V, backlog %d failed",
@@ -604,6 +642,22 @@
                           ngx_close_socket_n " %V failed", &ls[i].addr_text);
         }
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+        if (ls[i].sockaddr->sa_family == AF_UNIX
+            && ngx_process <= NGX_PROCESS_MASTER
+            && ngx_new_binary == 0)
+        {
+            u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
+
+            if (ngx_delete_file(name) == -1) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
+                              ngx_delete_file_n " %s failed", name);
+            }
+        }
+
+#endif
+
         ls[i].fd = (ngx_socket_t) -1;
     }
 }
@@ -858,7 +912,6 @@
             return NGX_ERROR;
         }
 
-        c->local_socklen = len;
         ngx_memcpy(c->local_sockaddr, &sa, len);
     }
 
@@ -917,12 +970,8 @@
             level = NGX_LOG_INFO;
             break;
 
-        case NGX_ERROR_ERR:
+        default:
             level = NGX_LOG_ERR;
-            break;
-
-        default:
-            level = NGX_LOG_ALERT;
         }
 
     } else {
--- a/src/core/ngx_connection.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_connection.h	Thu Mar 11 21:27:17 2010 +0300
@@ -129,7 +129,6 @@
 #endif
 
     struct sockaddr    *local_sockaddr;
-    socklen_t           local_socklen;
 
     ngx_buf_t          *buffer;
 
--- a/src/core/ngx_core.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_core.h	Thu Mar 11 21:27:17 2010 +0300
@@ -83,7 +83,9 @@
 #define CRLF   "\x0d\x0a"
 
 
-#define ngx_abs(value)   (((value) >= 0) ? (value) : - (value))
+#define ngx_abs(value)       (((value) >= 0) ? (value) : - (value))
+#define ngx_max(val1, val2)  ((val1 < val2) ? (val2) : (val1))
+#define ngx_min(val1, val2)  ((val1 > val2) ? (val2) : (val1))
 
 void ngx_cpuinfo(void);
 
--- a/src/core/ngx_cycle.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_cycle.c	Thu Mar 11 21:27:17 2010 +0300
@@ -204,7 +204,7 @@
         return NULL;
     }
 
-    ngx_memcpy(cycle->hostname.data, hostname, cycle->hostname.len);
+    ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
 
 
     for (i = 0; ngx_modules[i]; i++) {
@@ -255,11 +255,13 @@
 #endif
 
     if (ngx_conf_param(&conf) != NGX_CONF_OK) {
+        environ = senv;
         ngx_destroy_cycle_pools(&conf);
         return NULL;
     }
 
     if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
+        environ = senv;
         ngx_destroy_cycle_pools(&conf);
         return NULL;
     }
@@ -280,6 +282,7 @@
             if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
                 == NGX_CONF_ERROR)
             {
+                environ = senv;
                 ngx_destroy_cycle_pools(&conf);
                 return NULL;
             }
@@ -698,8 +701,8 @@
     if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {
 
         /*
-         * perl_destruct() frees environ if it is not the same as it was at
-         * perl_construct() time.  So we have saved an previous cycle
+         * perl_destruct() frees environ, if it is not the same as it was at
+         * perl_construct() time, therefore we save the previous cycle
          * environment before ngx_conf_parse() where it will be changed.
          */
 
--- a/src/core/ngx_file.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_file.c	Thu Mar 11 21:27:17 2010 +0300
@@ -183,7 +183,15 @@
     u_char     *p, ch;
     ngx_err_t   err;
 
-    for (p = dir + 1; *p; p++) {
+    err = 0;
+
+#if (NGX_WIN32)
+    p = dir + 3;
+#else
+    p = dir + 1;
+#endif
+
+    for ( /* void */ ; *p; p++) {
         ch = *p;
 
         if (ch != '/') {
@@ -194,7 +202,14 @@
 
         if (ngx_create_dir(dir, access) == NGX_FILE_ERROR) {
             err = ngx_errno;
-            if (err != NGX_EEXIST) {
+
+            switch (err) {
+            case NGX_EEXIST:
+                err = 0;
+            case NGX_EACCES:
+                break;
+
+            default:
                 return err;
             }
         }
@@ -202,7 +217,7 @@
         *p = '/';
     }
 
-    return 0;
+    return err;
 }
 
 
@@ -576,16 +591,10 @@
 #if (NGX_WIN32)
 
     if (err == NGX_EEXIST) {
-        if (ngx_win32_rename_file(src, to, ext->log) == NGX_OK) {
+        err = ngx_win32_rename_file(src, to, ext->log);
 
-            if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
-                return NGX_OK;
-            }
-
-            err = ngx_errno;
-
-        } else {
-            err = 0;
+        if (err == 0) {
+            return NGX_OK;
         }
     }
 
--- a/src/core/ngx_inet.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_inet.c	Thu Mar 11 21:27:17 2010 +0300
@@ -8,9 +8,6 @@
 #include <ngx_core.h>
 
 
-#if (NGX_HAVE_INET6)
-static size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
-#endif
 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
@@ -59,6 +56,126 @@
 }
 
 
+#if (NGX_HAVE_INET6)
+
+ngx_int_t
+ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
+{
+    u_char      c, *zero, *digit, *s, *d;
+    size_t      len4;
+    ngx_uint_t  n, nibbles, word;
+
+    if (len == 0) {
+        return NGX_ERROR;
+    }
+
+    zero = NULL;
+    digit = NULL;
+    len4 = 0;
+    nibbles = 0;
+    word = 0;
+    n = 8;
+
+    if (p[0] == ':') {
+        p++;
+        len--;
+    }
+
+    for (/* void */; len; len--) {
+        c = *p++;
+
+        if (c == ':') {
+            if (nibbles) {
+                digit = p;
+                len4 = len;
+                *addr++ = (u_char) (word >> 8);
+                *addr++ = (u_char) (word & 0xff);
+
+                if (--n) {
+                    nibbles = 0;
+                    word = 0;
+                    continue;
+                }
+
+            } else {
+                if (zero == NULL) {
+                    digit = p;
+                    len4 = len;
+                    zero = addr;
+                    continue;
+                }
+            }
+
+            return NGX_ERROR;
+        }
+
+        if (c == '.' && nibbles) {
+            if (n < 2) {
+                return NGX_ERROR;
+            }
+
+            word = ngx_inet_addr(digit, len4 - 1);
+            if (word == INADDR_NONE) {
+                return NGX_ERROR;
+            }
+
+            word = ntohl(word);
+            *addr++ = (u_char) ((word >> 24) & 0xff);
+            *addr++ = (u_char) ((word >> 16) & 0xff);
+            n--;
+            break;
+        }
+
+        if (++nibbles > 4) {
+            return NGX_ERROR;
+        }
+
+        if (c >= '0' && c <= '9') {
+            word = word * 16 + (c - '0');
+            continue;
+        }
+
+        c |= 0x20;
+
+        if (c >= 'a' && c <= 'f') {
+            word = word * 16 + (c - 'a') + 10;
+            continue;
+        }
+
+        return NGX_ERROR;
+    }
+
+    if (nibbles == 0 && zero == NULL) {
+        return NGX_ERROR;
+    }
+
+    *addr++ = (u_char) (word >> 8);
+    *addr++ = (u_char) (word & 0xff);
+
+    if (--n) {
+        if (zero) {
+            n *= 2;
+            s = addr - 1;
+            d = s + n;
+            while (s >= zero) {
+                *d-- = *s--;
+            }
+            ngx_memzero(zero, n);
+            return NGX_OK;
+        }
+
+    } else {
+        if (zero == NULL) {
+            return NGX_OK;
+        }
+    }
+
+    return NGX_ERROR;
+}
+
+#endif
+
+
 size_t
 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
 {
@@ -68,6 +185,9 @@
     size_t                n;
     struct sockaddr_in6  *sin6;
 #endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+    struct sockaddr_un   *saun;
+#endif
 
     switch (sa->sa_family) {
 
@@ -98,7 +218,7 @@
             text[n++] = '[';
         }
 
-        n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len);
+        n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
 
         if (port) {
             n = ngx_sprintf(&text[1 + n], "]:%d",
@@ -108,6 +228,17 @@
         return n;
 #endif
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+    case AF_UNIX:
+        saun = (struct sockaddr_un *) sa;
+
+        /* we do not include trailing zero in address length */
+
+        return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
+
+#endif
+
     default:
         return 0;
     }
@@ -144,7 +275,7 @@
 
 #if (NGX_HAVE_INET6)
 
-static size_t
+size_t
 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
 {
     u_char      *dst;
@@ -223,31 +354,47 @@
 #endif
 
 
-/* AF_INET only */
-
 ngx_int_t
 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
 {
-    u_char     *addr, *mask, *last;
-    ngx_int_t   shift;
+    u_char      *addr, *mask, *last;
+    size_t       len;
+    ngx_int_t    shift;
+#if (NGX_HAVE_INET6)
+    ngx_int_t    rc;
+    ngx_uint_t   s, i;
+#endif
 
     addr = text->data;
     last = addr + text->len;
 
     mask = ngx_strlchr(addr, last, '/');
+    len = (mask ? mask : last) - addr;
 
-    cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
+    cidr->u.in.addr = ngx_inet_addr(addr, len);
+
+    if (cidr->u.in.addr != INADDR_NONE) {
+        cidr->family = AF_INET;
+
+        if (mask == NULL) {
+            cidr->u.in.mask = 0xffffffff;
+            return NGX_OK;
+        }
 
-    if (cidr->u.in.addr == INADDR_NONE) {
+#if (NGX_HAVE_INET6)
+    } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
+        cidr->family = AF_INET6;
+
+        if (mask == NULL) {
+            ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
+            return NGX_OK;
+        }
+
+#endif
+    } else {
         return NGX_ERROR;
     }
 
-    if (mask == NULL) {
-        cidr->family = AF_INET;
-        cidr->u.in.mask = 0xffffffff;
-        return NGX_OK;
-    }
-
     mask++;
 
     shift = ngx_atoi(mask, last - mask);
@@ -255,30 +402,108 @@
         return NGX_ERROR;
     }
 
-    cidr->family = AF_INET;
+    switch (cidr->family) {
 
-    if (shift == 0) {
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        addr = cidr->u.in6.addr.s6_addr;
+        mask = cidr->u.in6.mask.s6_addr;
+        rc = NGX_OK;
+
+        for (i = 0; i < 16; i++) {
+
+            s = (shift > 8) ? 8 : shift;
+            shift -= s;
+
+            mask[i] = (u_char) (0 - (1 << (8 - s)));
 
-        /* the x86 compilers use the shl instruction that shifts by modulo 32 */
+            if (addr[i] != (addr[i] & mask[i])) {
+                rc = NGX_DONE;
+                addr[i] &= mask[i];
+            }
+        }
+
+        return rc;
+#endif
 
-        cidr->u.in.mask = 0;
+    default: /* AF_INET */
+
+        if (shift) {
+            cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
 
-        if (cidr->u.in.addr == 0) {
+        } else {
+            /* x86 compilers use a shl instruction that shifts by modulo 32 */
+            cidr->u.in.mask = 0;
+        }
+
+        if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
             return NGX_OK;
         }
 
+        cidr->u.in.addr &= cidr->u.in.mask;
+
         return NGX_DONE;
     }
+}
+
+
+ngx_int_t
+ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
+{
+    in_addr_t             inaddr;
+    ngx_uint_t            family;
+    struct sockaddr_in   *sin;
+#if (NGX_HAVE_INET6)
+    struct in6_addr       inaddr6;
+    struct sockaddr_in6  *sin6;
+
+    /*
+     * prevent MSVC8 waring:
+     *    potentially uninitialized local variable 'inaddr6' used
+     */
+    ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
+#endif
+
+    inaddr = ngx_inet_addr(text, len);
+
+    if (inaddr != INADDR_NONE) {
+        family = AF_INET;
+        len = sizeof(struct sockaddr_in);
+
+#if (NGX_HAVE_INET6)
+    } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
+        family = AF_INET6;
+        len = sizeof(struct sockaddr_in6);
+
+#endif
+    } else {
+        return NGX_DECLINED;
+    }
 
-    cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
-
-    if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
-        return NGX_OK;
+    addr->sockaddr = ngx_pcalloc(pool, len);
+    if (addr->sockaddr == NULL) {
+        return NGX_ERROR;
     }
 
-    cidr->u.in.addr &= cidr->u.in.mask;
+    addr->sockaddr->sa_family = (u_char) family;
+    addr->socklen = len;
+
+    switch (family) {
 
-    return NGX_DONE;
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) addr->sockaddr;
+        ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
+        break;
+#endif
+
+    default: /* AF_INET */
+        sin = (struct sockaddr_in *) addr->sockaddr;
+        sin->sin_addr.s_addr = inaddr;
+        break;
+    }
+
+    return NGX_OK;
 }
 
 
@@ -351,7 +576,7 @@
     saun->sun_family = AF_UNIX;
     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
 
-    u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
+    u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
     if (u->addrs == NULL) {
         return NGX_ERROR;
     }
@@ -509,22 +734,22 @@
         return NGX_OK;
     }
 
-    if (len++) {
-
-        p = ngx_alloc(len, pool->log);
-        if (p == NULL) {
-            return NGX_ERROR;
-        }
-
-        (void) ngx_cpystrn(p, host, len);
-
-        sin->sin_addr.s_addr = inet_addr((const char *) p);
+    if (len) {
+        sin->sin_addr.s_addr = ngx_inet_addr(host, len);
 
         if (sin->sin_addr.s_addr == INADDR_NONE) {
+            p = ngx_alloc(++len, pool->log);
+            if (p == NULL) {
+                return NGX_ERROR;
+            }
+
+            (void) ngx_cpystrn(p, host, len);
+
             h = gethostbyname((const char *) p);
 
+            ngx_free(p);
+
             if (h == NULL || h->h_addr_list[0] == NULL) {
-                ngx_free(p);
                 u->err = "host not found";
                 return NGX_ERROR;
             }
@@ -536,8 +761,6 @@
             u->wildcard = 1;
         }
 
-        ngx_free(p);
-
     } else {
         sin->sin_addr.s_addr = INADDR_ANY;
         u->wildcard = 1;
@@ -564,7 +787,6 @@
 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
 {
 #if (NGX_HAVE_INET6)
-    int                   rc;
     u_char               *p, *host, *port, *last, *uri;
     size_t                len;
     ngx_int_t             n;
@@ -636,35 +858,10 @@
         return NGX_ERROR;
     }
 
-    u->host.len = len++;
+    u->host.len = len;
     u->host.data = host;
 
-    p = ngx_alloc(len, pool->log);
-    if (p == NULL) {
-        return NGX_ERROR;
-    }
-
-    (void) ngx_cpystrn(p, host, len);
-
-#if (NGX_WIN32)
-
-    rc = WSAStringToAddress((char *) p, AF_INET6, NULL,
-                            (SOCKADDR *) sin6, &u->socklen);
-    rc = !rc;
-
-    if (u->port) {
-        sin6->sin6_port = htons(u->port);
-    }
-
-#else
-
-    rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
-
-#endif
-
-    ngx_free(p);
-
-    if (rc == 0) {
+    if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
         u->err = "invalid IPv6 address";
         return NGX_ERROR;
     }
@@ -707,20 +904,20 @@
     struct hostent      *h;
     struct sockaddr_in  *sin;
 
-    host = ngx_alloc(u->host.len + 1, pool->log);
-    if (host == NULL) {
-        return NGX_ERROR;
-    }
-
-    (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
-
     /* AF_INET only */
 
     port = htons(u->port);
 
-    in_addr = inet_addr((char *) host);
+    in_addr = ngx_inet_addr(u->host.data, u->host.len);
 
     if (in_addr == INADDR_NONE) {
+        host = ngx_alloc(u->host.len + 1, pool->log);
+        if (host == NULL) {
+            return NGX_ERROR;
+        }
+
+        (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
+
         h = gethostbyname((char *) host);
 
         ngx_free(host);
@@ -739,7 +936,7 @@
 
         /* MP: ngx_shared_palloc() */
 
-        u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
@@ -775,11 +972,9 @@
 
     } else {
 
-        ngx_free(host);
-
         /* MP: ngx_shared_palloc() */
 
-        u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
--- a/src/core/ngx_inet.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_inet.h	Thu Mar 11 21:27:17 2010 +0300
@@ -12,21 +12,26 @@
 #include <ngx_core.h>
 
 
-#define NGX_INET_ADDRSTRLEN   (sizeof("255.255.255.255") - 1)
-#define NGX_INET6_ADDRSTRLEN                                                 \
-    (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1)
-
-#define NGX_SOCKADDR_STRLEN   (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
-
-
 /*
- * TODO: autoconfigure NGX_SOCKADDRLEN as
+ * TODO: autoconfigure NGX_SOCKADDRLEN and NGX_SOCKADDR_STRLEN as
  *       sizeof(struct sockaddr_storage)
  *       sizeof(struct sockaddr_un)
  *       sizeof(struct sockaddr_in6)
  *       sizeof(struct sockaddr_in)
  */
 
+#define NGX_INET_ADDRSTRLEN   (sizeof("255.255.255.255") - 1)
+#define NGX_INET6_ADDRSTRLEN                                                 \
+    (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1)
+#define NGX_UNIX_ADDRSTRLEN                                                  \
+    (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path))
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+#define NGX_SOCKADDR_STRLEN   (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN)
+#else
+#define NGX_SOCKADDR_STRLEN   (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
+#endif
+
 #if (NGX_HAVE_UNIX_DOMAIN)
 #define NGX_SOCKADDRLEN       sizeof(struct sockaddr_un)
 #else
@@ -65,7 +70,7 @@
     struct sockaddr          *sockaddr;
     socklen_t                 socklen;
     ngx_str_t                 name;
-} ngx_peer_addr_t;
+} ngx_addr_t;
 
 
 typedef struct {
@@ -89,7 +94,7 @@
     socklen_t                 socklen;
     u_char                    sockaddr[NGX_SOCKADDRLEN];
 
-    ngx_peer_addr_t          *addrs;
+    ngx_addr_t               *addrs;
     ngx_uint_t                naddrs;
 
     char                     *err;
@@ -97,13 +102,18 @@
 
 
 in_addr_t ngx_inet_addr(u_char *text, size_t len);
+#if (NGX_HAVE_INET6)
+ngx_int_t ngx_inet6_addr(u_char *p, size_t len, u_char *addr);
+size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
+#endif
 size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
     ngx_uint_t port);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
 ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
+ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
+    size_t len);
 ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
 ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
 
 
-
 #endif /* _NGX_INET_H_INCLUDED_ */
--- a/src/core/ngx_open_file_cache.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_open_file_cache.c	Thu Mar 11 21:27:17 2010 +0300
@@ -17,6 +17,9 @@
  */
 
 
+#define NGX_MIN_READ_AHEAD  (128 * 1024)
+
+
 static void ngx_open_file_cache_cleanup(void *data);
 static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of,
     ngx_log_t *log);
@@ -524,8 +527,15 @@
     } else {
         of->fd = fd;
 
+        if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) {
+            if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) {
+                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                              ngx_read_ahead_n " \"%s\" failed", name);
+            }
+        }
+
         if (of->directio <= ngx_file_size(&fi)) {
-            if (ngx_directio_on(fd) == -1) {
+            if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                               ngx_directio_on_n " \"%s\" failed", name);
 
--- a/src/core/ngx_open_file_cache.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_open_file_cache.h	Thu Mar 11 21:27:17 2010 +0300
@@ -21,6 +21,7 @@
     time_t                   mtime;
     off_t                    size;
     off_t                    directio;
+    size_t                   read_ahead;
 
     ngx_err_t                err;
     char                    *failed;
--- a/src/core/ngx_output_chain.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_output_chain.c	Thu Mar 11 21:27:17 2010 +0300
@@ -514,7 +514,7 @@
 #if (NGX_HAVE_ALIGNED_DIRECTIO)
 
         if (ctx->unaligned) {
-            if (ngx_directio_off(src->file->fd) == -1) {
+            if (ngx_directio_off(src->file->fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
                               ngx_directio_off_n " \"%s\" failed",
                               src->file->name.data);
@@ -550,7 +550,7 @@
 
             err = ngx_errno;
 
-            if (ngx_directio_on(src->file->fd) == -1) {
+            if (ngx_directio_on(src->file->fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
                               ngx_directio_on_n " \"%s\" failed",
                               src->file->name.data);
@@ -571,9 +571,7 @@
             ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
                           ngx_read_file_n " read only %z of %O from \"%s\"",
                           n, size, src->file->name.data);
-            if (n == 0) {
-                return NGX_ERROR;
-            }
+            return NGX_ERROR;
         }
 
         dst->last += n;
--- a/src/core/ngx_palloc.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_palloc.c	Thu Mar 11 21:27:17 2010 +0300
@@ -17,7 +17,7 @@
 {
     ngx_pool_t  *p;
 
-    p = ngx_alloc(size, log);
+    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
     if (p == NULL) {
         return NULL;
     }
@@ -181,7 +181,7 @@
 
     psize = (size_t) (pool->d.end - (u_char *) pool);
 
-    m = ngx_alloc(psize, pool->log);
+    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
     if (m == NULL) {
         return NULL;
     }
--- a/src/core/ngx_palloc.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_palloc.h	Thu Mar 11 21:27:17 2010 +0300
@@ -19,8 +19,11 @@
 #define NGX_MAX_ALLOC_FROM_POOL  (ngx_pagesize - 1)
 
 #define NGX_DEFAULT_POOL_SIZE    (16 * 1024)
+
+#define NGX_POOL_ALIGNMENT       16
 #define NGX_MIN_POOL_SIZE                                                     \
-    (sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t))
+    ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)),            \
+              NGX_POOL_ALIGNMENT)
 
 
 typedef void (*ngx_pool_cleanup_pt)(void *data);
--- a/src/core/ngx_regex.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_regex.c	Thu Mar 11 21:27:17 2010 +0300
@@ -23,61 +23,116 @@
 }
 
 
-ngx_regex_t *
-ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, ngx_pool_t *pool,
-    ngx_str_t *err)
+static ngx_inline void
+ngx_regex_malloc_init(ngx_pool_t *pool)
 {
-    int              erroff;
-    const char      *errstr;
-    ngx_regex_t     *re;
 #if (NGX_THREADS)
     ngx_core_tls_t  *tls;
 
-#if (NGX_SUPPRESS_WARN)
-    tls = NULL;
-#endif
-
     if (ngx_threaded) {
         tls = ngx_thread_get_tls(ngx_core_tls_key);
         tls->pool = pool;
-    } else {
-        ngx_pcre_pool = pool;
+        return;
     }
 
-#else
+#endif
 
     ngx_pcre_pool = pool;
+}
+
+
+static ngx_inline void
+ngx_regex_malloc_done(void)
+{
+#if (NGX_THREADS)
+    ngx_core_tls_t  *tls;
+
+    if (ngx_threaded) {
+        tls = ngx_thread_get_tls(ngx_core_tls_key);
+        tls->pool = NULL;
+        return;
+    }
 
 #endif
 
-    re = pcre_compile((const char *) pattern->data, (int) options,
+    ngx_pcre_pool = NULL;
+}
+
+
+ngx_int_t
+ngx_regex_compile(ngx_regex_compile_t *rc)
+{
+    int           n, erroff;
+    char         *p;
+    const char   *errstr;
+    ngx_regex_t  *re;
+
+    ngx_regex_malloc_init(rc->pool);
+
+    re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
                       &errstr, &erroff, NULL);
 
+    /* ensure that there is no current pool */
+    ngx_regex_malloc_done();
+
     if (re == NULL) {
-       if ((size_t) erroff == pattern->len) {
-           ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\"%Z",
-                        errstr, pattern->data);
+        if ((size_t) erroff == rc->pattern.len) {
+           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                              "pcre_compile() failed: %s in \"%V\"",
+                               errstr, &rc->pattern)
+                      - rc->err.data;
+
         } else {
-           ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z",
-                        errstr, pattern->data, pattern->data + erroff);
+           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                              "pcre_compile() failed: %s in \"%V\" at \"%s\"",
+                               errstr, &rc->pattern, rc->pattern.data + erroff)
+                      - rc->err.data;
         }
+
+        return NGX_ERROR;
+    }
+
+    rc->regex = re;
+
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
+        goto failed;
+    }
+
+    if (rc->captures == 0) {
+        return NGX_OK;
     }
 
-    /* ensure that there is no current pool */
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
+        goto failed;
+    }
+
+    if (rc->named_captures == 0) {
+        return NGX_OK;
+    }
 
-#if (NGX_THREADS)
-    if (ngx_threaded) {
-        tls->pool = NULL;
-    } else {
-        ngx_pcre_pool = NULL;
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
+        goto failed;
     }
-#else
-    ngx_pcre_pool = NULL;
-#endif
+
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
+        goto failed;
+    }
 
-    return re;
+    return NGX_OK;
+
+failed:
+
+    rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
+                  - rc->err.data;
+    return NGX_OK;
 }
 
 
@@ -99,22 +154,6 @@
 
 
 ngx_int_t
-ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size)
-{
-    int  rc;
-
-    rc = pcre_exec(re, NULL, (const char *) s->data, s->len, 0, 0,
-                   captures, size);
-
-    if (rc == -1) {
-        return NGX_REGEX_NO_MATCHED;
-    }
-
-    return rc;
-}
-
-
-ngx_int_t
 ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
 {
     ngx_int_t         n;
@@ -133,7 +172,7 @@
 
         if (n < 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
-                          ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"",
+                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
                           n, s, re[i].name);
             return NGX_ERROR;
         }
@@ -157,11 +196,15 @@
     if (ngx_threaded) {
         tls = ngx_thread_get_tls(ngx_core_tls_key);
         pool = tls->pool;
+
     } else {
         pool = ngx_pcre_pool;
     }
+
 #else
+
     pool = ngx_pcre_pool;
+
 #endif
 
     if (pool) {
--- a/src/core/ngx_regex.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_regex.h	Thu Mar 11 21:27:17 2010 +0300
@@ -14,29 +14,42 @@
 #include <pcre.h>
 
 
-#define NGX_REGEX_NO_MATCHED  -1000
+#define NGX_REGEX_NO_MATCHED  PCRE_ERROR_NOMATCH   /* -1 */
 
 #define NGX_REGEX_CASELESS    PCRE_CASELESS
 
 typedef pcre  ngx_regex_t;
 
+
 typedef struct {
-    ngx_regex_t   *regex;
-    u_char        *name;
+    ngx_str_t     pattern;
+    ngx_pool_t   *pool;
+    ngx_int_t     options;
+
+    ngx_regex_t  *regex;
+    int           captures;
+    int           named_captures;
+    int           name_size;
+    u_char       *names;
+    ngx_str_t     err;
+} ngx_regex_compile_t;
+
+
+typedef struct {
+    ngx_regex_t  *regex;
+    u_char       *name;
 } ngx_regex_elt_t;
 
 
 void ngx_regex_init(void);
-ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
-    ngx_pool_t *pool, ngx_str_t *err);
-ngx_int_t ngx_regex_capture_count(ngx_regex_t *re);
-ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
-    ngx_int_t size);
+ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
+
+#define ngx_regex_exec(re, s, captures, size)                                \
+    pcre_exec(re, NULL, (const char *) (s)->data, (s)->len, 0, 0,            \
+              captures, size)
+#define ngx_regex_exec_n      "pcre_exec()"
+
 ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log);
 
 
-#define ngx_regex_exec_n           "pcre_exec()"
-#define ngx_regex_capture_count_n  "pcre_fullinfo()"
-
-
 #endif /* _NGX_REGEX_H_INCLUDED_ */
--- a/src/core/ngx_resolver.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_resolver.c	Thu Mar 11 21:27:17 2010 +0300
@@ -87,12 +87,11 @@
 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
-
-
-/* STUB: ngx_peer_addr_t * */
+static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
+
 
 ngx_resolver_t *
-ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr)
+ngx_resolver_create(ngx_conf_t *cf, ngx_addr_t *addr)
 {
     ngx_resolver_t        *r;
     ngx_pool_cleanup_t    *cln;
@@ -152,7 +151,11 @@
         uc->sockaddr = addr->sockaddr;
         uc->socklen = addr->socklen;
         uc->server = addr->name;
-        uc->log = &cf->cycle->new_log;
+
+        uc->log = cf->cycle->new_log;
+        uc->log.handler = ngx_resolver_log_error;
+        uc->log.data = uc;
+        uc->log.action = "resolving";
     }
 
     return r;
@@ -464,6 +467,7 @@
 
             ctx->next = rn->waiting;
             rn->waiting = ctx;
+            ctx->state = NGX_AGAIN;
 
             return NGX_AGAIN;
         }
@@ -625,6 +629,7 @@
 
             ctx->next = rn->waiting;
             rn->waiting = ctx;
+            ctx->state = NGX_AGAIN;
 
             /* unlock addr mutex */
 
@@ -840,7 +845,7 @@
     }
 
     if ((size_t) n != (size_t) rn->qlen) {
-        ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete");
+        ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
         return NGX_ERROR;
     }
 
@@ -1149,6 +1154,8 @@
         goto failed;
     }
 
+    ngx_resolver_free(r, name.data);
+
     if (code == 0 && nan == 0) {
         code = 3; /* NXDOMAIN */
     }
@@ -1400,6 +1407,8 @@
 
     /* unlock name mutex */
 
+    ngx_resolver_free(r, name.data);
+
     return;
 }
 
@@ -1595,7 +1604,6 @@
 ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
 {
     ngx_int_t             rc;
-    size_t                len;
     ngx_rbtree_node_t    *node, *sentinel;
     ngx_resolver_node_t  *rn;
 
@@ -1619,9 +1627,7 @@
         do {
             rn = (ngx_resolver_node_t *) node;
 
-            len = (name->len > (size_t) rn->nlen) ? rn->nlen : name->len;
-
-            rc = ngx_strncmp(name->data, rn->name, len);
+            rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
 
             if (rc == 0) {
                 return rn;
@@ -1675,7 +1681,6 @@
 ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
 {
-    size_t                 len;
     ngx_rbtree_node_t    **p;
     ngx_resolver_node_t   *rn, *rn_temp;
 
@@ -1694,10 +1699,8 @@
             rn = (ngx_resolver_node_t *) node;
             rn_temp = (ngx_resolver_node_t *) temp;
 
-            len = (rn->nlen > rn_temp->nlen) ? rn_temp->nlen : rn->nlen;
-
-            p = (ngx_strncmp(rn->name, rn_temp->name, len) < 0)
-                    ? &temp->left : &temp->right;
+            p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen)
+                 < 0) ? &temp->left : &temp->right;
         }
 
         if (*p == sentinel) {
@@ -1719,15 +1722,16 @@
 ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
 {
     u_char                *p, *s;
-    size_t                 len;
+    size_t                 len, nlen;
     ngx_uint_t             ident;
     ngx_resolver_qs_t     *qs;
     ngx_resolver_query_t  *query;
 
-    len = sizeof(ngx_resolver_query_t)
-          + 1 + ctx->name.len + 1 + sizeof(ngx_resolver_qs_t);
-
-    p = ngx_resolver_calloc(ctx->resolver, len);
+    nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;
+
+    len = sizeof(ngx_resolver_query_t) + nlen + sizeof(ngx_resolver_qs_t);
+
+    p = ngx_resolver_alloc(ctx->resolver, len);
     if (p == NULL) {
         return NGX_ERROR;
     }
@@ -1754,7 +1758,7 @@
     query->nns_hi = 0; query->nns_lo = 0;
     query->nar_hi = 0; query->nar_lo = 0;
 
-    p += sizeof(ngx_resolver_query_t) + 1 + ctx->name.len + 1;
+    p += sizeof(ngx_resolver_query_t) + nlen;
 
     qs = (ngx_resolver_qs_t *) p;
 
@@ -1808,7 +1812,7 @@
           + sizeof(".255.255.255.255.in-addr.arpa.") - 1
           + sizeof(ngx_resolver_qs_t);
 
-    p = ngx_resolver_calloc(ctx->resolver, len);
+    p = ngx_resolver_alloc(ctx->resolver, len);
     if (p == NULL) {
         return NGX_ERROR;
     }
@@ -1902,6 +1906,12 @@
         return NGX_OK;
     }
 
+    if (len == -1) {
+        name->len = 0;
+        name->data = NULL;
+        return NGX_OK;
+    }
+
     dst = ngx_resolver_alloc(r, len);
     if (dst == NULL) {
         return NGX_ERROR;
@@ -2066,6 +2076,29 @@
 }
 
 
+static u_char *
+ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
+{
+    u_char                *p;
+    ngx_udp_connection_t  *uc;
+
+    p = buf;
+
+    if (log->action) {
+        p = ngx_snprintf(buf, len, " while %s", log->action);
+        len -= p - buf;
+    }
+
+    uc = log->data;
+
+    if (uc) {
+        p = ngx_snprintf(p, len, ", resolver: %V", &uc->server);
+    }
+
+    return p;
+}
+
+
 ngx_int_t
 ngx_udp_connect(ngx_udp_connection_t *uc)
 {
@@ -2077,19 +2110,19 @@
 
     s = ngx_socket(AF_INET, SOCK_DGRAM, 0);
 
-    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, uc->log, 0, "UDP socket %d", s);
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);
 
     if (s == -1) {
-        ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+        ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                       ngx_socket_n " failed");
         return NGX_ERROR;
     }
 
-    c = ngx_get_connection(s, uc->log);
+    c = ngx_get_connection(s, &uc->log);
 
     if (c == NULL) {
         if (ngx_close_socket(s) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+            ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                           ngx_close_socket_n "failed");
         }
 
@@ -2097,13 +2130,13 @@
     }
 
     if (ngx_nonblocking(s) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+        ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                       ngx_nonblocking_n " failed");
 
         ngx_free_connection(c);
 
         if (ngx_close_socket(s) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+            ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                           ngx_close_socket_n " failed");
         }
 
@@ -2113,8 +2146,8 @@
     rev = c->read;
     wev = c->write;
 
-    rev->log = uc->log;
-    wev->log = uc->log;
+    rev->log = &uc->log;
+    wev->log = &uc->log;
 
     uc->connection = c;
 
@@ -2131,7 +2164,7 @@
 
 #endif
 
-    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, uc->log, 0,
+    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
                    "connect to %V, fd:%d #%d", &uc->server, s, c->number);
 
     rc = connect(s, uc->sockaddr, uc->socklen);
@@ -2139,8 +2172,8 @@
     /* TODO: aio, iocp */
 
     if (rc == -1) {
-        ngx_log_error(NGX_LOG_CRIT, uc->log, ngx_socket_errno,
-                      "connect() to %V failed", &uc->server);
+        ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
+                      "connect() failed");
 
         return NGX_ERROR;
     }
--- a/src/core/ngx_resolver.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_resolver.h	Thu Mar 11 21:27:17 2010 +0300
@@ -37,7 +37,7 @@
     struct sockaddr          *sockaddr;
     socklen_t                 socklen;
     ngx_str_t                 server;
-    ngx_log_t                *log;
+    ngx_log_t                 log;
 } ngx_udp_connection_t;
 
 
@@ -135,7 +135,7 @@
 };
 
 
-ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr);
+ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_addr_t *addr);
 ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r,
     ngx_resolver_ctx_t *temp);
 ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx);
--- a/src/core/ngx_string.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/core/ngx_string.c	Thu Mar 11 21:27:17 2010 +0300
@@ -15,10 +15,11 @@
 void
 ngx_strlow(u_char *dst, u_char *src, size_t n)
 {
-    while (n--) {
+    while (n) {
         *dst = ngx_tolower(*src);
         dst++;
         src++;
+        n--;
     }
 }
 
@@ -147,7 +148,7 @@
     int64_t                i64;
     uint64_t               ui64;
     ngx_msec_t             ms;
-    ngx_uint_t             width, sign, hex, max_width, frac_width, i;
+    ngx_uint_t             width, sign, hex, max_width, frac_width, n;
     ngx_str_t             *v;
     ngx_variable_value_t  *vv;
 
@@ -377,7 +378,7 @@
 
                     scale = 1.0;
 
-                    for (i = 0; i < frac_width; i++) {
+                    for (n = frac_width; n; n--) {
                         scale *= 10.0;
                     }
 
@@ -1238,10 +1239,8 @@
             break;
         }
 
-        len--;
-
         while (src < next) {
-            *++dst = *++src;
+            *dst++ = *src++;
             len--;
         }
     }
@@ -1255,7 +1254,7 @@
 uintptr_t
 ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
 {
-    ngx_uint_t      i, n;
+    ngx_uint_t      n;
     uint32_t       *escape;
     static u_char   hex[] = "0123456789abcdef";
 
@@ -1373,17 +1372,18 @@
 
         n = 0;
 
-        for (i = 0; i < size; i++) {
+        while (size) {
             if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
                 n++;
             }
             src++;
+            size--;
         }
 
         return (uintptr_t) n;
     }
 
-    for (i = 0; i < size; i++) {
+    while (size) {
         if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
             *dst++ = '%';
             *dst++ = hex[*src >> 4];
@@ -1393,6 +1393,7 @@
         } else {
             *dst++ = *src++;
         }
+        size--;
     }
 
     return (uintptr_t) dst;
@@ -1533,13 +1534,13 @@
 ngx_escape_html(u_char *dst, u_char *src, size_t size)
 {
     u_char      ch;
-    ngx_uint_t  i, len;
+    ngx_uint_t  len;
 
     if (dst == NULL) {
 
         len = 0;
 
-        for (i = 0; i < size; i++) {
+        while (size) {
             switch (*src++) {
 
             case '<':
@@ -1557,12 +1558,13 @@
             default:
                 break;
             }
+            size--;
         }
 
         return (uintptr_t) len;
     }
 
-    for (i = 0; i < size; i++) {
+    while (size) {
         ch = *src++;
 
         switch (ch) {
@@ -1584,6 +1586,7 @@
             *dst++ = ch;
             break;
         }
+        size--;
     }
 
     return (uintptr_t) dst;
--- a/src/event/modules/ngx_poll_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/modules/ngx_poll_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -72,7 +72,7 @@
         nevents = 0;
     }
 
-    if (ngx_process == NGX_PROCESS_WORKER
+    if (ngx_process >= NGX_PROCESS_WORKER
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
--- a/src/event/modules/ngx_select_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/modules/ngx_select_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -81,7 +81,7 @@
         nevents = 0;
     }
 
-    if (ngx_process == NGX_PROCESS_WORKER
+    if (ngx_process >= NGX_PROCESS_WORKER
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
--- a/src/event/modules/ngx_win32_select_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/modules/ngx_win32_select_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -82,7 +82,7 @@
         nevents = 0;
     }
 
-    if (ngx_process == NGX_PROCESS_WORKER
+    if (ngx_process >= NGX_PROCESS_WORKER
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
--- a/src/event/ngx_event_accept.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/ngx_event_accept.c	Thu Mar 11 21:27:17 2010 +0300
@@ -152,10 +152,20 @@
         c->socklen = socklen;
         c->listening = ls;
         c->local_sockaddr = ls->sockaddr;
-        c->local_socklen = ls->socklen;
 
         c->unexpected_eof = 1;
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+        if (c->sockaddr->sa_family == AF_UNIX) {
+            c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
+            c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
+#if (NGX_SOLARIS)
+            /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
+            c->sendfile = 0;
+#endif
+        }
+#endif
+
         rev = c->read;
         wev = c->write;
 
--- a/src/event/ngx_event_connect.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/ngx_event_connect.c	Thu Mar 11 21:27:17 2010 +0300
@@ -54,15 +54,7 @@
         {
             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
                           "setsockopt(SO_RCVBUF) failed");
-
-            ngx_free_connection(c);
-
-            if (ngx_close_socket(s) == -1) {
-                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
-                              ngx_close_socket_n " failed");
-            }
-
-            return NGX_ERROR;
+            goto failed;
         }
     }
 
@@ -70,14 +62,16 @@
         ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
                       ngx_nonblocking_n " failed");
 
-        ngx_free_connection(c);
+        goto failed;
+    }
 
-        if (ngx_close_socket(s) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
-                          ngx_close_socket_n " failed");
+    if (pc->local) {
+        if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
+            ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
+                          "bind(%V) failed", &pc->local->name);
+
+            goto failed;
         }
-
-        return NGX_ERROR;
     }
 
     c->recv = ngx_recv;
@@ -107,27 +101,22 @@
 
     pc->connection = c;
 
-    /*
-     * TODO: MT: - ngx_atomic_fetch_add()
-     *             or protection by critical section or mutex
-     *
-     * TODO: MP: - allocated in a shared memory
-     *           - ngx_atomic_fetch_add()
-     *             or protection by critical section or mutex
-     */
-
     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
 
 #if (NGX_THREADS)
+
+    /* TODO: lock event when call completion handler */
+
     rev->lock = pc->lock;
     wev->lock = pc->lock;
     rev->own_lock = &c->lock;
     wev->own_lock = &c->lock;
+
 #endif
 
     if (ngx_add_conn) {
         if (ngx_add_conn(c) == NGX_ERROR) {
-            return NGX_ERROR;
+            goto failed;
         }
     }
 
@@ -199,7 +188,7 @@
         if (ngx_blocking(s) == -1) {
             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
                           ngx_blocking_n " failed");
-            return NGX_ERROR;
+            goto failed;
         }
 
         /*
@@ -229,7 +218,7 @@
     }
 
     if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
-        return NGX_ERROR;
+        goto failed;
     }
 
     if (rc == -1) {
@@ -237,7 +226,7 @@
         /* NGX_EINPROGRESS */
 
         if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
-            return NGX_ERROR;
+            goto failed;
         }
 
         return NGX_AGAIN;
@@ -248,6 +237,17 @@
     wev->ready = 1;
 
     return NGX_OK;
+
+failed:
+
+    ngx_free_connection(c);
+
+    if (ngx_close_socket(s) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+                      ngx_close_socket_n " failed");
+    }
+
+    return NGX_ERROR;
 }
 
 
--- a/src/event/ngx_event_connect.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/ngx_event_connect.h	Thu Mar 11 21:27:17 2010 +0300
@@ -55,6 +55,8 @@
     ngx_atomic_t                    *lock;
 #endif
 
+    ngx_addr_t                      *local;
+
     int                              rcvbuf;
 
     ngx_log_t                       *log;
@@ -70,5 +72,4 @@
 ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data);
 
 
-
 #endif /* _NGX_EVENT_CONNECT_H_INCLUDED_ */
--- a/src/event/ngx_event_openssl.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/ngx_event_openssl.c	Thu Mar 11 21:27:17 2010 +0300
@@ -15,6 +15,8 @@
 
 
 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
+static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
+    int ret);
 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
 static void ngx_ssl_write_handler(ngx_event_t *wev);
@@ -104,6 +106,8 @@
 
     ENGINE_load_builtin_engines();
 
+    OpenSSL_add_all_algorithms();
+
     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 
     if (ngx_ssl_connection_index == -1) {
@@ -175,6 +179,8 @@
 
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
+    SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
+
     return NGX_OK;
 }
 
@@ -350,6 +356,22 @@
 }
 
 
+static void
+ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
+{
+    ngx_connection_t  *c;
+
+    if (where & SSL_CB_HANDSHAKE_START) {
+        c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
+
+        if (c->ssl->handshaked) {
+            c->ssl->renegotiation = 1;
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
+        }
+    }
+}
+
+
 ngx_int_t
 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
 {
@@ -587,6 +609,11 @@
         c->recv_chain = ngx_ssl_recv_chain;
         c->send_chain = ngx_ssl_send_chain;
 
+        /* initial handshake done, disable renegotiation (CVE-2009-3555) */
+        if (c->ssl->connection->s3) {
+            c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+        }
+
         return NGX_OK;
     }
 
@@ -789,6 +816,21 @@
     int        sslerr;
     ngx_err_t  err;
 
+    if (c->ssl->renegotiation) {
+        /*
+         * disable renegotiation (CVE-2009-3555):
+         * OpenSSL (at least up to 0.9.8l) does not handle disabled
+         * renegotiation gracefully, so drop connection here
+         */
+
+        ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
+
+        c->ssl->no_wait_shutdown = 1;
+        c->ssl->no_send_shutdown = 1;
+
+        return NGX_ERROR;
+    }
+
     if (n > 0) {
 
         if (c->ssl->saved_write_handler) {
@@ -946,7 +988,7 @@
 
     for ( ;; ) {
 
-        while (in && buf->last < buf->end) {
+        while (in && buf->last < buf->end && send < limit) {
             if (in->buf->last_buf || in->buf->flush) {
                 flush = 1;
             }
@@ -973,8 +1015,8 @@
             ngx_memcpy(buf->last, in->buf->pos, size);
 
             buf->last += size;
-
             in->buf->pos += size;
+            send += size;
 
             if (in->buf->pos == in->buf->last) {
                 in = in->next;
@@ -999,7 +1041,6 @@
         }
 
         buf->pos += n;
-        send += n;
         c->sent += n;
 
         if (n < size) {
@@ -1269,10 +1310,15 @@
 
             /* handshake failures */
         if (n == SSL_R_DIGEST_CHECK_FAILED                           /*  149 */
+            || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
+            || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
+            || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
+            || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
+            || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
@@ -1384,6 +1430,8 @@
         return NGX_OK;
     }
 
+    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
+
     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
 
         /*
@@ -1415,8 +1463,6 @@
 
     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
 
-    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
-
     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
 
         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
@@ -1588,7 +1634,7 @@
     hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
 
     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "http ssl new session: %08XD:%d:%d",
+                   "ssl new session: %08XD:%d:%d",
                    hash, sess->session_id_length, len);
 
     sess_id->node.key = hash;
@@ -1651,7 +1697,7 @@
     *copy = 0;
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "http ssl get session: %08XD:%d", hash, len);
+                   "ssl get session: %08XD:%d", hash, len);
 
     shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
                                    ngx_ssl_session_cache_index);
@@ -1765,7 +1811,7 @@
     hash = ngx_crc32_short(id, len);
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
-                   "http ssl remove session: %08XD:%uz", hash, len);
+                   "ssl remove session: %08XD:%uz", hash, len);
 
     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
@@ -1929,6 +1975,40 @@
 
 
 ngx_int_t
+ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+    int           len;
+    u_char       *p, *buf;
+    SSL_SESSION  *sess;
+
+    sess = SSL_get0_session(c->ssl->connection);
+
+    len = i2d_SSL_SESSION(sess, NULL);
+
+    buf = ngx_alloc(len, c->log);
+    if (buf == NULL) {
+        return NGX_ERROR;
+    }
+
+    s->len = 2 * len;
+    s->data = ngx_pnalloc(pool, 2 * len);
+    if (s->data == NULL) {
+        ngx_free(buf);
+        return NGX_ERROR;
+    }
+
+    p = buf;
+    i2d_SSL_SESSION(sess, &p);
+
+    ngx_hex_dump(s->data, buf, len);
+
+    ngx_free(buf);
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
 {
     size_t   len;
@@ -2237,5 +2317,6 @@
 static void
 ngx_openssl_exit(ngx_cycle_t *cycle)
 {
+    EVP_cleanup();
     ENGINE_cleanup();
 }
--- a/src/event/ngx_event_openssl.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/event/ngx_event_openssl.h	Thu Mar 11 21:27:17 2010 +0300
@@ -15,6 +15,7 @@
 #include <openssl/err.h>
 #include <openssl/conf.h>
 #include <openssl/engine.h>
+#include <openssl/evp.h>
 
 #define NGX_SSL_NAME     "OpenSSL"
 
@@ -41,6 +42,7 @@
     ngx_event_handler_pt        saved_write_handler;
 
     unsigned                    handshaked:1;
+    unsigned                    renegotiation:1;
     unsigned                    buffer:1;
     unsigned                    no_wait_shutdown:1;
     unsigned                    no_send_shutdown:1;
@@ -118,6 +120,8 @@
     ngx_str_t *s);
 ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
+ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
+    ngx_str_t *s);
 ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
 ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,
--- a/src/http/modules/ngx_http_access_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_access_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -10,18 +10,37 @@
 
 
 typedef struct {
-    in_addr_t     mask;
-    in_addr_t     addr;
-    ngx_uint_t    deny;      /* unsigned  deny:1; */
+    in_addr_t         mask;
+    in_addr_t         addr;
+    ngx_uint_t        deny;      /* unsigned  deny:1; */
 } ngx_http_access_rule_t;
 
+#if (NGX_HAVE_INET6)
 
 typedef struct {
-    ngx_array_t  *rules;     /* array of ngx_http_access_rule_t */
+    struct in6_addr   addr;
+    struct in6_addr   mask;
+    ngx_uint_t        deny;      /* unsigned  deny:1; */
+} ngx_http_access_rule6_t;
+
+#endif
+
+typedef struct {
+    ngx_array_t      *rules;     /* array of ngx_http_access_rule_t */
+#if (NGX_HAVE_INET6)
+    ngx_array_t      *rules6;    /* array of ngx_http_access_rule6_t */
+#endif
 } ngx_http_access_loc_conf_t;
 
 
 static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_access_inet(ngx_http_request_t *r,
+    ngx_http_access_loc_conf_t *alcf, in_addr_t addr);
+#if (NGX_HAVE_INET6)
+static ngx_int_t ngx_http_access_inet6(ngx_http_request_t *r,
+    ngx_http_access_loc_conf_t *alcf, u_char *p);
+#endif
+static ngx_int_t ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny);
 static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf);
@@ -87,46 +106,59 @@
 static ngx_int_t
 ngx_http_access_handler(ngx_http_request_t *r)
 {
-    ngx_uint_t                   i;
     struct sockaddr_in          *sin;
-    ngx_http_access_rule_t      *rule;
-    ngx_http_core_loc_conf_t    *clcf;
     ngx_http_access_loc_conf_t  *alcf;
 
     alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
 
-    if (alcf->rules == NULL) {
-        return NGX_DECLINED;
+#if (NGX_HAVE_INET6)
+
+    if (alcf->rules6 && r->connection->sockaddr->sa_family == AF_INET6) {
+        u_char               *p;
+        in_addr_t             addr;
+        struct sockaddr_in6  *sin6;
+
+        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+        p = sin6->sin6_addr.s6_addr;
+
+        if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+            addr = p[12] << 24;
+            addr += p[13] << 16;
+            addr += p[14] << 8;
+            addr += p[15];
+            return ngx_http_access_inet(r, alcf, htonl(addr));
+        }
+
+        return ngx_http_access_inet6(r, alcf, p);
     }
 
-    /* AF_INET only */
+#endif
 
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        return NGX_DECLINED;
+    if (alcf->rules && r->connection->sockaddr->sa_family == AF_INET) {
+        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr);
     }
 
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
+    return NGX_DECLINED;
+}
+
+
+static ngx_int_t
+ngx_http_access_inet(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
+    in_addr_t addr)
+{
+    ngx_uint_t               i;
+    ngx_http_access_rule_t  *rule;
 
     rule = alcf->rules->elts;
     for (i = 0; i < alcf->rules->nelts; i++) {
 
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "access: %08XD %08XD %08XD",
-                       sin->sin_addr.s_addr, rule[i].mask, rule[i].addr);
-
-        if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) {
-            if (rule[i].deny) {
-                clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+                       addr, rule[i].mask, rule[i].addr);
 
-                if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
-                    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                                  "access forbidden by rule");
-                }
-
-                return NGX_HTTP_FORBIDDEN;
-            }
-
-            return NGX_OK;
+        if ((addr & rule[i].mask) == rule[i].addr) {
+            return ngx_http_access_found(r, rule[i].deny);
         }
     }
 
@@ -134,62 +166,159 @@
 }
 
 
+#if (NGX_HAVE_INET6)
+
+static ngx_int_t
+ngx_http_access_inet6(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
+    u_char *p)
+{
+    ngx_uint_t                n;
+    ngx_uint_t                i;
+    ngx_http_access_rule6_t  *rule6;
+
+    rule6 = alcf->rules6->elts;
+    for (i = 0; i < alcf->rules6->nelts; i++) {
+
+#if (NGX_DEBUG)
+        {
+        size_t  cl, ml, al;
+        u_char  ct[NGX_INET6_ADDRSTRLEN];
+        u_char  mt[NGX_INET6_ADDRSTRLEN];
+        u_char  at[NGX_INET6_ADDRSTRLEN];
+
+        cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN);
+        ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN);
+        al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN);
+
+        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "access: %*s %*s %*s", cl, ct, ml, mt, al, at);
+        }
+#endif
+
+        for (n = 0; n < 16; n++) {
+            if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) {
+                goto next;
+            }
+        }
+
+        return ngx_http_access_found(r, rule6[i].deny);
+
+    next:
+        continue;
+    }
+
+    return NGX_DECLINED;
+}
+
+#endif
+
+
+static ngx_int_t
+ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny)
+{
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (deny) {
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+        if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          "access forbidden by rule");
+        }
+
+        return NGX_HTTP_FORBIDDEN;
+    }
+
+    return NGX_OK;
+}
+
+
 static char *
 ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_access_loc_conf_t *alcf = conf;
 
-    ngx_int_t                rc;
-    ngx_str_t               *value;
-    ngx_cidr_t               cidr;
-    ngx_http_access_rule_t  *rule;
+    ngx_int_t                 rc;
+    ngx_uint_t                all;
+    ngx_str_t                *value;
+    ngx_cidr_t                cidr;
+    ngx_http_access_rule_t   *rule;
+#if (NGX_HAVE_INET6)
+    ngx_http_access_rule6_t  *rule6;
+#endif
 
-    if (alcf->rules == NULL) {
-        alcf->rules = ngx_array_create(cf->pool, 4,
-                                       sizeof(ngx_http_access_rule_t));
-        if (alcf->rules == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    rule = ngx_array_push(alcf->rules);
-    if (rule == NULL) {
-        return NGX_CONF_ERROR;
-    }
+    ngx_memzero(&cidr, sizeof(ngx_cidr_t));
 
     value = cf->args->elts;
 
-    rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
+    all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0);
+
+    if (!all) {
+
+        rc = ngx_ptocidr(&value[1], &cidr);
 
-    if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) {
-        rule->mask = 0;
-        rule->addr = 0;
+        if (rc == NGX_ERROR) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                         "invalid parameter \"%V\"", &value[1]);
+            return NGX_CONF_ERROR;
+        }
 
-        return NGX_CONF_OK;
+        if (rc == NGX_DONE) {
+            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                         "low address bits of %V are meaningless", &value[1]);
+        }
     }
 
-    rc = ngx_ptocidr(&value[1], &cidr);
+    switch (cidr.family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+    case 0: /* all */
 
-    if (rc == NGX_ERROR) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
-                           &value[1]);
-        return NGX_CONF_ERROR;
-    }
+        if (alcf->rules6 == NULL) {
+            alcf->rules6 = ngx_array_create(cf->pool, 4,
+                                            sizeof(ngx_http_access_rule6_t));
+            if (alcf->rules6 == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
+
+        rule6 = ngx_array_push(alcf->rules6);
+        if (rule6 == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        rule6->mask = cidr.u.in6.mask;
+        rule6->addr = cidr.u.in6.addr;
+        rule6->deny = (value[0].data[0] == 'd') ? 1 : 0;
 
-    if (cidr.family != AF_INET) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "\"allow\" supports IPv4 only");
-        return NGX_CONF_ERROR;
-    }
+        if (!all) {
+            break;
+        }
+
+        /* "all" passes through */
+#endif
+
+    default: /* AF_INET */
 
-    if (rc == NGX_DONE) {
-        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
-                           "low address bits of %V are meaningless", &value[1]);
+        if (alcf->rules == NULL) {
+            alcf->rules = ngx_array_create(cf->pool, 4,
+                                           sizeof(ngx_http_access_rule_t));
+            if (alcf->rules == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
+
+        rule = ngx_array_push(alcf->rules);
+        if (rule == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        rule->mask = cidr.u.in.mask;
+        rule->addr = cidr.u.in.addr;
+        rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
     }
 
-    rule->mask = cidr.u.in.mask;
-    rule->addr = cidr.u.in.addr;
-
     return NGX_CONF_OK;
 }
 
@@ -218,6 +347,12 @@
         conf->rules = prev->rules;
     }
 
+#if (NGX_HAVE_INET6)
+    if (conf->rules6 == NULL) {
+        conf->rules6 = prev->rules6;
+    }
+#endif
+
     return NGX_CONF_OK;
 }
 
--- a/src/http/modules/ngx_http_addition_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_addition_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -45,7 +45,7 @@
       offsetof(ngx_http_addition_conf_t, after_body),
       NULL },
 
-    { ngx_string("addtion_types"),
+    { ngx_string("addition_types"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_types_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
@@ -237,8 +237,8 @@
     ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
     ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_charset_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_charset_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -1550,8 +1550,8 @@
     ngx_http_charset_recode_t     *recode;
     ngx_http_charset_main_conf_t  *mcf;
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_charset_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_chunked_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_chunked_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -52,7 +52,6 @@
 {
     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
         || r->headers_out.status == NGX_HTTP_NO_CONTENT
-        || r->headers_out.status == NGX_HTTP_CREATED
         || r != r->main
         || (r->method & NGX_HTTP_HEAD))
     {
--- a/src/http/modules/ngx_http_dav_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_dav_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -490,6 +490,7 @@
     p = ngx_http_map_uri_to_path(r, &path, &root, 0);
 
     *(p - 1) = '\0';
+    r->uri.len--;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http mkcol path: \"%s\"", path.data);
@@ -516,8 +517,8 @@
     size_t                    len, root;
     ngx_err_t                 err;
     ngx_int_t                 rc, depth;
-    ngx_uint_t                overwrite, slash, dir;
-    ngx_str_t                 path, uri;
+    ngx_uint_t                overwrite, slash, dir, flags;
+    ngx_str_t                 path, uri, duri, args;
     ngx_tree_ctx_t            tree;
     ngx_copy_file_t           cf;
     ngx_file_info_t           fi;
@@ -594,6 +595,14 @@
 
 destination_done:
 
+    duri.len = last - p;
+    duri.data = p;
+    flags = 0;
+
+    if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) {
+        goto invalid_destination;
+    }
+
     if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/')
         || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/'))
     {
@@ -656,9 +665,7 @@
                    "http copy from: \"%s\"", path.data);
 
     uri = r->uri;
-
-    r->uri.len = last - p;
-    r->uri.data = p;
+    r->uri = duri;
 
     ngx_http_map_uri_to_path(r, &copy.path, &root, 0);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/http/modules/ngx_http_degradation_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -0,0 +1,228 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    size_t      sbrk_size;
+} ngx_http_degradation_main_conf_t;
+
+
+typedef struct {
+    ngx_uint_t  degrade;
+} ngx_http_degradation_loc_conf_t;
+
+
+static ngx_conf_enum_t  ngx_http_degrade[] = {
+    { ngx_string("204"), 204 },
+    { ngx_string("444"), 444 },
+    { ngx_null_string, 0 }
+};
+
+
+static void *ngx_http_degradation_create_main_conf(ngx_conf_t *cf);
+static void *ngx_http_degradation_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent,
+    void *child);
+static char *ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static ngx_int_t ngx_http_degradation_init(ngx_conf_t *cf);
+
+
+static ngx_command_t  ngx_http_degradation_commands[] = {
+
+    { ngx_string("degradation"),
+      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
+      ngx_http_degradation,
+      NGX_HTTP_MAIN_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("degrade"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_degradation_loc_conf_t, degrade),
+      &ngx_http_degrade },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_degradation_module_ctx = {
+    NULL,                                  /* preconfiguration */
+    ngx_http_degradation_init,             /* postconfiguration */
+
+    ngx_http_degradation_create_main_conf, /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_degradation_create_loc_conf,  /* create location configuration */
+    ngx_http_degradation_merge_loc_conf    /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_degradation_module = {
+    NGX_MODULE_V1,
+    &ngx_http_degradation_module_ctx,      /* module context */
+    ngx_http_degradation_commands,         /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    NULL,                                  /* init master */
+    NULL,                                  /* init module */
+    NULL,                                  /* init process */
+    NULL,                                  /* init thread */
+    NULL,                                  /* exit thread */
+    NULL,                                  /* exit process */
+    NULL,                                  /* exit master */
+    NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_int_t
+ngx_http_degradation_handler(ngx_http_request_t *r)
+{
+    time_t                             now;
+    static size_t                      sbrk_size;
+    static time_t                      sbrk_time;
+    ngx_http_degradation_loc_conf_t   *dlcf;
+    ngx_http_degradation_main_conf_t  *dmcf;
+
+    dlcf = ngx_http_get_module_loc_conf(r, ngx_http_degradation_module);
+
+    if (dlcf->degrade == 0) {
+        return NGX_DECLINED;
+    }
+
+    dmcf = ngx_http_get_module_main_conf(r, ngx_http_degradation_module);
+
+    if (dmcf->sbrk_size) {
+
+        now = ngx_time();
+
+        /* lock mutex */
+
+        if (now != sbrk_time) {
+
+            /*
+             * ELF/i386 is loaded at 0x08000000, 128M
+             * ELF/amd64 is loaded at 0x00400000, 4M
+             *
+             * use a function address to substract the loading address
+             */
+
+            sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF);
+            sbrk_time = now;
+        }
+
+        /* unlock mutex */
+
+        if (sbrk_size >= dmcf->sbrk_size) {
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "degradation sbrk: %uz", sbrk_size);
+
+            return dlcf->degrade;
+        }
+    }
+
+    return NGX_DECLINED;
+}
+
+
+static void *
+ngx_http_degradation_create_main_conf(ngx_conf_t *cf)
+{
+    ngx_http_degradation_main_conf_t  *dmcf;
+
+    dmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_degradation_main_conf_t));
+    if (dmcf == NULL) {
+        return NULL;
+    }
+
+    return dmcf;
+}
+
+
+static void *
+ngx_http_degradation_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_degradation_loc_conf_t  *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_degradation_loc_conf_t));
+    if (conf == NULL) {
+        return NULL;
+    }
+
+    conf->degrade = NGX_CONF_UNSET_UINT;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_degradation_loc_conf_t  *prev = parent;
+    ngx_http_degradation_loc_conf_t  *conf = child;
+
+    ngx_conf_merge_uint_value(conf->degrade, prev->degrade, 0);
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_degradation_main_conf_t  *dmcf = conf;
+
+    ngx_str_t  *value, s;
+
+    value = cf->args->elts;
+
+    if (ngx_strncmp(value[1].data, "sbrk=", 5) == 0) {
+
+        s.len = value[1].len - 5;
+        s.data = value[1].data + 5;
+
+        dmcf->sbrk_size = ngx_parse_size(&s);
+        if (dmcf->sbrk_size == (size_t) NGX_ERROR) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid sbrk size \"%V\"", &value[1]);
+            return NGX_CONF_ERROR;
+        }
+
+        return NGX_CONF_OK;
+    }
+
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "invalid parameter \"%V\"", &value[1]);
+
+    return NGX_CONF_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_degradation_init(ngx_conf_t *cf)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_degradation_handler;
+
+    return NGX_OK;
+}
--- a/src/http/modules/ngx_http_fastcgi_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_fastcgi_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -62,7 +62,8 @@
     size_t                         length;
     size_t                         padding;
 
-    ngx_uint_t                     fastcgi_stdout; /* unsigned :1 */
+    unsigned                       fastcgi_stdout:1;
+    unsigned                       large_stderr:1;
 
     ngx_array_t                   *split_parts;
 
@@ -240,6 +241,13 @@
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
       NULL },
 
+    { ngx_string("fastcgi_bind"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_upstream_bind_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
+      NULL },
+
     { ngx_string("fastcgi_connect_timeout"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -523,6 +531,23 @@
 };
 
 
+#if (NGX_HTTP_CACHE)
+
+static ngx_str_t  ngx_http_fastcgi_hide_cache_headers[] = {
+    ngx_string("Status"),
+    ngx_string("X-Accel-Expires"),
+    ngx_string("X-Accel-Redirect"),
+    ngx_string("X-Accel-Limit-Rate"),
+    ngx_string("X-Accel-Buffering"),
+    ngx_string("X-Accel-Charset"),
+    ngx_string("Set-Cookie"),
+    ngx_string("P3P"),
+    ngx_null_string
+};
+
+#endif
+
+
 static ngx_path_init_t  ngx_http_fastcgi_temp_path = {
     ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
 };
@@ -1057,6 +1082,7 @@
 
     f->state = ngx_http_fastcgi_st_version;
     f->fastcgi_stdout = 0;
+    f->large_stderr = 0;
 
     return NGX_OK;
 }
@@ -1075,6 +1101,7 @@
     ngx_table_elt_t                *h;
     ngx_http_upstream_t            *u;
     ngx_http_fastcgi_ctx_t         *f;
+    ngx_http_fastcgi_header_t      *fh;
     ngx_http_upstream_header_t     *hh;
     ngx_http_fastcgi_loc_conf_t    *flcf;
     ngx_http_fastcgi_split_part_t  *part;
@@ -1199,8 +1226,17 @@
                          * of the PHP warnings to not allocate memory
                          */
 
-                        u->buffer.pos = u->buffer.start;
-                        u->buffer.last = u->buffer.start;
+#if (NGX_HTTP_CACHE)
+                        if (r->cache) {
+                            u->buffer.pos = u->buffer.start
+                                                     + r->cache->header_start;
+                        } else {
+                            u->buffer.pos = u->buffer.start;
+                        }
+#endif
+
+                        u->buffer.last = u->buffer.pos;
+                        f->large_stderr = 1;
                     }
 
                     return NGX_AGAIN;
@@ -1216,6 +1252,45 @@
 
         /* f->type == NGX_HTTP_FASTCGI_STDOUT */
 
+#if (NGX_HTTP_CACHE)
+
+        if (f->large_stderr) {
+            u_char   *start;
+            ssize_t   len;
+
+            start = u->buffer.start + r->cache->header_start;
+
+            len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
+
+            /*
+             * A tail of large stderr output before HTTP header is placed
+             * in a cache file without a FastCGI record header.
+             * To workaround it we put a dummy FastCGI record header at the
+             * start of the stderr output or update r->cache_header_start,
+             * if there is no enough place for the record header.
+             */
+
+            if (len >= 0) {
+                fh = (ngx_http_fastcgi_header_t *) start;
+                fh->version = 1;
+                fh->type = NGX_HTTP_FASTCGI_STDERR;
+                fh->request_id_hi = 0;
+                fh->request_id_lo = 1;
+                fh->content_length_hi = (u_char) ((len >> 8) & 0xff);
+                fh->content_length_lo = (u_char) (len & 0xff);
+                fh->padding_length = 0;
+                fh->reserved = 0;
+
+            } else {
+                r->cache->header_start += u->buffer.pos - start
+                                           - sizeof(ngx_http_fastcgi_header_t);
+            }
+
+            f->large_stderr = 0;
+        }
+
+#endif
+
         f->fastcgi_stdout = 1;
 
         start = u->buffer.pos;
@@ -1899,6 +1974,7 @@
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
+    ngx_str_t                    *h;
     ngx_uint_t                    i;
     ngx_keyval_t                 *src;
     ngx_hash_init_t               hash;
@@ -2119,10 +2195,18 @@
     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
     hash.name = "fastcgi_hide_headers_hash";
 
+#if (NGX_HTTP_CACHE)
+
+    h = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers:
+                               ngx_http_fastcgi_hide_headers;
+#else
+
+    h = ngx_http_fastcgi_hide_headers;
+
+#endif
+
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream,
-                                            ngx_http_fastcgi_hide_headers,
-                                            &hash)
+                                            &prev->upstream, h, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
@@ -2374,27 +2458,25 @@
 
     n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
 
+    if (n >= 0) { /* match */
+        f->script_name.len = captures[3] - captures[2];
+        f->script_name.data = r->uri.data;
+
+        f->path_info.len = captures[5] - captures[4];
+        f->path_info.data = r->uri.data + f->script_name.len;
+
+        return f;
+    }
+
     if (n == NGX_REGEX_NO_MATCHED) {
         f->script_name = r->uri;
         return f;
     }
 
-    if (n < 0) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
-                      n, &r->uri, &flcf->split_name);
-        return NULL;
-    }
-
-    /* match */
-
-    f->script_name.len = captures[3] - captures[2];
-    f->script_name.data = r->uri.data;
-
-    f->path_info.len = captures[5] - captures[4];
-    f->path_info.data = r->uri.data + f->script_name.len;
-
-    return f;
+    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                  ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+                  n, &r->uri, &flcf->split_name);
+    return NULL;
 
 #else
 
@@ -2485,39 +2567,34 @@
 #if (NGX_PCRE)
     ngx_http_fastcgi_loc_conf_t *flcf = conf;
 
-    ngx_int_t   n;
-    ngx_str_t  *value, err;
-    u_char      errstr[NGX_MAX_CONF_ERRSTR];
+    ngx_str_t            *value;
+    ngx_regex_compile_t   rc;
+    u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
     value = cf->args->elts;
 
     flcf->split_name = value[1];
 
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
-
-    flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
-
-    if (flcf->split_regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+    rc.pattern = value[1];
+    rc.pool = cf->pool;
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
+
+    if (ngx_regex_compile(&rc) != NGX_OK) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
         return NGX_CONF_ERROR;
     }
 
-    n = ngx_regex_capture_count(flcf->split_regex);
-
-    if (n < 0) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           ngx_regex_capture_count_n " failed for "
-                           "pattern \"%V\"", &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    if (n != 2) {
+    if (rc.captures != 2) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "pattern \"%V\" must have 2 captures", &value[1]);
         return NGX_CONF_ERROR;
     }
 
+    flcf->split_regex = rc.regex;
+
     return NGX_CONF_OK;
 
 #else
--- a/src/http/modules/ngx_http_flv_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_flv_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -106,6 +106,7 @@
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
--- a/src/http/modules/ngx_http_geo_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_geo_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -589,7 +589,7 @@
     ngx_array_t           *a;
     ngx_http_geo_range_t  *range;
 
-    for (n = start; n <= end; n += 0x10000) {
+    for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) {
 
         h = n >> 16;
 
--- a/src/http/modules/ngx_http_geoip_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_geoip_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -30,6 +30,9 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
@@ -93,23 +96,32 @@
 
 static ngx_http_variable_t  ngx_http_geoip_vars[] = {
 
-    { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code3"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_name"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_continent_code"), NULL,
+      ngx_http_geoip_city_variable,
+      offsetof(GeoIPRecord, continent_code), 0, 0 },
+
+    { ngx_string("geoip_city_country_code"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code), 0, 0 },
 
     { ngx_string("geoip_city_country_code3"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code3), 0, 0 },
 
-    { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_country_name"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_name), 0, 0 },
 
     { ngx_string("geoip_region"), NULL,
@@ -124,6 +136,14 @@
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, postal_code), 0, 0 },
 
+    { ngx_string("geoip_latitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, latitude), 0, 0 },
+
+    { ngx_string("geoip_longitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, longitude), 0, 0 },
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -179,34 +199,16 @@
 ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    u_long                  addr;
-    char                   *val;
-    size_t                  len;
-    GeoIPRecord            *gr;
-    struct sockaddr_in     *sin;
-    ngx_http_geoip_conf_t  *gcf;
-
-    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+    char         *val;
+    size_t        len;
+    GeoIPRecord  *gr;
 
-    if (gcf->city == NULL) {
-        goto not_found;
-    }
-
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        goto not_found;
-    }
-
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
-    addr = ntohl(sin->sin_addr.s_addr);
-
-    gr = GeoIP_record_by_ipnum(gcf->city, addr);
-
+    gr = ngx_http_geoip_get_city_record(r);
     if (gr == NULL) {
         goto not_found;
     }
 
     val = *(char **) ((char *) gr + data);
-
     if (val == NULL) {
         goto no_value;
     }
@@ -243,6 +245,56 @@
 
 
 static ngx_int_t
+ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    float         val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    val = *(float *) ((char *) gr + data);
+
+    v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+}
+
+
+static GeoIPRecord *
+ngx_http_geoip_get_city_record(ngx_http_request_t *r)
+{
+    u_long                  addr;
+    struct sockaddr_in     *sin;
+    ngx_http_geoip_conf_t  *gcf;
+
+    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+
+    if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) {
+
+        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        addr = ntohl(sin->sin_addr.s_addr);
+
+        return GeoIP_record_by_ipnum(gcf->city, addr);
+    }
+
+    return NULL;
+}
+
+
+static ngx_int_t
 ngx_http_geoip_add_variables(ngx_conf_t *cf)
 {
     ngx_http_variable_t  *var, *v;
--- a/src/http/modules/ngx_http_gzip_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_gzip_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -246,17 +246,27 @@
         || (r->headers_out.status != NGX_HTTP_OK
             && r->headers_out.status != NGX_HTTP_FORBIDDEN
             && r->headers_out.status != NGX_HTTP_NOT_FOUND)
-        || r->header_only
         || (r->headers_out.content_encoding
             && r->headers_out.content_encoding->value.len)
         || (r->headers_out.content_length_n != -1
             && r->headers_out.content_length_n < conf->min_length)
         || ngx_http_test_content_type(r, &conf->types) == NULL
-        || ngx_http_gzip_ok(r) != NGX_OK)
+        || r->header_only)
     {
         return ngx_http_next_header_filter(r);
     }
 
+    r->gzip_vary = 1;
+
+    if (!r->gzip_tested) {
+        if (ngx_http_gzip_ok(r) != NGX_OK) {
+            return ngx_http_next_header_filter(r);
+        }
+
+    } else if (!r->gzip_ok) {
+        return ngx_http_next_header_filter(r);
+    }
+
     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t));
     if (ctx == NULL) {
         return NGX_ERROR;
@@ -1113,8 +1123,8 @@
                               MAX_MEM_LEVEL - 1);
     ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_gzip_static_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_gzip_static_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -95,7 +95,15 @@
 
     gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);
 
-    if (!gzcf->enable || ngx_http_gzip_ok(r) != NGX_OK) {
+    if (!gzcf->enable) {
+        return NGX_DECLINED;
+    }
+
+    rc = ngx_http_gzip_ok(r);
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (!clcf->gzip_vary && rc != NGX_OK) {
         return NGX_DECLINED;
     }
 
@@ -116,10 +124,9 @@
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
                    "http filename: \"%s\"", path.data);
 
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
@@ -157,6 +164,12 @@
         return NGX_DECLINED;
     }
 
+    r->gzip_vary = 1;
+
+    if (rc != NGX_OK) {
+        return NGX_DECLINED;
+    }
+
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
 
     if (of.is_dir) {
--- a/src/http/modules/ngx_http_headers_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_headers_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -291,7 +291,7 @@
 
     ngx_http_time(expires->value.data, expires_time);
 
-    if (conf->expires_time < 0) {
+    if (conf->expires_time < 0 || max_age < 0) {
         cc->value.len = sizeof("no-cache") - 1;
         cc->value.data = (u_char *) "no-cache";
 
--- a/src/http/modules/ngx_http_image_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_image_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -40,6 +40,8 @@
     ngx_uint_t                   height;
     ngx_int_t                    jpeg_quality;
 
+    ngx_flag_t                   transparency;
+
     ngx_http_complex_value_t    *wcv;
     ngx_http_complex_value_t    *hcv;
 
@@ -61,6 +63,7 @@
 
     ngx_uint_t                   phase;
     ngx_uint_t                   type;
+    ngx_uint_t                   force;
 } ngx_http_image_filter_ctx_t;
 
 
@@ -115,6 +118,13 @@
       offsetof(ngx_http_image_filter_conf_t, jpeg_quality),
       NULL },
 
+    { ngx_string("image_filter_transparency"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_image_filter_conf_t, transparency),
+      NULL },
+
     { ngx_string("image_filter_buffer"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_size_slot,
@@ -492,7 +502,8 @@
 
     if (rc == NGX_OK
         && ctx->width <= ctx->max_width
-        && ctx->height <= ctx->max_height)
+        && ctx->height <= ctx->max_height
+        && !ctx->force)
     {
         return ngx_http_image_asis(r, ctx);
     }
@@ -592,6 +603,7 @@
 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
 {
     u_char      *p, *last;
+    size_t       len, app;
     ngx_uint_t   width, height;
 
     p = ctx->image;
@@ -602,26 +614,38 @@
 
         p += 2;
         last = ctx->image + ctx->length - 10;
+        width = 0;
+        height = 0;
+        app = 0;
 
         while (p < last) {
 
             if (p[0] == 0xff && p[1] != 0xff) {
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "JPEG: %02xd %02xd", *p, *(p + 1));
+                               "JPEG: %02xd %02xd", p[0], p[1]);
 
                 p++;
 
-                if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
-                    || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
+                     || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                    && (width == 0 || height == 0))
                 {
-                    goto found;
+                    width = p[6] * 256 + p[7];
+                    height = p[4] * 256 + p[5];
                 }
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                                "JPEG: %02xd %02xd", p[1], p[2]);
 
-                p += p[1] * 256 + p[2];
+                len = p[1] * 256 + p[2];
+
+                if (*p >= 0xe1 && *p <= 0xef) {
+                    /* application data, e.g., EXIF, Adobe XMP, etc. */
+                    app += len;
+                }
+
+                p += len;
 
                 continue;
             }
@@ -629,12 +653,16 @@
             p++;
         }
 
-        return NGX_DECLINED;
+        if (width == 0 || height == 0) {
+            return NGX_DECLINED;
+        }
 
-    found:
-
-        width = p[6] * 256 + p[7];
-        height = p[4] * 256 + p[5];
+        if (ctx->length / 20 < app) {
+            /* force conversion if application data consume more than 5% */
+            ctx->force = 1;
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "app data size: %uz", app);
+        }
 
         break;
 
@@ -678,8 +706,9 @@
 static ngx_buf_t *
 ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
 {
-    int                            sx, sy, dx, dy, ox, oy,
-                                   colors, transparent, red, green, blue, size;
+    int                            sx, sy, dx, dy, ox, oy, size,
+                                   colors, palette, transparent,
+                                   red, green, blue;
     u_char                        *out;
     ngx_buf_t                     *b;
     ngx_uint_t                     resize;
@@ -698,7 +727,8 @@
 
     conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
 
-    if ((ngx_uint_t) sx <= ctx->max_width
+    if (!ctx->force
+        && (ngx_uint_t) sx <= ctx->max_width
         && (ngx_uint_t) sy <= ctx->max_height)
     {
         gdImageDestroy(src);
@@ -706,17 +736,29 @@
     }
 
     colors = gdImageColorsTotal(src);
-    transparent = gdImageGetTransparent(src);
+
+    if (colors && conf->transparency) {
+        transparent = gdImageGetTransparent(src);
+
+        if (transparent != -1) {
+            palette = colors;
+            red = gdImageRed(src, transparent);
+            green = gdImageGreen(src, transparent);
+            blue = gdImageBlue(src, transparent);
 
-    if (transparent != -1 && colors) {
-        red = gdImageRed(src, transparent);
-        green = gdImageGreen(src, transparent);
-        blue = gdImageBlue(src, transparent);
-        gdImageColorTransparent(src, -1);
+            goto transparent;
+        }
+    }
 
-    } else {
-        red = 0; green = 0; blue = 0;
-    }
+    palette = 0;
+    transparent = -1;
+    red = 0;
+    green = 0;
+    blue = 0;
+
+transparent:
+
+    gdImageColorTransparent(src, -1);
 
     dx = sx;
     dy = sy;
@@ -762,14 +804,23 @@
     }
 
     if (resize) {
-        dst = ngx_http_image_new(r, dx, dy, colors);
+        dst = ngx_http_image_new(r, dx, dy, palette);
         if (dst == NULL) {
             gdImageDestroy(src);
             return NULL;
         }
 
+        if (colors == 0) {
+            gdImageSaveAlpha(dst, 1);
+            gdImageAlphaBlending(dst, 0);
+        }
+
         gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy);
 
+        if (colors) {
+            gdImageTrueColorToPalette(dst, 1, 256);
+        }
+
         gdImageDestroy(src);
 
     } else {
@@ -810,8 +861,17 @@
                            "image crop: %d x %d @ %d x %d",
                            dx, dy, ox, oy);
 
+            if (colors == 0) {
+                gdImageSaveAlpha(dst, 1);
+                gdImageAlphaBlending(dst, 0);
+            }
+
             gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy);
 
+            if (colors) {
+                gdImageTrueColorToPalette(dst, 1, 256);
+            }
+
             gdImageDestroy(src);
         }
     }
@@ -1021,6 +1081,7 @@
 
     conf->filter = NGX_CONF_UNSET_UINT;
     conf->jpeg_quality = NGX_CONF_UNSET;
+    conf->transparency = NGX_CONF_UNSET;
     conf->buffer_size = NGX_CONF_UNSET_SIZE;
 
     return conf;
@@ -1050,6 +1111,8 @@
     /* 75 is libjpeg default quality */
     ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75);
 
+    ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
+
     ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
                               1 * 1024 * 1024);
 
--- a/src/http/modules/ngx_http_index_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_index_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -205,6 +205,7 @@
 
         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+        of.read_ahead = clcf->read_ahead;
         of.directio = clcf->directio;
         of.valid = clcf->open_file_cache_valid;
         of.min_uses = clcf->open_file_cache_min_uses;
@@ -222,7 +223,10 @@
                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
             }
 
-            if (of.err == NGX_ENOTDIR || of.err == NGX_EACCES) {
+            if (of.err == NGX_ENOTDIR
+                || of.err == NGX_ENAMETOOLONG
+                || of.err == NGX_EACCES)
+            {
                 return ngx_http_index_error(r, clcf, path.data, of.err);
             }
 
--- a/src/http/modules/ngx_http_limit_req_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_limit_req_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -42,7 +42,10 @@
     ngx_shm_zone_t              *shm_zone;
     /* integer value, 1 corresponds to 0.001 r/s */
     ngx_uint_t                   burst;
-    ngx_uint_t                   nodelay;/* unsigned  nodelay:1 */
+    ngx_uint_t                   limit_log_level;
+    ngx_uint_t                   delay_log_level;
+
+    ngx_uint_t                   nodelay; /* unsigned  nodelay:1 */
 } ngx_http_limit_req_conf_t;
 
 
@@ -62,6 +65,15 @@
 static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
 
 
+static ngx_conf_enum_t  ngx_http_limit_req_log_levels[] = {
+    { ngx_string("info"), NGX_LOG_INFO },
+    { ngx_string("notice"), NGX_LOG_NOTICE },
+    { ngx_string("warn"), NGX_LOG_WARN },
+    { ngx_string("error"), NGX_LOG_ERR },
+    { ngx_null_string, 0 }
+};
+
+
 static ngx_command_t  ngx_http_limit_req_commands[] = {
 
     { ngx_string("limit_req_zone"),
@@ -78,6 +90,13 @@
       0,
       NULL },
 
+    { ngx_string("limit_req_log_level"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_limit_req_conf_t, limit_log_level),
+      &ngx_http_limit_req_log_levels },
+
       ngx_null_command
 };
 
@@ -186,7 +205,7 @@
     if (rc == NGX_BUSY) {
         ngx_shmtx_unlock(&ctx->shpool->mutex);
 
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+        ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
                       "limiting requests, excess: %ui.%03ui by zone \"%V\"",
                       excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
 
@@ -200,7 +219,7 @@
             return NGX_DECLINED;
         }
 
-        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+        ngx_log_error(lrcf->delay_log_level, r->connection->log, 0,
                       "delaying request, excess: %ui.%03ui, by zone \"%V\"",
                       excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
 
@@ -383,15 +402,16 @@
                     excess = 0;
                 }
 
+                if ((ngx_uint_t) excess > lrcf->burst) {
+                    *lrp = lr;
+                    return NGX_BUSY;
+                }
+
                 lr->excess = excess;
                 lr->last = now;
 
                 *lrp = lr;
 
-                if ((ngx_uint_t) excess > lrcf->burst) {
-                    return NGX_BUSY;
-                }
-
                 if (excess) {
                     return NGX_AGAIN;
                 }
@@ -548,6 +568,8 @@
      *     conf->nodelay = 0;
      */
 
+    conf->limit_log_level = NGX_CONF_UNSET_UINT;
+
     return conf;
 }
 
@@ -562,6 +584,12 @@
         *conf = *prev;
     }
 
+    ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
+                              NGX_LOG_ERR);
+
+    conf->delay_log_level = (conf->limit_log_level == NGX_LOG_INFO) ?
+                                NGX_LOG_INFO : conf->limit_log_level + 1;
+
     return NGX_CONF_OK;
 }
 
--- a/src/http/modules/ngx_http_limit_zone_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_limit_zone_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -33,6 +33,7 @@
 typedef struct {
     ngx_shm_zone_t     *shm_zone;
     ngx_uint_t          conn;
+    ngx_uint_t          log_level;
 } ngx_http_limit_zone_conf_t;
 
 
@@ -48,6 +49,15 @@
 static ngx_int_t ngx_http_limit_zone_init(ngx_conf_t *cf);
 
 
+static ngx_conf_enum_t  ngx_http_limit_conn_log_levels[] = {
+    { ngx_string("info"), NGX_LOG_INFO },
+    { ngx_string("notice"), NGX_LOG_NOTICE },
+    { ngx_string("warn"), NGX_LOG_WARN },
+    { ngx_string("error"), NGX_LOG_ERR },
+    { ngx_null_string, 0 }
+};
+
+
 static ngx_command_t  ngx_http_limit_zone_commands[] = {
 
     { ngx_string("limit_zone"),
@@ -64,6 +74,13 @@
       0,
       NULL },
 
+    { ngx_string("limit_conn_log_level"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_limit_zone_conf_t, log_level),
+      &ngx_http_limit_conn_log_levels },
+
       ngx_null_command
 };
 
@@ -189,7 +206,7 @@
 
                 ngx_shmtx_unlock(&shpool->mutex);
 
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                ngx_log_error(lzcf->log_level, r->connection->log, 0,
                               "limiting connections by zone \"%V\"",
                               &lzcf->shm_zone->shm.name);
 
@@ -391,6 +408,8 @@
      *     conf->conn = 0;
      */
 
+    conf->log_level = NGX_CONF_UNSET_UINT;
+
     return conf;
 }
 
@@ -405,6 +424,8 @@
         *conf = *prev;
     }
 
+    ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR);
+
     return NGX_CONF_OK;
 }
 
--- a/src/http/modules/ngx_http_log_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_log_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -542,8 +542,25 @@
 static u_char *
 ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
 {
-    return ngx_sprintf(buf, "%ui",
-                       r->err_status ? r->err_status : r->headers_out.status);
+    ngx_uint_t  status;
+
+    if (r->err_status) {
+        status = r->err_status;
+
+    } else if (r->headers_out.status) {
+        status = r->headers_out.status;
+
+    } else if (r->http_version == NGX_HTTP_VERSION_9) {
+        *buf++ = '0';
+        *buf++ = '0';
+        *buf++ = '9';
+        return buf;
+
+    } else {
+        status = 0;
+    }
+
+    return ngx_sprintf(buf, "%ui", status);
 }
 
 
@@ -650,7 +667,7 @@
 static uintptr_t
 ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
 {
-    ngx_uint_t      i, n;
+    ngx_uint_t      n;
     static u_char   hex[] = "0123456789ABCDEF";
 
     static uint32_t   escape[] = {
@@ -678,17 +695,18 @@
 
         n = 0;
 
-        for (i = 0; i < size; i++) {
+        while (size) {
             if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
                 n++;
             }
             src++;
+            size--;
         }
 
         return (uintptr_t) n;
     }
 
-    for (i = 0; i < size; i++) {
+    while (size) {
         if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
             *dst++ = '\\';
             *dst++ = 'x';
@@ -699,6 +717,7 @@
         } else {
             *dst++ = *src++;
         }
+        size--;
     }
 
     return (uintptr_t) dst;
--- a/src/http/modules/ngx_http_memcached_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_memcached_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -63,6 +63,13 @@
       0,
       NULL },
 
+    { ngx_string("memcached_bind"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_upstream_bind_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_memcached_loc_conf_t, upstream.local),
+      NULL },
+
     { ngx_string("memcached_connect_timeout"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
--- a/src/http/modules/ngx_http_not_modified_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -88,6 +88,11 @@
     ngx_http_clear_content_length(r);
     ngx_http_clear_accept_ranges(r);
 
+    if (r->headers_out.content_encoding) {
+        r->headers_out.content_encoding->hash = 0;
+        r->headers_out.content_encoding = NULL;
+    }
+
     return ngx_http_next_header_filter(r);
 }
 
--- a/src/http/modules/ngx_http_proxy_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_proxy_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -229,6 +229,13 @@
       offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
       NULL },
 
+    { ngx_string("proxy_bind"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_upstream_bind_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
+      NULL },
+
     { ngx_string("proxy_connect_timeout"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -530,7 +537,7 @@
     { ngx_string("Expect"), ngx_string("") },
     { ngx_string("If-Modified-Since"), ngx_string("") },
     { ngx_string("If-Unmodified-Since"), ngx_string("") },
-    { ngx_string("If-Match-None"), ngx_string("") },
+    { ngx_string("If-None-Match"), ngx_string("") },
     { ngx_string("If-Match"), ngx_string("") },
     { ngx_string("Range"), ngx_string("") },
     { ngx_string("If-Range"), ngx_string("") },
@@ -717,17 +724,22 @@
         return NGX_ERROR;
     }
 
-    if (url.uri.len && url.uri.data[0] == '?') {
-        p = ngx_pnalloc(r->pool, url.uri.len + 1);
-        if (p == NULL) {
-            return NGX_ERROR;
+    if (url.uri.len) {
+        if (url.uri.data[0] == '?') {
+            p = ngx_pnalloc(r->pool, url.uri.len + 1);
+            if (p == NULL) {
+                return NGX_ERROR;
+            }
+
+            *p++ = '/';
+            ngx_memcpy(p, url.uri.data, url.uri.len);
+
+            url.uri.len++;
+            url.uri.data = p - 1;
         }
 
-        *p++ = '/';
-        ngx_memcpy(p, url.uri.data, url.uri.len);
-
-        url.uri.len++;
-        url.uri.data = p - 1;
+    } else {
+        url.uri = r->unparsed_uri;
     }
 
     ctx->vars.key_start = u->schema;
@@ -1218,7 +1230,6 @@
 
         if (r->cache) {
             r->http_version = NGX_HTTP_VERSION_9;
-            u->headers_in.status_n = NGX_HTTP_OK;
             return NGX_OK;
         }
 
@@ -1234,7 +1245,6 @@
 #endif
 
         r->http_version = NGX_HTTP_VERSION_9;
-        u->headers_in.status_n = NGX_HTTP_OK;
         u->state->status = NGX_HTTP_OK;
 
         return NGX_OK;
--- a/src/http/modules/ngx_http_random_index_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_random_index_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -175,7 +175,7 @@
 
         len = ngx_de_namelen(&dir);
 
-        if (!dir.valid_type) {
+        if (dir.type == 0 || ngx_de_is_link(&dir)) {
 
             /* 1 byte for '/' and 1 byte for terminating '\0' */
 
--- a/src/http/modules/ngx_http_realip_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_realip_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -25,17 +25,23 @@
     ngx_uint_t         type;
     ngx_uint_t         hash;
     ngx_str_t          header;
+#if (NGX_HAVE_UNIX_DOMAIN)
+    ngx_uint_t         unixsock; /* unsigned  unixsock:2; */
+#endif
 } ngx_http_realip_loc_conf_t;
 
 
 typedef struct {
     ngx_connection_t  *connection;
-    in_addr_t          addr;
+    struct sockaddr   *sockaddr;
+    socklen_t          socklen;
     ngx_str_t          addr_text;
 } ngx_http_realip_ctx_t;
 
 
 static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip,
+    size_t len);
 static void ngx_http_realip_cleanup(void *data);
 static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
@@ -103,13 +109,11 @@
 {
     u_char                      *ip, *p;
     size_t                       len;
-    in_addr_t                    addr;
     ngx_uint_t                   i, hash;
     ngx_list_part_t             *part;
     ngx_table_elt_t             *header;
     struct sockaddr_in          *sin;
     ngx_connection_t            *c;
-    ngx_pool_cleanup_t          *cln;
     ngx_http_realip_ctx_t       *ctx;
     ngx_http_realip_from_t      *from;
     ngx_http_realip_loc_conf_t  *rlcf;
@@ -120,14 +124,14 @@
         return NGX_DECLINED;
     }
 
-    cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
-    if (cln == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
 
-    if (rlcf->from == NULL) {
+    if (rlcf->from == NULL
+#if (NGX_HAVE_UNIX_DOMAIN)
+        && !rlcf->unixsock
+#endif
+       )
+    {
         return NGX_DECLINED;
     }
 
@@ -207,52 +211,83 @@
 
     /* AF_INET only */
 
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        return NGX_DECLINED;
+    if (c->sockaddr->sa_family == AF_INET) {
+        sin = (struct sockaddr_in *) c->sockaddr;
+
+        from = rlcf->from->elts;
+        for (i = 0; i < rlcf->from->nelts; i++) {
+
+            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                           "realip: %08XD %08XD %08XD",
+                           sin->sin_addr.s_addr, from[i].mask, from[i].addr);
+
+            if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
+                return ngx_http_realip_set_addr(r, ip, len);
+            }
+        }
+    }
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+    if (c->sockaddr->sa_family == AF_UNIX && rlcf->unixsock) {
+        return ngx_http_realip_set_addr(r, ip, len);
     }
 
-    sin = (struct sockaddr_in *) c->sockaddr;
+#endif
 
-    from = rlcf->from->elts;
-    for (i = 0; i < rlcf->from->nelts; i++) {
+    return NGX_DECLINED;
+}
 
-        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                       "realip: %08XD %08XD %08XD",
-                       sin->sin_addr.s_addr, from[i].mask, from[i].addr);
 
-        if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
-
-            ctx = cln->data;
-
-            ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
+static ngx_int_t
+ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
+{
+    u_char                 *p;
+    ngx_int_t               rc;
+    ngx_addr_t              addr;
+    ngx_connection_t       *c;
+    ngx_pool_cleanup_t     *cln;
+    ngx_http_realip_ctx_t  *ctx;
 
-            addr = inet_addr((char *) ip);
+    cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
+    if (cln == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
 
-            if (addr == INADDR_NONE) {
-                return NGX_DECLINED;
-            }
+    ctx = cln->data;
+    ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
+
+    c = r->connection;
+
+    rc = ngx_parse_addr(c->pool, &addr, ip, len);
 
-            p = ngx_pnalloc(c->pool, len);
-            if (p == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
+    switch (rc) {
+    case NGX_DECLINED:
+        return NGX_DECLINED;
+    case NGX_ERROR:
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    default: /* NGX_OK */
+        break;
+    }
 
-            ngx_memcpy(p, ip, len);
-
-            cln->handler = ngx_http_realip_cleanup;
+    p = ngx_pnalloc(c->pool, len);
+    if (p == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
 
-            ctx->connection = c;
-            ctx->addr = sin->sin_addr.s_addr;
-            ctx->addr_text = c->addr_text;
+    ngx_memcpy(p, ip, len);
 
-            sin->sin_addr.s_addr = addr;
+    cln->handler = ngx_http_realip_cleanup;
 
-            c->addr_text.len = len;
-            c->addr_text.data = p;
+    ctx->connection = c;
+    ctx->sockaddr = c->sockaddr;
+    ctx->socklen = c->socklen;
+    ctx->addr_text = c->addr_text;
 
-            return NGX_DECLINED;
-        }
-    }
+    c->sockaddr = addr.sockaddr;
+    c->socklen = addr.socklen;
+    c->addr_text.len = len;
+    c->addr_text.data = p;
 
     return NGX_DECLINED;
 }
@@ -263,14 +298,12 @@
 {
     ngx_http_realip_ctx_t *ctx = data;
 
-    ngx_connection_t    *c;
-    struct sockaddr_in  *sin;
+    ngx_connection_t  *c;
 
     c = ctx->connection;
 
-    sin = (struct sockaddr_in *) c->sockaddr;
-    sin->sin_addr.s_addr = ctx->addr;
-
+    c->sockaddr = ctx->sockaddr;
+    c->socklen = ctx->socklen;
     c->addr_text = ctx->addr_text;
 }
 
@@ -285,6 +318,17 @@
     ngx_cidr_t               cidr;
     ngx_http_realip_from_t  *from;
 
+    value = cf->args->elts;
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+    if (ngx_strcmp(value[1].data, "unix:") == 0) {
+         rlcf->unixsock = 1;
+         return NGX_CONF_OK;
+    }
+
+#endif
+
     if (rlcf->from == NULL) {
         rlcf->from = ngx_array_create(cf->pool, 2,
                                       sizeof(ngx_http_realip_from_t));
@@ -298,8 +342,6 @@
         return NGX_CONF_ERROR;
     }
 
-    value = cf->args->elts;
-
     rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
@@ -310,7 +352,7 @@
 
     if (cidr.family != AF_INET) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "\"realip_from\" supports IPv4 only");
+                           "\"set_real_ip_from\" supports IPv4 only");
         return NGX_CONF_ERROR;
     }
 
@@ -372,6 +414,9 @@
      */
 
     conf->type = NGX_CONF_UNSET_UINT;
+#if (NGX_HAVE_UNIX_DOMAIN)
+    conf->unixsock = 2;
+#endif
 
     return conf;
 }
@@ -387,6 +432,12 @@
         conf->from = prev->from;
     }
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+    if (conf->unixsock == 2) {
+        conf->unixsock = (prev->unixsock == 2) ? 0 : prev->unixsock;
+    }
+#endif
+
     ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
 
     if (conf->header.len == 0) {
--- a/src/http/modules/ngx_http_referer_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_referer_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -124,18 +124,27 @@
     len = r->headers_in.referer->value.len;
     ref = r->headers_in.referer->value.data;
 
-    if (len < sizeof("http://i.ru") - 1
-        || (ngx_strncasecmp(ref, (u_char *) "http://", 7) != 0))
-    {
-        if (rlcf->blocked_referer) {
-            goto valid;
+    if (len >= sizeof("http://i.ru") - 1) {
+        last = ref + len;
+
+        if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) {
+            ref += 7;
+            goto valid_scheme;
+
+        } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) {
+            ref += 8;
+            goto valid_scheme;
         }
-
-        goto invalid;
     }
 
-    last = ref + len;
-    ref += 7;
+    if (rlcf->blocked_referer) {
+        goto valid;
+    }
+
+    goto invalid;
+
+valid_scheme:
+
     i = 0;
     key = 0;
 
@@ -412,7 +421,7 @@
                 if (sn[n].regex) {
 
                     if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name,
-                                                   sn[n].regex)
+                                                   sn[n].regex->regex)
                         != NGX_OK)
                     {
                         return NGX_CONF_ERROR;
@@ -502,9 +511,9 @@
     ngx_str_t *name, ngx_regex_t *regex)
 {
 #if (NGX_PCRE)
-    ngx_str_t         err;
-    ngx_regex_elt_t  *re;
-    u_char            errstr[NGX_MAX_CONF_ERRSTR];
+    ngx_regex_elt_t      *re;
+    ngx_regex_compile_t   rc;
+    u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
     if (name->len == 1) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name);
@@ -530,19 +539,23 @@
         return NGX_CONF_OK;
     }
 
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
-
     name->len--;
     name->data++;
 
-    re->regex = ngx_regex_compile(name, NGX_REGEX_CASELESS, cf->pool, &err);
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
 
-    if (re->regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+    rc.pattern = *name;
+    rc.pool = cf->pool;
+    rc.options = NGX_REGEX_CASELESS;
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
+
+    if (ngx_regex_compile(&rc) != NGX_OK) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
         return NGX_CONF_ERROR;
     }
 
+    re->regex = rc.regex;
     re->name = name->data;
 
     return NGX_CONF_OK;
--- a/src/http/modules/ngx_http_rewrite_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_rewrite_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -294,9 +294,9 @@
 {
     ngx_http_rewrite_loc_conf_t  *lcf = conf;
 
-    ngx_str_t                         *value, err;
-    ngx_int_t                          n;
+    ngx_str_t                         *value;
     ngx_uint_t                         last;
+    ngx_regex_compile_t                rc;
     ngx_http_script_code_pt           *code;
     ngx_http_script_compile_t          sc;
     ngx_http_script_regex_code_t      *regex;
@@ -313,15 +313,16 @@
 
     value = cf->args->elts;
 
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+    rc.pattern = value[1];
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
 
     /* TODO: NGX_REGEX_CASELESS */
 
-    regex->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
-
+    regex->regex = ngx_http_regex_compile(cf, &rc);
     if (regex->regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
         return NGX_CONF_ERROR;
     }
 
@@ -394,7 +395,6 @@
 
     regex = sc.main;
 
-    regex->ncaptures = sc.ncaptures;
     regex->size = sc.size;
     regex->args = sc.args;
 
@@ -402,31 +402,6 @@
         regex->lengths = NULL;
     }
 
-    n = ngx_regex_capture_count(regex->regex);
-
-    if (n < 0) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           ngx_regex_capture_count_n " failed for "
-                           "pattern \"%V\"", &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    if (regex->ncaptures > (ngx_uint_t) n) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "pattern \"%V\" has less captures "
-                           "than referrenced in substitution \"%V\"",
-                           &value[1], &value[2]);
-        return NGX_CONF_ERROR;
-    }
-
-    if (regex->ncaptures < (ngx_uint_t) n) {
-        regex->ncaptures = (ngx_uint_t) n;
-    }
-
-    if (regex->ncaptures) {
-        regex->ncaptures = (regex->ncaptures + 1) * 3;
-    }
-
     regex_end = ngx_http_script_add_code(lcf->codes,
                                       sizeof(ngx_http_script_regex_end_code_t),
                                       &regex);
@@ -446,7 +421,7 @@
             return NGX_CONF_ERROR;
         }
 
-        *code = (uintptr_t) NULL;
+        *code = NULL;
     }
 
     regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
@@ -624,8 +599,9 @@
 {
     u_char                        *p;
     size_t                         len;
-    ngx_str_t                     *value, err;
-    ngx_uint_t                     cur, last, n;
+    ngx_str_t                     *value;
+    ngx_uint_t                     cur, last;
+    ngx_regex_compile_t            rc;
     ngx_http_script_code_pt       *code;
     ngx_http_script_file_code_t   *fop;
     ngx_http_script_regex_code_t  *regex;
@@ -733,15 +709,15 @@
 
             ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
 
-            err.len = NGX_MAX_CONF_ERRSTR;
-            err.data = errstr;
+            ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
 
-            regex->regex = ngx_regex_compile(&value[last],
-                                  (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0,
-                                   cf->pool, &err);
+            rc.pattern = value[last];
+            rc.options = (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0;
+            rc.err.len = NGX_MAX_CONF_ERRSTR;
+            rc.err.data = errstr;
 
+            regex->regex = ngx_http_regex_compile(cf, &rc);
             if (regex->regex == NULL) {
-                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
                 return NGX_CONF_ERROR;
             }
 
@@ -753,12 +729,6 @@
             }
             regex->name = value[last];
 
-            n = ngx_regex_capture_count(regex->regex);
-
-            if (n) {
-                regex->ncaptures = (n + 1) * 3;
-            }
-
             return NGX_CONF_OK;
         }
 
--- a/src/http/modules/ngx_http_ssi_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_ssi_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -1908,7 +1908,7 @@
 
     args.len = 0;
     args.data = NULL;
-    flags = 0;
+    flags = NGX_HTTP_LOG_UNSAFE;
 
     if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
         return NGX_HTTP_SSI_ERROR;
@@ -2061,9 +2061,9 @@
     out = data;
 
     if (!r->header_sent) {
-        if (ngx_http_set_content_type(r) != NGX_OK) {
-            return NGX_ERROR;
-        }
+        r->headers_out.content_type_len =
+                                      r->parent->headers_out.content_type_len;
+        r->headers_out.content_type = r->parent->headers_out.content_type;
 
         if (ngx_http_send_header(r) == NGX_ERROR) {
             return NGX_ERROR;
@@ -2450,27 +2450,28 @@
 
     } else {
 #if (NGX_PCRE)
-        ngx_str_t     err;
-        ngx_regex_t  *regex;
-        u_char        errstr[NGX_MAX_CONF_ERRSTR];
-
-        err.len = NGX_MAX_CONF_ERRSTR;
-        err.data = errstr;
+        ngx_regex_compile_t  rgc;
+        u_char               errstr[NGX_MAX_CONF_ERRSTR];
 
         right.data[right.len] = '\0';
 
-        regex = ngx_regex_compile(&right, 0, r->pool, &err);
-
-        if (regex == NULL) {
-            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s", err.data);
+        ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
+
+        rgc.pattern = right;
+        rgc.pool = r->pool;
+        rgc.err.len = NGX_MAX_CONF_ERRSTR;
+        rgc.err.data = errstr;
+
+        if (ngx_regex_compile(&rgc) != NGX_OK) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
             return NGX_HTTP_SSI_ERROR;
         }
 
-        rc = ngx_regex_exec(regex, &left, NULL, 0);
-
-        if (rc != NGX_REGEX_NO_MATCHED && rc < 0) {
+        rc = ngx_regex_exec(rgc.regex, &left, NULL, 0);
+
+        if (rc < NGX_REGEX_NO_MATCHED) {
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
+                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
                           rc, &left, &right);
             return NGX_HTTP_SSI_ERROR;
         }
@@ -2614,8 +2615,7 @@
             return NGX_ERROR;
         }
 
-        v->len = ngx_sprintf(v->data, "%T", tp->sec + (gmt ? 0 : tp->gmtoff))
-                 - v->data;
+        v->len = ngx_sprintf(v->data, "%T", tp->sec) - v->data;
 
         return NGX_OK;
     }
@@ -2772,8 +2772,8 @@
     ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024);
     ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256);
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_ssl_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_ssl_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -13,7 +13,7 @@
     ngx_pool_t *pool, ngx_str_t *s);
 
 
-#define NGX_DEFAULT_CIPHERS  "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
+#define NGX_DEFAULT_CIPHERS  "HIGH:!ADH:!MD5"
 
 
 static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
@@ -184,6 +184,9 @@
     { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
       (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
+    { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
+      (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
     { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
       (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
@@ -344,8 +347,7 @@
                          prev->prefer_server_ciphers, 0);
 
     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
-                         (NGX_CONF_BITMASK_SET
-                          |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
+                         (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
 
     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
@@ -406,9 +408,10 @@
                                                ngx_http_ssl_servername)
         == 0)
     {
-        ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
-                      "SSL_CTX_set_tlsext_servername_callback() failed");
-        return NGX_CONF_ERROR;
+        ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+            "nginx was built with SNI support, however, now it is linked "
+            "dynamically to an OpenSSL library which has no tlsext support, "
+            "therefore SNI is not available");
     }
 
 #endif
--- a/src/http/modules/ngx_http_static_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_static_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -91,6 +91,7 @@
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
--- a/src/http/modules/ngx_http_sub_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_sub_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -671,8 +671,8 @@
         conf->value = prev->value;
     }
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_xslt_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/ngx_http_xslt_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -1230,8 +1230,8 @@
         conf->sheets = prev->sheets;
     }
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_xslt_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/perl/nginx.pm	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/perl/nginx.pm	Thu Mar 11 21:27:17 2010 +0300
@@ -47,7 +47,7 @@
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.8.15';
+our $VERSION = '0.8.34';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/perl/nginx.xs	Thu Mar 11 21:27:17 2010 +0300
@@ -648,6 +648,7 @@
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
@@ -901,9 +902,6 @@
             XSRETURN_UNDEF;
         }
 
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "variable \"%V\" not found", &var);
-
         XSRETURN_UNDEF;
     }
 
@@ -946,6 +944,7 @@
     ngx_add_timer(r->connection->write, sleep);
 
     r->write_event_handler = ngx_http_perl_sleep_handler;
+    r->main->count++;
 
 
 void
--- a/src/http/modules/perl/ngx_http_perl_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/modules/perl/ngx_http_perl_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -13,8 +13,8 @@
 typedef struct {
     PerlInterpreter   *perl;
     HV                *nginx;
-    ngx_str_t          modules;
-    ngx_array_t        requires;
+    ngx_array_t       *modules;
+    ngx_array_t       *requires;
 } ngx_http_perl_main_conf_t;
 
 
@@ -30,12 +30,6 @@
 } ngx_http_perl_variable_t;
 
 
-typedef struct {
-    SV                *sv;
-    PerlInterpreter   *perl;
-} ngx_http_perl_cleanup_t;
-
-
 #if (NGX_HTTP_SSI)
 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
@@ -57,8 +51,6 @@
 static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf);
 static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent,
     void *child);
-static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
@@ -74,16 +66,16 @@
 
     { ngx_string("perl_modules"),
       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_str_slot,
+      ngx_conf_set_str_array_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
       offsetof(ngx_http_perl_main_conf_t, modules),
       NULL },
 
     { ngx_string("perl_require"),
       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
-      ngx_http_perl_require,
+      ngx_conf_set_str_array_slot,
       NGX_HTTP_MAIN_CONF_OFFSET,
-      0,
+      offsetof(ngx_http_perl_main_conf_t, requires),
       NULL },
 
     { ngx_string("perl"),
@@ -154,12 +146,13 @@
 #endif
 
 
-static ngx_str_t    ngx_null_name = ngx_null_string;
-
-static HV          *nginx_stash;
+static ngx_str_t         ngx_null_name = ngx_null_string;
+static HV               *nginx_stash;
 
 #if (NGX_HAVE_PERL_MULTIPLICITY)
-static ngx_uint_t   ngx_perl_term;
+static ngx_uint_t        ngx_perl_term;
+#else
+static PerlInterpreter  *perl;
 #endif
 
 
@@ -463,27 +456,42 @@
 static char *
 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
 {
+    ngx_str_t           *m;
+    ngx_uint_t           i;
 #if (NGX_HAVE_PERL_MULTIPLICITY)
-    ngx_pool_cleanup_t       *cln;
+    ngx_pool_cleanup_t  *cln;
 
     cln = ngx_pool_cleanup_add(cf->pool, 0);
     if (cln == NULL) {
         return NGX_CONF_ERROR;
     }
 
-#else
-    static PerlInterpreter  *perl;
 #endif
 
 #ifdef NGX_PERL_MODULES
-    if (pmcf->modules.data == NULL) {
-        pmcf->modules.data = NGX_PERL_MODULES;
+    if (pmcf->modules == NGX_CONF_UNSET_PTR) {
+
+        pmcf->modules = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
+        if (pmcf->modules == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        m = ngx_array_push(pmcf->modules);
+        if (m == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        m->len = sizeof(NGX_PERL_MODULES) - 1;
+        m->data = NGX_PERL_MODULES;
     }
 #endif
 
-    if (pmcf->modules.data) {
-        if (ngx_conf_full_name(cf->cycle, &pmcf->modules, 0) != NGX_OK) {
-            return NGX_CONF_ERROR;
+    if (pmcf->modules != NGX_CONF_UNSET_PTR) {
+        m = pmcf->modules->elts;
+        for (i = 0; i < pmcf->modules->nelts; i++) {
+            if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) {
+                return NGX_CONF_ERROR;
+            }
         }
     }
 
@@ -495,7 +503,7 @@
             return NGX_CONF_ERROR;
         }
 
-        if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log)
+        if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log)
             != NGX_OK)
         {
             return NGX_CONF_ERROR;
@@ -543,7 +551,9 @@
     int                n;
     STRLEN             len;
     SV                *sv;
-    char              *ver, *embedding[6];
+    char              *ver, **embedding;
+    ngx_str_t         *m;
+    ngx_uint_t         i;
     PerlInterpreter   *perl;
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter");
@@ -569,15 +579,21 @@
     PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
 #endif
 
+    n = (pmcf->modules != NGX_CONF_UNSET_PTR) ? pmcf->modules->nelts * 2 : 0;
+
+    embedding = ngx_palloc(cf->pool, (4 + n) * sizeof(char *));
+    if (embedding == NULL) {
+        goto fail;
+    }
+
     embedding[0] = "";
 
-    if (pmcf->modules.data) {
-        embedding[1] = "-I";
-        embedding[2] = (char *) pmcf->modules.data;
-        n = 3;
-
-    } else {
-        n = 1;
+    if (n++) {
+        m = pmcf->modules->elts;
+        for (i = 0; i < pmcf->modules->nelts; i++) {
+            embedding[2 * i + 1] = "-I";
+            embedding[2 * i + 2] = (char *) m[i].data;
+        }
     }
 
     embedding[n++] = "-Mnginx";
@@ -601,7 +617,7 @@
         goto fail;
     }
 
-    if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) {
+    if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) != NGX_OK) {
         goto fail;
     }
 
@@ -622,26 +638,28 @@
 static ngx_int_t
 ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log)
 {
-    char       **script;
+    u_char      *err;
     STRLEN       len;
-    ngx_str_t    err;
+    ngx_str_t   *script;
     ngx_uint_t   i;
 
+    if (requires == NGX_CONF_UNSET_PTR) {
+        return NGX_OK;
+    }
+
     script = requires->elts;
     for (i = 0; i < requires->nelts; i++) {
 
-        require_pv(script[i]);
+        require_pv((char *) script[i].data);
 
         if (SvTRUE(ERRSV)) {
 
-            err.data = (u_char *) SvPV(ERRSV, len);
-            for (len--; err.data[len] == LF || err.data[len] == CR; len--) {
-                /* void */
-            }
-            err.len = len + 1;
+            err = (u_char *) SvPV(ERRSV, len);
+            while (--len && (err[len] == CR || err[len] == LF)) { /* void */ }
 
             ngx_log_error(NGX_LOG_EMERG, log, 0,
-                          "require_pv(\"%s\") failed: \"%V\"", script[i], &err);
+                          "require_pv(\"%s\") failed: \"%*s\"",
+                          script[i].data, len + 1, err);
 
             return NGX_ERROR;
         }
@@ -658,8 +676,8 @@
     SV                *sv;
     int                n, status;
     char              *line;
+    u_char            *err;
     STRLEN             len, n_a;
-    ngx_str_t          err;
     ngx_uint_t         i;
     ngx_connection_t  *c;
 
@@ -720,14 +738,11 @@
 
     if (SvTRUE(ERRSV)) {
 
-        err.data = (u_char *) SvPV(ERRSV, len);
-        for (len--; err.data[len] == LF || err.data[len] == CR; len--) {
-            /* void */
-        }
-        err.len = len + 1;
+        err = (u_char *) SvPV(ERRSV, len);
+        while (--len && (err[len] == CR || err[len] == LF)) { /* void */ }
 
         ngx_log_error(NGX_LOG_ERR, c->log, 0,
-                      "call_sv(\"%V\") failed: \"%V\"", handler, &err);
+                      "call_sv(\"%V\") failed: \"%*s\"", handler, len + 1, err);
 
         if (rv) {
             return NGX_ERROR;
@@ -761,7 +776,10 @@
         }
     }
 
-    if (ngx_strncmp(p, "sub ", 4) == 0 || ngx_strncmp(p, "use ", 4) == 0) {
+    if (ngx_strncmp(p, "sub ", 4) == 0
+        || ngx_strncmp(p, "sub{", 4) == 0
+        || ngx_strncmp(p, "use ", 4) == 0)
+    {
         *sv = eval_pv((char *) p, FALSE);
 
         /* eval_pv() does not set ERRSV on failure */
@@ -783,11 +801,8 @@
         return NULL;
     }
 
-    if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *))
-        != NGX_OK)
-    {
-        return NULL;
-    }
+    pmcf->modules = NGX_CONF_UNSET_PTR;
+    pmcf->requires = NGX_CONF_UNSET_PTR;
 
     return pmcf;
 }
@@ -894,28 +909,6 @@
 
 
 static char *
-ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_perl_main_conf_t *pmcf = conf;
-
-    u_char     **p;
-    ngx_str_t   *value;
-
-    value = cf->args->elts;
-
-    p = ngx_array_push(&pmcf->requires);
-
-    if (p == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    *p = value[1].data;
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
 ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_perl_loc_conf_t *plcf = conf;
@@ -1064,19 +1057,21 @@
 {
 #if (NGX_HAVE_PERL_MULTIPLICITY)
 
+    /*
+     * the master exit hook is run before global pool cleanup,
+     * therefore just set flag here
+     */
+
     ngx_perl_term = 1;
 
 #else
-    ngx_http_perl_main_conf_t  *pmcf;
 
-    pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module);
-
-    if (pmcf && nginx_stash) {
+    if (nginx_stash) {
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "perl term");
 
-        (void) perl_destruct(pmcf->perl);
+        (void) perl_destruct(perl);
 
-        perl_free(pmcf->perl);
+        perl_free(perl);
 
         PERL_SYS_TERM();
     }
--- a/src/http/ngx_http.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http.c	Thu Mar 11 21:27:17 2010 +0300
@@ -17,18 +17,13 @@
 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
     ngx_http_core_main_conf_t *cmcf);
 
-static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
-    ngx_array_t *servers, ngx_array_t *ports);
-static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf,
-    ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports,
-    ngx_http_listen_t *listen);
 static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
-    ngx_http_listen_t *listen);
+    ngx_http_listen_opt_t *lsopt);
 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
-    ngx_http_listen_t *listen);
-static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
+    ngx_http_listen_opt_t *lsopt);
+static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
 
 static char *ngx_http_merge_locations(ngx_conf_t *cf,
@@ -122,7 +117,6 @@
     char                        *rv;
     ngx_uint_t                   mi, m, s;
     ngx_conf_t                   pcf;
-    ngx_array_t                  ports;
     ngx_http_module_t           *module;
     ngx_http_conf_ctx_t         *ctx;
     ngx_http_core_loc_conf_t    *clcf;
@@ -362,19 +356,9 @@
     }
 
 
-    /*
-     * create the lists of ports, addresses and server names
-     * to find quickly the server core module configuration at run-time
-     */
-
-    if (ngx_http_init_server_lists(cf, &cmcf->servers, &ports) != NGX_OK) {
-        return NGX_CONF_ERROR;
-    }
-
-
     /* optimize the lists of ports, addresses and server names */
 
-    if (ngx_http_optimize_servers(cf, cmcf, &ports) != NGX_OK) {
+    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
 
@@ -1109,72 +1093,55 @@
 }
 
 
-static ngx_int_t
-ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
-    ngx_array_t *ports)
+ngx_int_t
+ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+    ngx_http_listen_opt_t *lsopt)
 {
-    ngx_uint_t                  s, i;
-    ngx_http_listen_t          *listen;
-    ngx_http_core_srv_conf_t  **cscfp;
-
-    if (ngx_array_init(ports, cf->temp_pool, 2, sizeof(ngx_http_conf_port_t))
-        != NGX_OK)
-    {
-        return NGX_ERROR;
-    }
+    in_port_t                   p;
+    ngx_uint_t                  i;
+    struct sockaddr            *sa;
+    struct sockaddr_in         *sin;
+    ngx_http_conf_port_t       *port;
+    ngx_http_core_main_conf_t  *cmcf;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6        *sin6;
+#endif
 
-    /* "server" directives */
-
-    cscfp = servers->elts;
-    for (s = 0; s < servers->nelts; s++) {
-
-        /* "listen" directives */
+    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
 
-        listen = cscfp[s]->listen.elts;
-        for (i = 0; i < cscfp[s]->listen.nelts; i++) {
-
-            if (ngx_http_add_ports(cf, cscfp[s], ports, &listen[i]) != NGX_OK) {
-                return NGX_ERROR;
-            }
+    if (cmcf->ports == NULL) {
+        cmcf->ports = ngx_array_create(cf->temp_pool, 2,
+                                       sizeof(ngx_http_conf_port_t));
+        if (cmcf->ports == NULL) {
+            return NGX_ERROR;
         }
     }
 
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
-    ngx_array_t *ports, ngx_http_listen_t *listen)
-{
-    in_port_t                 p;
-    ngx_uint_t                i;
-    struct sockaddr          *sa;
-    struct sockaddr_in       *sin;
-    ngx_http_conf_port_t     *port;
-#if (NGX_HAVE_INET6)
-    struct sockaddr_in6      *sin6;
-#endif
-
-    sa = (struct sockaddr *) &listen->sockaddr;
+    sa = &lsopt->u.sockaddr;
 
     switch (sa->sa_family) {
 
 #if (NGX_HAVE_INET6)
     case AF_INET6:
-        sin6 = (struct sockaddr_in6 *) sa;
+        sin6 = &lsopt->u.sockaddr_in6;
         p = sin6->sin6_port;
         break;
 #endif
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+    case AF_UNIX:
+        p = 0;
+        break;
+#endif
+
     default: /* AF_INET */
-        sin = (struct sockaddr_in *) sa;
+        sin = &lsopt->u.sockaddr_in;
         p = sin->sin_port;
         break;
     }
 
-    port = ports->elts;
-    for (i = 0; i < ports->nelts; i++) {
+    port = cmcf->ports->elts;
+    for (i = 0; i < cmcf->ports->nelts; i++) {
 
         if (p != port[i].port || sa->sa_family != port[i].family) {
             continue;
@@ -1182,12 +1149,12 @@
 
         /* a port is already in the port list */
 
-        return ngx_http_add_addresses(cf, cscf, &port[i], listen);
+        return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
     }
 
     /* add a port to the port list */
 
-    port = ngx_array_push(ports);
+    port = ngx_array_push(cmcf->ports);
     if (port == NULL) {
         return NGX_ERROR;
     }
@@ -1196,26 +1163,29 @@
     port->port = p;
     port->addrs.elts = NULL;
 
-    return ngx_http_add_address(cf, cscf, port, listen);
+    return ngx_http_add_address(cf, cscf, port, lsopt);
 }
 
 
 static ngx_int_t
 ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
-    ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
+    ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
 {
     u_char                *p;
     size_t                 len, off;
-    ngx_uint_t             i;
+    ngx_uint_t             i, default_server;
     struct sockaddr       *sa;
     ngx_http_conf_addr_t  *addr;
+#if (NGX_HAVE_UNIX_DOMAIN)
+    struct sockaddr_un    *saun;
+#endif
 
     /*
      * we can not compare whole sockaddr struct's as kernel
      * may fill some fields in inherited sockaddr struct's
      */
 
-    sa = (struct sockaddr *) &listen->sockaddr;
+    sa = &lsopt->u.sockaddr;
 
     switch (sa->sa_family) {
 
@@ -1226,54 +1196,71 @@
         break;
 #endif
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+    case AF_UNIX:
+        off = offsetof(struct sockaddr_un, sun_path);
+        len = sizeof(saun->sun_path);
+        break;
+#endif
+
     default: /* AF_INET */
         off = offsetof(struct sockaddr_in, sin_addr);
         len = 4;
         break;
     }
 
-    p = listen->sockaddr + off;
+    p = lsopt->u.sockaddr_data + off;
 
     addr = port->addrs.elts;
 
     for (i = 0; i < port->addrs.nelts; i++) {
 
-        if (ngx_memcmp(p, (u_char *) addr[i].sockaddr + off, len) != 0) {
+        if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) {
             continue;
         }
 
         /* the address is already in the address list */
 
-        if (ngx_http_add_names(cf, cscf, &addr[i]) != NGX_OK) {
+        if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
             return NGX_ERROR;
         }
 
+        /* preserve default_server bit during listen options overwriting */
+        default_server = addr[i].opt.default_server;
+
+        if (lsopt->set) {
+
+            if (addr[i].opt.set) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                        "a duplicate listen options for %s", addr[i].opt.addr);
+                return NGX_ERROR;
+            }
+
+            addr[i].opt = *lsopt;
+        }
+
         /* check the duplicate "default" server for this address:port */
 
-        if (listen->conf.default_server) {
+        if (lsopt->default_server) {
 
-            if (addr[i].default_server) {
-                ngx_log_error(NGX_LOG_ERR, cf->log, 0,
-                              "the duplicate default server in %s:%ui",
-                               listen->file_name, listen->line);
-
+            if (default_server) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                        "a duplicate default server for %s", addr[i].opt.addr);
                 return NGX_ERROR;
             }
 
-            addr[i].core_srv_conf = cscf;
-            addr[i].default_server = 1;
-#if (NGX_HTTP_SSL)
-            addr[i].ssl = listen->conf.ssl;
-#endif
-            addr[i].listen_conf = &listen->conf;
+            default_server = 1;
+            addr[i].default_server = cscf;
         }
 
+        addr[i].opt.default_server = default_server;
+
         return NGX_OK;
     }
 
     /* add the address to the addresses list that bound to this port */
 
-    return ngx_http_add_address(cf, cscf, port, listen);
+    return ngx_http_add_address(cf, cscf, port, lsopt);
 }
 
 
@@ -1284,7 +1271,7 @@
 
 static ngx_int_t
 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
-    ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
+    ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
 {
     ngx_http_conf_addr_t  *addr;
 
@@ -1302,68 +1289,56 @@
         return NGX_ERROR;
     }
 
-    addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
-    addr->socklen = listen->socklen;
+    addr->opt = *lsopt;
     addr->hash.buckets = NULL;
     addr->hash.size = 0;
     addr->wc_head = NULL;
     addr->wc_tail = NULL;
-    addr->names.elts = NULL;
 #if (NGX_PCRE)
     addr->nregex = 0;
     addr->regex = NULL;
 #endif
-    addr->core_srv_conf = cscf;
-    addr->default_server = listen->conf.default_server;
-    addr->bind = listen->conf.bind;
-    addr->wildcard = listen->conf.wildcard;
-#if (NGX_HTTP_SSL)
-    addr->ssl = listen->conf.ssl;
-#endif
-    addr->listen_conf = &listen->conf;
+    addr->default_server = cscf;
+    addr->servers.elts = NULL;
 
-    return ngx_http_add_names(cf, cscf, addr);
+    return ngx_http_add_server(cf, cscf, addr);
 }
 
 
-/*
- * add the server names and the server core module
- * configurations to the address:port
- */
+/* add the server core module configuration to the address:port */
 
 static ngx_int_t
-ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
     ngx_http_conf_addr_t *addr)
 {
-    ngx_uint_t               i;
-    ngx_http_server_name_t  *server_names, *name;
+    ngx_uint_t                  i;
+    ngx_http_core_srv_conf_t  **server;
 
-    if (addr->names.elts == NULL) {
-        if (ngx_array_init(&addr->names, cf->temp_pool, 4,
-                           sizeof(ngx_http_server_name_t))
+    if (addr->servers.elts == NULL) {
+        if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
+                           sizeof(ngx_http_core_srv_conf_t *))
             != NGX_OK)
         {
             return NGX_ERROR;
         }
+
+    } else {
+        server = addr->servers.elts;
+        for (i = 0; i < addr->servers.nelts; i++) {
+            if (server[i] == cscf) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "a duplicate listen %s", addr->opt.addr);
+                return NGX_ERROR;
+            }
+        }
     }
 
-    server_names = cscf->server_names.elts;
-
-    for (i = 0; i < cscf->server_names.nelts; i++) {
-
-        ngx_strlow(server_names[i].name.data, server_names[i].name.data,
-                   server_names[i].name.len);
+    server = ngx_array_push(&addr->servers);
+    if (server == NULL) {
+        return NGX_ERROR;
+    }
 
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
-                       "name: %V", &server_names[i].name);
-
-        name = ngx_array_push(&addr->names);
-        if (name == NULL) {
-            return NGX_ERROR;
-        }
-
-        *name = server_names[i];
-    }
+    *server = cscf;
 
     return NGX_OK;
 }
@@ -1373,10 +1348,13 @@
 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
     ngx_array_t *ports)
 {
-    ngx_uint_t               s, p, a;
-    ngx_http_conf_port_t    *port;
-    ngx_http_conf_addr_t    *addr;
-    ngx_http_server_name_t  *name;
+    ngx_uint_t             p, a;
+    ngx_http_conf_port_t  *port;
+    ngx_http_conf_addr_t  *addr;
+
+    if (ports == NULL) {
+        return NGX_OK;
+    }
 
     port = ports->elts;
     for (p = 0; p < ports->nelts; p++) {
@@ -1392,23 +1370,15 @@
         addr = port[p].addrs.elts;
         for (a = 0; a < port[p].addrs.nelts; a++) {
 
-            name = addr[a].names.elts;
-            for (s = 0; s < addr[a].names.nelts; s++) {
-
-                if (addr[a].core_srv_conf == name[s].core_srv_conf
+            if (addr[a].servers.nelts > 1
 #if (NGX_PCRE)
-                    && name[s].captures == 0
+                || addr[a].default_server->captures
 #endif
-                    )
-                {
-                    continue;
-                }
-
+               )
+            {
                 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
                     return NGX_ERROR;
                 }
-
-                break;
             }
         }
 
@@ -1425,13 +1395,14 @@
 ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
     ngx_http_conf_addr_t *addr)
 {
-    ngx_int_t                rc;
-    ngx_uint_t               s;
-    ngx_hash_init_t          hash;
-    ngx_hash_keys_arrays_t   ha;
-    ngx_http_server_name_t  *name;
+    ngx_int_t                   rc;
+    ngx_uint_t                  n, s;
+    ngx_hash_init_t             hash;
+    ngx_hash_keys_arrays_t      ha;
+    ngx_http_server_name_t     *name;
+    ngx_http_core_srv_conf_t  **cscfp;
 #if (NGX_PCRE)
-    ngx_uint_t               regex, i;
+    ngx_uint_t                  regex, i;
 
     regex = 0;
 #endif
@@ -1449,35 +1420,40 @@
         goto failed;
     }
 
-    name = addr->names.elts;
+    cscfp = addr->servers.elts;
+
+    for (s = 0; s < addr->servers.nelts; s++) {
 
-    for (s = 0; s < addr->names.nelts; s++) {
+        name = cscfp[s]->server_names.elts;
+
+        for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
 
 #if (NGX_PCRE)
-        if (name[s].regex) {
-            regex++;
-            continue;
-        }
+            if (name[n].regex) {
+                regex++;
+                continue;
+            }
 #endif
 
-        rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
-                              NGX_HASH_WILDCARD_KEY);
+            rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
+                                  NGX_HASH_WILDCARD_KEY);
 
-        if (rc == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+            if (rc == NGX_ERROR) {
+                return NGX_ERROR;
+            }
 
-        if (rc == NGX_DECLINED) {
-            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "invalid server name or wildcard \"%V\" on %s",
-                          &name[s].name, addr->listen_conf->addr);
-            return NGX_ERROR;
-        }
+            if (rc == NGX_DECLINED) {
+                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                              "invalid server name or wildcard \"%V\" on %s",
+                              &name[n].name, addr->opt.addr);
+                return NGX_ERROR;
+            }
 
-        if (rc == NGX_BUSY) {
+            if (rc == NGX_BUSY) {
             ngx_log_error(NGX_LOG_WARN, cf->log, 0,
-                          "conflicting server name \"%V\" on %s, ignored",
-                          &name[s].name, addr->listen_conf->addr);
+                              "conflicting server name \"%V\" on %s, ignored",
+                              &name[n].name, addr->opt.addr);
+            }
         }
     }
 
@@ -1546,9 +1522,16 @@
         return NGX_ERROR;
     }
 
-    for (i = 0, s = 0; s < addr->names.nelts; s++) {
-        if (name[s].regex) {
-            addr->regex[i++] = name[s];
+    i = 0;
+
+    for (s = 0; s < addr->servers.nelts; s++) {
+
+        name = cscfp[s]->server_names.elts;
+
+        for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
+            if (name[n].regex) {
+                addr->regex[i++] = name[n];
+            }
         }
     }
 
@@ -1572,17 +1555,17 @@
     first = (ngx_http_conf_addr_t *) one;
     second = (ngx_http_conf_addr_t *) two;
 
-    if (first->wildcard) {
+    if (first->opt.wildcard) {
         /* a wildcard address must be the last resort, shift it to the end */
         return 1;
     }
 
-    if (first->bind && !second->bind) {
+    if (first->opt.bind && !second->opt.bind) {
         /* shift explicit bind()ed addresses to the start */
         return -1;
     }
 
-    if (!first->bind && second->bind) {
+    if (!first->opt.bind && second->opt.bind) {
         /* shift explicit bind()ed addresses to the start */
         return 1;
     }
@@ -1623,8 +1606,8 @@
      * implicit bindings go, and wildcard binding is in the end.
      */
 
-    if (addr[last - 1].wildcard) {
-        addr[last - 1].bind = 1;
+    if (addr[last - 1].opt.wildcard) {
+        addr[last - 1].opt.bind = 1;
         bind_wildcard = 1;
 
     } else {
@@ -1635,7 +1618,7 @@
 
     while (i < last) {
 
-        if (bind_wildcard && !addr[i].bind) {
+        if (bind_wildcard && !addr[i].opt.bind) {
             i++;
             continue;
         }
@@ -1691,7 +1674,7 @@
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
 
-    ls = ngx_create_listening(cf, addr->sockaddr, addr->socklen);
+    ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
     if (ls == NULL) {
         return NULL;
     }
@@ -1700,7 +1683,7 @@
 
     ls->handler = ngx_http_init_connection;
 
-    cscf = addr->core_srv_conf;
+    cscf = addr->default_server;
     ls->pool_size = cscf->connection_pool_size;
     ls->post_accept_timeout = cscf->client_header_timeout;
 
@@ -1721,20 +1704,20 @@
     }
 #endif
 
-    ls->backlog = addr->listen_conf->backlog;
-    ls->rcvbuf = addr->listen_conf->rcvbuf;
-    ls->sndbuf = addr->listen_conf->sndbuf;
+    ls->backlog = addr->opt.backlog;
+    ls->rcvbuf = addr->opt.rcvbuf;
+    ls->sndbuf = addr->opt.sndbuf;
 
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
-    ls->accept_filter = addr->listen_conf->accept_filter;
+    ls->accept_filter = addr->opt.accept_filter;
 #endif
 
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
-    ls->deferred_accept = addr->listen_conf->deferred_accept;
+    ls->deferred_accept = addr->opt.deferred_accept;
 #endif
 
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
-    ls->ipv6only = addr->listen_conf->ipv6only;
+    ls->ipv6only = addr->opt.ipv6only;
 #endif
 
     return ls;
@@ -1760,11 +1743,11 @@
 
     for (i = 0; i < hport->naddrs; i++) {
 
-        sin = (struct sockaddr_in *) addr[i].sockaddr;
+        sin = &addr[i].opt.u.sockaddr_in;
         addrs[i].addr = sin->sin_addr.s_addr;
-        addrs[i].conf.core_srv_conf = addr[i].core_srv_conf;
+        addrs[i].conf.default_server = addr[i].default_server;
 #if (NGX_HTTP_SSL)
-        addrs[i].conf.ssl = addr[i].ssl;
+        addrs[i].conf.ssl = addr[i].opt.ssl;
 #endif
 
         if (addr[i].hash.buckets == NULL
@@ -1821,11 +1804,11 @@
 
     for (i = 0; i < hport->naddrs; i++) {
 
-        sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
+        sin6 = &addr[i].opt.u.sockaddr_in6;
         addrs6[i].addr6 = sin6->sin6_addr;
-        addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf;
+        addrs6[i].conf.default_server = addr[i].default_server;
 #if (NGX_HTTP_SSL)
-        addrs6[i].conf.ssl = addr[i].ssl;
+        addrs6[i].conf.ssl = addr[i].opt.ssl;
 #endif
 
         if (addr[i].hash.buckets == NULL
@@ -1871,6 +1854,10 @@
 
     types = (ngx_array_t **) (p + cmd->offset);
 
+    if (*types == (void *) -1) {
+        return NGX_CONF_OK;
+    }
+
     default_type = cmd->post;
 
     if (*types == NULL) {
@@ -1896,6 +1883,11 @@
 
     for (i = 1; i < cf->args->nelts; i++) {
 
+        if (value[i].len == 1 && value[i].data[0] == '*') {
+            *types = (void *) -1;
+            return NGX_CONF_OK;
+        }
+
         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
         value[i].data[value[i].len] = '\0';
 
@@ -1924,13 +1916,17 @@
 
 
 char *
-ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
-    ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
+ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
+    ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
     ngx_str_t *default_types)
 {
     ngx_hash_init_t  hash;
 
-    if (keys) {
+    if (*keys) {
+
+        if (*keys == (void *) -1) {
+            return NGX_CONF_OK;
+        }
 
         hash.hash = types_hash;
         hash.key = NULL;
@@ -1940,7 +1936,7 @@
         hash.pool = cf->pool;
         hash.temp_pool = NULL;
 
-        if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
+        if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
 
@@ -1949,13 +1945,17 @@
 
     if (prev_types_hash->buckets == NULL) {
 
-        if (prev_keys == NULL) {
+        if (*prev_keys == NULL) {
 
-            if (ngx_http_set_default_types(cf, &prev_keys, default_types)
+            if (ngx_http_set_default_types(cf, prev_keys, default_types)
                 != NGX_OK)
             {
                 return NGX_CONF_ERROR;
             }
+
+        } else if (*prev_keys == (void *) -1) {
+            *keys = *prev_keys;
+            return NGX_CONF_OK;
         }
 
         hash.hash = prev_types_hash;
@@ -1966,7 +1966,9 @@
         hash.pool = cf->pool;
         hash.temp_pool = NULL;
 
-        if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
+        if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
+            != NGX_OK)
+        {
             return NGX_CONF_ERROR;
         }
     }
--- a/src/http/ngx_http.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http.h	Thu Mar 11 21:27:17 2010 +0300
@@ -57,6 +57,8 @@
 
 ngx_int_t ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
     ngx_http_core_loc_conf_t *clcf);
+ngx_int_t ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+    ngx_http_listen_opt_t *lsopt);
 
 
 void ngx_http_init_connection(ngx_connection_t *c);
@@ -92,7 +94,7 @@
 void ngx_http_request_empty_handler(ngx_http_request_t *r);
 
 
-#define ngx_http_ephemeral(r)  (ngx_http_ephemeral_t *) (&r->uri_start)
+#define ngx_http_ephemeral(r)  (void *) (&r->uri_start)
 
 
 #define NGX_HTTP_LAST   1
@@ -118,14 +120,15 @@
 
 
 ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r);
+void ngx_http_discarded_request_body_handler(ngx_http_request_t *r);
 void ngx_http_block_reading(ngx_http_request_t *r);
 void ngx_http_test_reading(ngx_http_request_t *r);
 
 
 char *ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-char *ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys,
-    ngx_hash_t *types_hash, ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
-    ngx_str_t *default_types);
+char *ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys,
+    ngx_hash_t *types_hash, ngx_array_t **prev_keys,
+    ngx_hash_t *prev_types_hash, ngx_str_t *default_types);
 ngx_int_t ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
     ngx_str_t *default_type);
 
--- a/src/http/ngx_http_copy_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_copy_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -118,7 +118,7 @@
         ctx->filter_ctx = r;
 
 #if (NGX_HAVE_FILE_AIO)
-        if (clcf->aio) {
+        if (ngx_file_aio && clcf->aio) {
             ctx->aio_handler = ngx_http_copy_aio_handler;
 #if (NGX_HAVE_AIO_SENDFILE)
             c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE);
--- a/src/http/ngx_http_core_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_core_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -408,6 +408,13 @@
 
 #endif
 
+    { ngx_string("read_ahead"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, read_ahead),
+      NULL },
+
     { ngx_string("directio"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_core_directio,
@@ -776,14 +783,24 @@
             break;
         }
 
-        if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
-
-            /*
-             * MSIE may wait for some time if an response for
-             * a POST request was sent over a keepalive connection
-             */
-
-            r->keepalive = 0;
+        if (r->keepalive) {
+
+            if (r->headers_in.msie6) {
+                if (r->method == NGX_HTTP_POST) {
+                    /*
+                     * MSIE may wait for some time if an response for
+                     * a POST request was sent over a keepalive connection
+                     */
+                    r->keepalive = 0;
+                }
+
+            } else if (r->headers_in.safari) {
+                /*
+                 * Safari may send a POST request to a closed keepalive
+                 * connection and stalls for some time
+                 */
+                r->keepalive = 0;
+            }
         }
 
         if (r->headers_in.content_length_n > 0) {
@@ -805,7 +822,11 @@
     }
 
     r->valid_location = 1;
-    r->gzip = 0;
+#if (NGX_HTTP_GZIP)
+    r->gzip_tested = 0;
+    r->gzip_ok = 0;
+    r->gzip_vary = 0;
+#endif
 
     r->write_event_handler = ngx_http_core_run_phases;
     ngx_http_core_run_phases(r);
@@ -994,7 +1015,6 @@
                       "rewrite or internal redirection cycle "
                       "while processing \"%V\"", &r->uri);
 
-        r->main->count++;
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return NGX_OK;
     }
@@ -1233,7 +1253,10 @@
         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
             != NGX_OK)
         {
-            if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
+            if (of.err != NGX_ENOENT
+                && of.err != NGX_ENOTDIR
+                && of.err != NGX_ENAMETOOLONG)
+            {
                 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
                               "%s \"%s\" failed", of.failed, path.data);
             }
@@ -1407,7 +1430,7 @@
     ngx_int_t                  rc;
     ngx_http_core_loc_conf_t  *pclcf;
 #if (NGX_PCRE)
-    ngx_int_t                  n, len;
+    ngx_int_t                  n;
     ngx_uint_t                 noregex;
     ngx_http_core_loc_conf_t  *clcf, **clcfp;
 
@@ -1441,51 +1464,28 @@
 
     if (noregex == 0 && pclcf->regex_locations) {
 
-        len = 0;
-
         for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
 
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                            "test location: ~ \"%V\"", &(*clcfp)->name);
 
-            if ((*clcfp)->captures) {
-
-                len = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
-
-                if (r->captures == NULL) {
-                    r->captures = ngx_palloc(r->pool, len * sizeof(int));
-                    if (r->captures == NULL) {
-                        return NGX_ERROR;
-                    }
-                }
+            n = ngx_http_regex_exec(r, (*clcfp)->regex, &r->uri);
+
+            if (n == NGX_OK) {
+                r->loc_conf = (*clcfp)->loc_conf;
+
+                /* look up nested locations */
+
+                rc = ngx_http_core_find_location(r);
+
+                return (rc == NGX_ERROR) ? rc : NGX_OK;
             }
 
-            n = ngx_regex_exec((*clcfp)->regex, &r->uri, r->captures, len);
-
-            if (n == NGX_REGEX_NO_MATCHED) {
+            if (n == NGX_DECLINED) {
                 continue;
             }
 
-            if (n < 0) {
-                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                              ngx_regex_exec_n
-                              " failed: %d on \"%V\" using \"%V\"",
-                              n, &r->uri, &(*clcfp)->name);
-                return NGX_ERROR;
-            }
-
-            /* match */
-
-            r->loc_conf = (*clcfp)->loc_conf;
-
-            r->ncaptures = len;
-            r->captures_data = r->uri.data;
-
-            /* look up nested locations */
-
-            rc = ngx_http_core_find_location(r);
-
-            return (rc == NGX_ERROR) ? rc : NGX_OK;
+            return NGX_ERROR;
         }
     }
 #endif
@@ -1582,6 +1582,10 @@
     size_t      len;
     ngx_uint_t  i, hash;
 
+    if (types_hash->size == 0) {
+        return (void *) 4;
+    }
+
     if (r->headers_out.content_type.len == 0) {
         return NULL;
     }
@@ -1765,7 +1769,7 @@
 #if (NGX_PCRE)
         ngx_uint_t  captures;
 
-        captures = alias && clcf->captures;
+        captures = alias && clcf->regex;
         reserved += captures ? 1 : r->uri.len - alias + 1;
 #else
         reserved += r->uri.len - alias + 1;
@@ -1882,15 +1886,7 @@
     ngx_table_elt_t           *e, *d;
     ngx_http_core_loc_conf_t  *clcf;
 
-    if (r->gzip == 1) {
-        return NGX_OK;
-    }
-
-    if (r->gzip == 2) {
-        return NGX_DECLINED;
-    }
-
-    r->gzip = 2;
+    r->gzip_tested = 1;
 
     if (r != r->main
         || r->headers_in.accept_encoding == NULL
@@ -2025,7 +2021,7 @@
 
 #endif
 
-    r->gzip = 1;
+    r->gzip_ok = 1;
 
     return NGX_OK;
 }
@@ -2591,26 +2587,27 @@
     ngx_str_t *regex, ngx_uint_t caseless)
 {
 #if (NGX_PCRE)
-    ngx_str_t  err;
-    u_char     errstr[NGX_MAX_CONF_ERRSTR];
-
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
+    ngx_regex_compile_t  rc;
+    u_char               errstr[NGX_MAX_CONF_ERRSTR];
+
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+    rc.pattern = *regex;
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
 
 #if (NGX_HAVE_CASELESS_FILESYSTEM)
-    caseless = 1;
+    rc.options = NGX_REGEX_CASELESS;
+#else
+    rc.options = caseless;
 #endif
 
-    clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
-                                    cf->pool, &err);
-
+    clcf->regex = ngx_http_regex_compile(cf, &rc);
     if (clcf->regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
         return NGX_ERROR;
     }
 
     clcf->name = *regex;
-    clcf->captures = (ngx_regex_capture_count(clcf->regex) > 0);
 
     return NGX_OK;
 
@@ -2628,14 +2625,14 @@
 static char *
 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     char        *rv;
     ngx_conf_t   save;
 
-    if (lcf->types == NULL) {
-        lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
-        if (lcf->types == NULL) {
+    if (clcf->types == NULL) {
+        clcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
+        if (clcf->types == NULL) {
             return NGX_CONF_ERROR;
         }
     }
@@ -2655,7 +2652,7 @@
 static char *
 ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     ngx_str_t       *value, *content_type, *old, file;
     ngx_uint_t       i, n, hash;
@@ -2686,8 +2683,8 @@
 
         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
 
-        type = lcf->types->elts;
-        for (n = 0; n < lcf->types->nelts; n++) {
+        type = clcf->types->elts;
+        for (n = 0; n < clcf->types->nelts; n++) {
             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
                 old = type[n].value;
                 type[n].value = content_type;
@@ -2702,7 +2699,7 @@
         }
 
 
-        type = ngx_array_push(lcf->types);
+        type = ngx_array_push(clcf->types);
         if (type == NULL) {
             return NGX_CONF_ERROR;
         }
@@ -2778,6 +2775,10 @@
     cmcf->variables_hash_bucket_size =
                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
 
+    if (cmcf->ncaptures) {
+        cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
+    }
+
     return NGX_CONF_OK;
 }
 
@@ -2798,13 +2799,6 @@
      *     conf->client_large_buffers.num = 0;
      */
 
-    if (ngx_array_init(&cscf->listen, cf->temp_pool, 4,
-                       sizeof(ngx_http_listen_t))
-        != NGX_OK)
-    {
-        return NULL;
-    }
-
     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
                        sizeof(ngx_http_server_name_t))
         != NGX_OK)
@@ -2830,58 +2824,12 @@
     ngx_http_core_srv_conf_t *prev = parent;
     ngx_http_core_srv_conf_t *conf = child;
 
-    ngx_http_listen_t       *ls;
     struct sockaddr_in      *sin;
+    ngx_http_listen_opt_t    lsopt;
     ngx_http_server_name_t  *sn;
 
     /* TODO: it does not merge, it inits only */
 
-    if (conf->listen.nelts == 0) {
-        ls = ngx_array_push(&conf->listen);
-        if (ls == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        ngx_memzero(ls, sizeof(ngx_http_listen_t));
-
-        sin = (struct sockaddr_in *) &ls->sockaddr;
-
-        sin->sin_family = AF_INET;
-#if (NGX_WIN32)
-        sin->sin_port = htons(80);
-#else
-        sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
-#endif
-        sin->sin_addr.s_addr = INADDR_ANY;
-
-        ls->socklen = sizeof(struct sockaddr_in);
-
-        ls->conf.backlog = NGX_LISTEN_BACKLOG;
-        ls->conf.rcvbuf = -1;
-        ls->conf.sndbuf = -1;
-        ls->conf.wildcard = 1;
-
-        (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr,
-                             NGX_SOCKADDR_STRLEN, 1);
-    }
-
-    if (conf->server_name.data == NULL) {
-        conf->server_name = cf->cycle->hostname;
-
-        sn = ngx_array_push(&conf->server_names);
-        if (sn == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-#if (NGX_PCRE)
-        sn->regex = NULL;
-        sn->captures = 0;
-#endif
-        sn->core_srv_conf = conf;
-        sn->name.len = conf->server_name.len;
-        sn->name.data = conf->server_name.data;
-    }
-
     ngx_conf_merge_size_value(conf->connection_pool_size,
                               prev->connection_pool_size, 256);
     ngx_conf_merge_size_value(conf->request_pool_size,
@@ -2892,7 +2840,7 @@
                               prev->client_header_buffer_size, 1024);
     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
                               prev->large_client_header_buffers,
-                              4, ngx_pagesize);
+                              4, 8192);
 
     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -2909,6 +2857,50 @@
     ngx_conf_merge_value(conf->underscores_in_headers,
                               prev->underscores_in_headers, 0);
 
+    if (!conf->listen) {
+        ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
+
+        sin = &lsopt.u.sockaddr_in;
+
+        sin->sin_family = AF_INET;
+#if (NGX_WIN32)
+        sin->sin_port = htons(80);
+#else
+        sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
+#endif
+        sin->sin_addr.s_addr = INADDR_ANY;
+
+        lsopt.socklen = sizeof(struct sockaddr_in);
+
+        lsopt.backlog = NGX_LISTEN_BACKLOG;
+        lsopt.rcvbuf = -1;
+        lsopt.sndbuf = -1;
+        lsopt.wildcard = 1;
+
+        (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
+                             NGX_SOCKADDR_STRLEN, 1);
+
+        if (ngx_http_add_listen(cf, conf, &lsopt) == NGX_OK) {
+            return NGX_CONF_OK;
+        }
+    }
+
+    if (conf->server_name.data == NULL) {
+        conf->server_name = cf->cycle->hostname;
+
+        sn = ngx_array_push(&conf->server_names);
+        if (sn == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+#if (NGX_PCRE)
+        sn->regex = NULL;
+#endif
+        sn->server = conf;
+        sn->name.len = conf->server_name.len;
+        sn->name.data = conf->server_name.data;
+    }
+
     return NGX_CONF_OK;
 }
 
@@ -2916,88 +2908,89 @@
 static void *
 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
 {
-    ngx_http_core_loc_conf_t  *lcf;
-
-    lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
-    if (lcf == NULL) {
+    ngx_http_core_loc_conf_t  *clcf;
+
+    clcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
+    if (clcf == NULL) {
         return NULL;
     }
 
     /*
      * set by ngx_pcalloc():
      *
-     *     lcf->root = { 0, NULL };
-     *     lcf->limit_except = 0;
-     *     lcf->post_action = { 0, NULL };
-     *     lcf->types = NULL;
-     *     lcf->default_type = { 0, NULL };
-     *     lcf->error_log = NULL;
-     *     lcf->error_pages = NULL;
-     *     lcf->try_files = NULL;
-     *     lcf->client_body_path = NULL;
-     *     lcf->regex = NULL;
-     *     lcf->exact_match = 0;
-     *     lcf->auto_redirect = 0;
-     *     lcf->alias = 0;
-     *     lcf->gzip_proxied = 0;
+     *     clcf->root = { 0, NULL };
+     *     clcf->limit_except = 0;
+     *     clcf->post_action = { 0, NULL };
+     *     clcf->types = NULL;
+     *     clcf->default_type = { 0, NULL };
+     *     clcf->error_log = NULL;
+     *     clcf->error_pages = NULL;
+     *     clcf->try_files = NULL;
+     *     clcf->client_body_path = NULL;
+     *     clcf->regex = NULL;
+     *     clcf->exact_match = 0;
+     *     clcf->auto_redirect = 0;
+     *     clcf->alias = 0;
+     *     clcf->gzip_proxied = 0;
      */
 
-    lcf->client_max_body_size = NGX_CONF_UNSET;
-    lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
-    lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
-    lcf->satisfy = NGX_CONF_UNSET_UINT;
-    lcf->if_modified_since = NGX_CONF_UNSET_UINT;
-    lcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
-    lcf->client_body_in_single_buffer = NGX_CONF_UNSET;
-    lcf->internal = NGX_CONF_UNSET;
-    lcf->sendfile = NGX_CONF_UNSET;
-    lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
+    clcf->client_max_body_size = NGX_CONF_UNSET;
+    clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
+    clcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
+    clcf->satisfy = NGX_CONF_UNSET_UINT;
+    clcf->if_modified_since = NGX_CONF_UNSET_UINT;
+    clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
+    clcf->client_body_in_single_buffer = NGX_CONF_UNSET;
+    clcf->internal = NGX_CONF_UNSET;
+    clcf->sendfile = NGX_CONF_UNSET;
+    clcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
 #if (NGX_HAVE_FILE_AIO)
-    lcf->aio = NGX_CONF_UNSET;
+    clcf->aio = NGX_CONF_UNSET;
 #endif
-    lcf->directio = NGX_CONF_UNSET;
-    lcf->directio_alignment = NGX_CONF_UNSET;
-    lcf->tcp_nopush = NGX_CONF_UNSET;
-    lcf->tcp_nodelay = NGX_CONF_UNSET;
-    lcf->send_timeout = NGX_CONF_UNSET_MSEC;
-    lcf->send_lowat = NGX_CONF_UNSET_SIZE;
-    lcf->postpone_output = NGX_CONF_UNSET_SIZE;
-    lcf->limit_rate = NGX_CONF_UNSET_SIZE;
-    lcf->limit_rate_after = NGX_CONF_UNSET_SIZE;
-    lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
-    lcf->keepalive_header = NGX_CONF_UNSET;
-    lcf->keepalive_requests = NGX_CONF_UNSET_UINT;
-    lcf->lingering_time = NGX_CONF_UNSET_MSEC;
-    lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
-    lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
-    lcf->reset_timedout_connection = NGX_CONF_UNSET;
-    lcf->server_name_in_redirect = NGX_CONF_UNSET;
-    lcf->port_in_redirect = NGX_CONF_UNSET;
-    lcf->msie_padding = NGX_CONF_UNSET;
-    lcf->msie_refresh = NGX_CONF_UNSET;
-    lcf->log_not_found = NGX_CONF_UNSET;
-    lcf->log_subrequest = NGX_CONF_UNSET;
-    lcf->recursive_error_pages = NGX_CONF_UNSET;
-    lcf->server_tokens = NGX_CONF_UNSET;
-    lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
-    lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
-
-    lcf->open_file_cache = NGX_CONF_UNSET_PTR;
-    lcf->open_file_cache_valid = NGX_CONF_UNSET;
-    lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
-    lcf->open_file_cache_errors = NGX_CONF_UNSET;
-    lcf->open_file_cache_events = NGX_CONF_UNSET;
+    clcf->read_ahead = NGX_CONF_UNSET_SIZE;
+    clcf->directio = NGX_CONF_UNSET;
+    clcf->directio_alignment = NGX_CONF_UNSET;
+    clcf->tcp_nopush = NGX_CONF_UNSET;
+    clcf->tcp_nodelay = NGX_CONF_UNSET;
+    clcf->send_timeout = NGX_CONF_UNSET_MSEC;
+    clcf->send_lowat = NGX_CONF_UNSET_SIZE;
+    clcf->postpone_output = NGX_CONF_UNSET_SIZE;
+    clcf->limit_rate = NGX_CONF_UNSET_SIZE;
+    clcf->limit_rate_after = NGX_CONF_UNSET_SIZE;
+    clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
+    clcf->keepalive_header = NGX_CONF_UNSET;
+    clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
+    clcf->lingering_time = NGX_CONF_UNSET_MSEC;
+    clcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
+    clcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
+    clcf->reset_timedout_connection = NGX_CONF_UNSET;
+    clcf->server_name_in_redirect = NGX_CONF_UNSET;
+    clcf->port_in_redirect = NGX_CONF_UNSET;
+    clcf->msie_padding = NGX_CONF_UNSET;
+    clcf->msie_refresh = NGX_CONF_UNSET;
+    clcf->log_not_found = NGX_CONF_UNSET;
+    clcf->log_subrequest = NGX_CONF_UNSET;
+    clcf->recursive_error_pages = NGX_CONF_UNSET;
+    clcf->server_tokens = NGX_CONF_UNSET;
+    clcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
+    clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
+
+    clcf->open_file_cache = NGX_CONF_UNSET_PTR;
+    clcf->open_file_cache_valid = NGX_CONF_UNSET;
+    clcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
+    clcf->open_file_cache_errors = NGX_CONF_UNSET;
+    clcf->open_file_cache_events = NGX_CONF_UNSET;
 
 #if (NGX_HTTP_GZIP)
-    lcf->gzip_vary = NGX_CONF_UNSET;
-    lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
+    clcf->gzip_vary = NGX_CONF_UNSET;
+    clcf->gzip_http_version = NGX_CONF_UNSET_UINT;
 #if (NGX_PCRE)
-    lcf->gzip_disable = NGX_CONF_UNSET_PTR;
-    lcf->gzip_disable_msie6 = 3;
+    clcf->gzip_disable = NGX_CONF_UNSET_PTR;
+    clcf->gzip_disable_msie6 = 3;
 #endif
 #endif
 
-    return lcf;
+    return clcf;
 }
 
 
@@ -3156,6 +3149,7 @@
 #if (NGX_HAVE_FILE_AIO)
     ngx_conf_merge_value(conf->aio, prev->aio, 0);
 #endif
+    ngx_conf_merge_size_value(conf->read_ahead, prev->read_ahead, 0);
     ngx_conf_merge_off_value(conf->directio, prev->directio,
                               NGX_MAX_OFF_T_VALUE);
     ngx_conf_merge_off_value(conf->directio_alignment, prev->directio_alignment,
@@ -3262,17 +3256,14 @@
 static char *
 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_srv_conf_t *scf = conf;
-
-    ngx_str_t          *value, size;
-    ngx_url_t           u;
-    ngx_uint_t          n;
-    ngx_http_listen_t  *ls;
-
-    /*
-     * TODO: check duplicate 'listen' directives,
-     *       add resolved name to server names ???
-     */
+    ngx_http_core_srv_conf_t *cscf = conf;
+
+    ngx_str_t              *value, size;
+    ngx_url_t               u;
+    ngx_uint_t              n;
+    ngx_http_listen_opt_t   lsopt;
+
+    cscf->listen = 1;
 
     value = cf->args->elts;
 
@@ -3292,58 +3283,40 @@
         return NGX_CONF_ERROR;
     }
 
-    ls = ngx_array_push(&scf->listen);
-    if (ls == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    ngx_memzero(ls, sizeof(ngx_http_listen_t));
-
-    ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
-
-    ls->socklen = u.socklen;
-    ls->file_name = cf->conf_file->file.name.data;
-    ls->line = cf->conf_file->line;
-    ls->conf.backlog = NGX_LISTEN_BACKLOG;
-    ls->conf.rcvbuf = -1;
-    ls->conf.sndbuf = -1;
-    ls->conf.wildcard = u.wildcard;
-
-    (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr,
+    ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
+
+    ngx_memcpy(&lsopt.u.sockaddr, u.sockaddr, u.socklen);
+
+    lsopt.socklen = u.socklen;
+    lsopt.backlog = NGX_LISTEN_BACKLOG;
+    lsopt.rcvbuf = -1;
+    lsopt.sndbuf = -1;
+    lsopt.wildcard = u.wildcard;
+
+    (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
                          NGX_SOCKADDR_STRLEN, 1);
 
-    if (cf->args->nelts == 2) {
-        return NGX_CONF_OK;
-    }
-
-    if (ngx_strcmp(value[2].data, "default") == 0) {
-        ls->conf.default_server = 1;
-        n = 3;
-
-    } else {
-        n = 2;
-    }
-
-    for ( /* void */ ; n < cf->args->nelts; n++) {
-
-        if (ls->conf.default_server == 0) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "\"%V\" parameter can be specified for "
-                               "the default \"listen\" directive only",
-                               &value[n]);
-            return NGX_CONF_ERROR;
+    for (n = 2; n < cf->args->nelts; n++) {
+
+        if (ngx_strcmp(value[n].data, "default_server") == 0
+            || ngx_strcmp(value[n].data, "default") == 0)
+        {
+            lsopt.default_server = 1;
+            continue;
         }
 
         if (ngx_strcmp(value[n].data, "bind") == 0) {
-            ls->conf.bind = 1;
+            lsopt.set = 1;
+            lsopt.bind = 1;
             continue;
         }
 
         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
-            ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
-            ls->conf.bind = 1;
-
-            if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
+            lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
+            lsopt.set = 1;
+            lsopt.bind = 1;
+
+            if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "invalid backlog \"%V\"", &value[n]);
                 return NGX_CONF_ERROR;
@@ -3356,10 +3329,11 @@
             size.len = value[n].len - 7;
             size.data = value[n].data + 7;
 
-            ls->conf.rcvbuf = ngx_parse_size(&size);
-            ls->conf.bind = 1;
-
-            if (ls->conf.rcvbuf == NGX_ERROR) {
+            lsopt.rcvbuf = ngx_parse_size(&size);
+            lsopt.set = 1;
+            lsopt.bind = 1;
+
+            if (lsopt.rcvbuf == NGX_ERROR) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "invalid rcvbuf \"%V\"", &value[n]);
                 return NGX_CONF_ERROR;
@@ -3372,10 +3346,11 @@
             size.len = value[n].len - 7;
             size.data = value[n].data + 7;
 
-            ls->conf.sndbuf = ngx_parse_size(&size);
-            ls->conf.bind = 1;
-
-            if (ls->conf.sndbuf == NGX_ERROR) {
+            lsopt.sndbuf = ngx_parse_size(&size);
+            lsopt.set = 1;
+            lsopt.bind = 1;
+
+            if (lsopt.sndbuf == NGX_ERROR) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "invalid sndbuf \"%V\"", &value[n]);
                 return NGX_CONF_ERROR;
@@ -3386,8 +3361,9 @@
 
         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
-            ls->conf.accept_filter = (char *) &value[n].data[14];
-            ls->conf.bind = 1;
+            lsopt.accept_filter = (char *) &value[n].data[14];
+            lsopt.set = 1;
+            lsopt.bind = 1;
 #else
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "accept filters \"%V\" are not supported "
@@ -3399,8 +3375,9 @@
 
         if (ngx_strcmp(value[n].data, "deferred") == 0) {
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
-            ls->conf.deferred_accept = 1;
-            ls->conf.bind = 1;
+            lsopt.deferred_accept = 1;
+            lsopt.set = 1;
+            lsopt.bind = 1;
 #else
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "the deferred accept is not supported "
@@ -3413,15 +3390,15 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
             struct sockaddr  *sa;
 
-            sa = (struct sockaddr *) ls->sockaddr;
+            sa = &lsopt.u.sockaddr;
 
             if (sa->sa_family == AF_INET6) {
 
                 if (ngx_strcmp(&value[n].data[10], "n") == 0) {
-                    ls->conf.ipv6only = 1;
+                    lsopt.ipv6only = 1;
 
                 } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) {
-                    ls->conf.ipv6only = 2;
+                    lsopt.ipv6only = 2;
 
                 } else {
                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -3430,13 +3407,13 @@
                     return NGX_CONF_ERROR;
                 }
 
-                ls->conf.bind = 1;
+                lsopt.set = 1;
+                lsopt.bind = 1;
 
             } else {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "ipv6only is not supported "
-                                   "on addr \"%s\", ignored",
-                                   ls->conf.addr);
+                                   "on addr \"%s\", ignored", lsopt.addr);
             }
 
             continue;
@@ -3450,7 +3427,8 @@
 
         if (ngx_strcmp(value[n].data, "ssl") == 0) {
 #if (NGX_HTTP_SSL)
-            ls->conf.ssl = 1;
+            lsopt.set = 1;
+            lsopt.ssl = 1;
             continue;
 #else
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -3465,7 +3443,11 @@
         return NGX_CONF_ERROR;
     }
 
-    return NGX_CONF_OK;
+    if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) {
+        return NGX_CONF_OK;
+    }
+
+    return NGX_CONF_ERROR;
 }
 
 
@@ -3537,19 +3519,20 @@
 
 #if (NGX_PCRE)
         sn->regex = NULL;
-        sn->captures = 0;
 #endif
-        sn->core_srv_conf = cscf;
+        sn->server = cscf;
         sn->name = value[i];
 
         if (value[i].data[0] != '~') {
+            ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
             continue;
         }
 
 #if (NGX_PCRE)
         {
-        ngx_str_t  err;
-        u_char     errstr[NGX_MAX_CONF_ERRSTR];
+        u_char               *p;
+        ngx_regex_compile_t   rc;
+        u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
         if (value[i].len == 1) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -3557,21 +3540,29 @@
             return NGX_CONF_ERROR;
         }
 
-        err.len = NGX_MAX_CONF_ERRSTR;
-        err.data = errstr;
-
         value[i].len--;
         value[i].data++;
 
-        sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
-
+        ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+        rc.pattern = value[i];
+        rc.err.len = NGX_MAX_CONF_ERRSTR;
+        rc.err.data = errstr;
+
+        for (p = value[i].data; p < value[i].data + value[i].len; p++) {
+            if (*p >= 'A' && *p <= 'Z') {
+                rc.options = NGX_REGEX_CASELESS;
+                break;
+            }
+        }
+
+        sn->regex = ngx_http_regex_compile(cf, &rc);
         if (sn->regex == NULL) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
             return NGX_CONF_ERROR;
         }
 
-        sn->captures = (ngx_regex_capture_count(sn->regex) > 0);
         sn->name = value[i];
+        cscf->captures = (rc.captures > 0);
         }
 #else
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -3589,7 +3580,7 @@
 static char *
 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     ngx_str_t                  *value;
     ngx_uint_t                  alias, n;
@@ -3597,11 +3588,11 @@
 
     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
 
-    if (lcf->root.data) {
+    if (clcf->root.data) {
 
         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
 
-        if ((ngx_uint_t) lcf->alias == alias) {
+        if ((ngx_uint_t) clcf->alias == alias) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "\"%V\" directive is duplicate",
                                &cmd->name);
@@ -3609,13 +3600,13 @@
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "\"%V\" directive is duplicate, "
                                "\"%s\" directive is specified before",
-                               &cmd->name, lcf->alias ? "alias" : "root");
+                               &cmd->name, clcf->alias ? "alias" : "root");
         }
 
         return NGX_CONF_ERROR;
     }
 
-    if (lcf->named && alias) {
+    if (clcf->named && alias) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "the \"alias\" directive may not be used "
                            "inside named location");
@@ -3647,28 +3638,28 @@
         return NGX_CONF_ERROR;
     }
 
-    lcf->alias = alias;
-    lcf->root = value[1];
-
-    if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
-        lcf->root.len--;
+    clcf->alias = alias;
+    clcf->root = value[1];
+
+    if (!alias && clcf->root.data[clcf->root.len - 1] == '/') {
+        clcf->root.len--;
     }
 
-    if (lcf->root.data[0] != '$') {
-        if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) != NGX_OK) {
+    if (clcf->root.data[0] != '$') {
+        if (ngx_conf_full_name(cf->cycle, &clcf->root, 0) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
     }
 
-    n = ngx_http_script_variables_count(&lcf->root);
+    n = ngx_http_script_variables_count(&clcf->root);
 
     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
 
     if (n) {
         sc.cf = cf;
-        sc.source = &lcf->root;
-        sc.lengths = &lcf->root_lengths;
-        sc.values = &lcf->root_values;
+        sc.source = &clcf->root;
+        sc.lengths = &clcf->root_lengths;
+        sc.values = &clcf->root_values;
         sc.variables = n;
         sc.complete_lengths = 1;
         sc.complete_values = 1;
@@ -3678,20 +3669,6 @@
         }
     }
 
-#if (NGX_PCRE)
-
-    if (alias && lcf->regex
-        && (ngx_regex_capture_count(lcf->regex) <= 0 || sc.ncaptures == 0))
-    {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "the \"alias\" directive must use captures "
-                           "inside location given by regular expression");
-
-        return NGX_CONF_ERROR;
-    }
-
-#endif
-
     return NGX_CONF_OK;
 }
 
@@ -3843,7 +3820,7 @@
 static char *
 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     u_char                            *p;
     ngx_int_t                          overwrite;
@@ -3853,10 +3830,10 @@
     ngx_http_complex_value_t           cv;
     ngx_http_compile_complex_value_t   ccv;
 
-    if (lcf->error_pages == NULL) {
-        lcf->error_pages = ngx_array_create(cf->pool, 4,
-                                            sizeof(ngx_http_err_page_t));
-        if (lcf->error_pages == NULL) {
+    if (clcf->error_pages == NULL) {
+        clcf->error_pages = ngx_array_create(cf->pool, 4,
+                                             sizeof(ngx_http_err_page_t));
+        if (clcf->error_pages == NULL) {
             return NGX_CONF_ERROR;
         }
     }
@@ -3920,7 +3897,7 @@
     }
 
     for (i = 1; i < cf->args->nelts - n; i++) {
-        err = ngx_array_push(lcf->error_pages);
+        err = ngx_array_push(clcf->error_pages);
         if (err == NULL) {
             return NGX_CONF_ERROR;
         }
@@ -3933,9 +3910,9 @@
             return NGX_CONF_ERROR;
         }
 
-        if (err->status < 400 || err->status > 599) {
+        if (err->status < 300 || err->status > 599) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "value \"%V\" must be between 400 and 599",
+                               "value \"%V\" must be between 300 and 599",
                                &value[i]);
             return NGX_CONF_ERROR;
         }
@@ -4048,14 +4025,14 @@
 static char *
 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     time_t       inactive;
     ngx_str_t   *value, s;
     ngx_int_t    max;
     ngx_uint_t   i;
 
-    if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) {
+    if (clcf->open_file_cache != NGX_CONF_UNSET_PTR) {
         return "is duplicate";
     }
 
@@ -4091,7 +4068,7 @@
 
         if (ngx_strcmp(value[i].data, "off") == 0) {
 
-            lcf->open_file_cache = NULL;
+            clcf->open_file_cache = NULL;
 
             continue;
         }
@@ -4104,7 +4081,7 @@
         return NGX_CONF_ERROR;
     }
 
-    if (lcf->open_file_cache == NULL) {
+    if (clcf->open_file_cache == NULL) {
         return NGX_CONF_OK;
     }
 
@@ -4114,8 +4091,8 @@
         return NGX_CONF_ERROR;
     }
 
-    lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
-    if (lcf->open_file_cache) {
+    clcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
+    if (clcf->open_file_cache) {
         return NGX_CONF_OK;
     }
 
@@ -4126,50 +4103,50 @@
 static char *
 ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     ngx_str_t  *value;
 
-    if (lcf->error_log) {
+    if (clcf->error_log) {
         return "is duplicate";
     }
 
     value = cf->args->elts;
 
-    lcf->error_log = ngx_log_create(cf->cycle, &value[1]);
-    if (lcf->error_log == NULL) {
+    clcf->error_log = ngx_log_create(cf->cycle, &value[1]);
+    if (clcf->error_log == NULL) {
         return NGX_CONF_ERROR;
     }
 
     if (cf->args->nelts == 2) {
-        lcf->error_log->log_level = NGX_LOG_ERR;
+        clcf->error_log->log_level = NGX_LOG_ERR;
         return NGX_CONF_OK;
     }
 
-    return ngx_log_set_levels(cf, lcf->error_log);
+    return ngx_log_set_levels(cf, clcf->error_log);
 }
 
 
 static char *
 ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
+    ngx_http_core_loc_conf_t *clcf = conf;
 
     ngx_str_t  *value;
 
-    if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
+    if (clcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
         return "is duplicate";
     }
 
     value = cf->args->elts;
 
-    lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
-
-    if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
+    clcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
+
+    if (clcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
         return "invalid value";
     }
 
-    if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
+    if (clcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
         return "value must be less than 597 hours";
     }
 
@@ -4177,13 +4154,13 @@
         return NGX_CONF_OK;
     }
 
-    lcf->keepalive_header = ngx_parse_time(&value[2], 1);
-
-    if (lcf->keepalive_header == NGX_ERROR) {
+    clcf->keepalive_header = ngx_parse_time(&value[2], 1);
+
+    if (clcf->keepalive_header == NGX_ERROR) {
         return "invalid value";
     }
 
-    if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
+    if (clcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
         return "value must be less than 68 years";
     }
 
@@ -4194,13 +4171,13 @@
 static char *
 ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_core_loc_conf_t *lcf = conf;
-
-    if (lcf->internal != NGX_CONF_UNSET) {
+    ngx_http_core_loc_conf_t *clcf = conf;
+
+    if (clcf->internal != NGX_CONF_UNSET) {
         return "is duplicate";
     }
 
-    lcf->internal = 1;
+    clcf->internal = 1;
 
     return NGX_CONF_OK;
 }
@@ -4248,10 +4225,11 @@
 
 #if (NGX_PCRE)
 
-    ngx_str_t         err, *value;
-    ngx_uint_t        i;
-    ngx_regex_elt_t  *re;
-    u_char            errstr[NGX_MAX_CONF_ERRSTR];
+    ngx_str_t            *value;
+    ngx_uint_t            i;
+    ngx_regex_elt_t      *re;
+    ngx_regex_compile_t   rc;
+    u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
@@ -4263,8 +4241,11 @@
 
     value = cf->args->elts;
 
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+    rc.pool = cf->pool;
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
 
     for (i = 1; i < cf->args->nelts; i++) {
 
@@ -4278,14 +4259,15 @@
             return NGX_CONF_ERROR;
         }
 
-        re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
-                                      &err);
-
-        if (re->regex == NULL) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+        rc.pattern = value[1];
+        rc.options = NGX_REGEX_CASELESS;
+
+        if (ngx_regex_compile(&rc) != NGX_OK) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
             return NGX_CONF_ERROR;
         }
 
+        re->regex = rc.regex;
         re->name = value[i].data;
     }
 
@@ -4348,8 +4330,15 @@
 
     if (*sp < NGX_MIN_POOL_SIZE) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
-
+                           "the pool size must be no less than %uz",
+                           NGX_MIN_POOL_SIZE);
+        return NGX_CONF_ERROR;
+    }
+
+    if (*sp % NGX_POOL_ALIGNMENT) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "the pool size must be a multiple of %uz",
+                           NGX_POOL_ALIGNMENT);
         return NGX_CONF_ERROR;
     }
 
--- a/src/http/ngx_http_core_module.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_core_module.h	Thu Mar 11 21:27:17 2010 +0300
@@ -43,6 +43,21 @@
 
 
 typedef struct {
+    union {
+        struct sockaddr        sockaddr;
+        struct sockaddr_in     sockaddr_in;
+#if (NGX_HAVE_INET6)
+        struct sockaddr_in6    sockaddr_in6;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+        struct sockaddr_un     sockaddr_un;
+#endif
+        u_char                 sockaddr_data[NGX_SOCKADDRLEN];
+    } u;
+
+    socklen_t                  socklen;
+
+    unsigned                   set:1;
     unsigned                   default_server:1;
     unsigned                   bind:1;
     unsigned                   wildcard:1;
@@ -65,18 +80,7 @@
 #endif
 
     u_char                     addr[NGX_SOCKADDR_STRLEN + 1];
-} ngx_http_listen_conf_t;
-
-
-typedef struct {
-    u_char                     sockaddr[NGX_SOCKADDRLEN];
-    socklen_t                  socklen;
-
-    u_char                    *file_name;
-    ngx_uint_t                 line;
-
-    ngx_http_listen_conf_t     conf;
-} ngx_http_listen_t;
+} ngx_http_listen_opt_t;
 
 
 typedef enum {
@@ -133,6 +137,7 @@
     ngx_hash_t                 variables_hash;
 
     ngx_array_t                variables;       /* ngx_http_variable_t */
+    ngx_uint_t                 ncaptures;
 
     ngx_uint_t                 server_names_hash_max_size;
     ngx_uint_t                 server_names_hash_bucket_size;
@@ -142,6 +147,8 @@
 
     ngx_hash_keys_arrays_t    *variables_keys;
 
+    ngx_array_t               *ports;
+
     ngx_uint_t                 try_files;       /* unsigned  try_files:1 */
 
     ngx_http_phase_t           phases[NGX_HTTP_LOG_PHASE + 1];
@@ -149,9 +156,6 @@
 
 
 typedef struct {
-    /* array of the ngx_http_listen_t, "listen" directive */
-    ngx_array_t                 listen;
-
     /* array of the ngx_http_server_name_t, "server_name" directive */
     ngx_array_t                 server_names;
 
@@ -172,6 +176,11 @@
     ngx_flag_t                  merge_slashes;
     ngx_flag_t                  underscores_in_headers;
 
+    unsigned                    listen:1;
+#if (NGX_PCRE)
+    unsigned                    captures:1;
+#endif
+
     ngx_http_core_loc_conf_t  **named_locations;
 } ngx_http_core_srv_conf_t;
 
@@ -181,7 +190,7 @@
 
 typedef struct {
     /* the default server configuration for this address:port */
-    ngx_http_core_srv_conf_t  *core_srv_conf;
+    ngx_http_core_srv_conf_t  *default_server;
 
     ngx_http_virtual_names_t  *virtual_names;
 
@@ -222,40 +231,28 @@
 
 
 typedef struct {
-    struct sockaddr           *sockaddr;
-    socklen_t                  socklen;
+    ngx_http_listen_opt_t      opt;
 
     ngx_hash_t                 hash;
     ngx_hash_wildcard_t       *wc_head;
     ngx_hash_wildcard_t       *wc_tail;
 
-    ngx_array_t                names;      /* array of ngx_http_server_name_t */
-
 #if (NGX_PCRE)
     ngx_uint_t                 nregex;
     ngx_http_server_name_t    *regex;
 #endif
 
     /* the default server configuration for this address:port */
-    ngx_http_core_srv_conf_t  *core_srv_conf;
-
-    unsigned                   default_server:1;
-    unsigned                   bind:1;
-    unsigned                   wildcard:1;
-#if (NGX_HTTP_SSL)
-    unsigned                   ssl:1;
-#endif
-
-    ngx_http_listen_conf_t    *listen_conf;
+    ngx_http_core_srv_conf_t  *default_server;
+    ngx_array_t                servers;  /* array of ngx_http_core_srv_conf_t */
 } ngx_http_conf_addr_t;
 
 
 struct ngx_http_server_name_s {
 #if (NGX_PCRE)
-    ngx_regex_t               *regex;
-    ngx_uint_t                 captures;      /* unsigned  captures:1; */
+    ngx_http_regex_t          *regex;
 #endif
-    ngx_http_core_srv_conf_t  *core_srv_conf; /* virtual name server conf */
+    ngx_http_core_srv_conf_t  *server;   /* virtual name server conf */
     ngx_str_t                  name;
 };
 
@@ -282,9 +279,7 @@
     ngx_str_t     name;          /* location name */
 
 #if (NGX_PCRE)
-    ngx_regex_t  *regex;
-
-    unsigned      captures:1;
+    ngx_http_regex_t  *regex;
 #endif
 
     unsigned      noname:1;   /* "if () {}" block or limit_except */
@@ -332,6 +327,7 @@
     size_t        limit_rate;              /* limit_rate */
     size_t        limit_rate_after;        /* limit_rate_after */
     size_t        sendfile_max_chunk;      /* sendfile_max_chunk */
+    size_t        read_ahead;              /* read_ahead */
 
     ngx_msec_t    client_body_timeout;     /* client_body_timeout */
     ngx_msec_t    send_timeout;            /* send_timeout */
--- a/src/http/ngx_http_file_cache.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_file_cache.c	Thu Mar 11 21:27:17 2010 +0300
@@ -12,6 +12,8 @@
 
 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,
+    ngx_http_cache_t *c);
 #if (NGX_HAVE_FILE_AIO)
 static void ngx_http_cache_aio_event_handler(ngx_event_t *ev);
 #endif
@@ -281,6 +283,7 @@
     of.min_uses = clcf->open_file_cache_min_uses;
     of.events = clcf->open_file_cache_events;
     of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
+    of.read_ahead = clcf->read_ahead;
 
     if (ngx_open_cached_file(clcf->open_file_cache, &c->file.name, &of, r->pool)
         != NGX_OK)
@@ -329,40 +332,13 @@
 
     c = r->cache;
 
-#if (NGX_HAVE_FILE_AIO)
-    {
-    ngx_http_core_loc_conf_t      *clcf;
-
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-    if (clcf->aio) {
-        n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool);
-
-        if (n == NGX_AGAIN) {
-            c->file.aio->data = r;
-            c->file.aio->handler = ngx_http_cache_aio_event_handler;
+    n = ngx_http_file_cache_aio_read(r, c);
 
-            r->main->blocked++;
-            r->aio = 1;
-
-            return NGX_AGAIN;
-        }
-
-    } else {
-        n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0);
-    }
-    }
-#else
-
-    n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0);
-
-#endif
-
-    if (n == NGX_ERROR) {
+    if (n < 0) {
         return n;
     }
 
-    if ((size_t) n <= c->header_start) {
+    if ((size_t) n < c->header_start) {
         ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
                       "cache file \"%s\" is too small", c->file.name.data);
         return NGX_ERROR;
@@ -370,7 +346,7 @@
 
     h = (ngx_http_file_cache_header_t *) c->buf->pos;
 
-    if (h->crc32 != c->crc32 || (size_t) h->header_start != c->header_start) {
+    if (h->crc32 != c->crc32) {
         ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
                       "cache file \"%s\" has md5 collision", c->file.name.data);
         return NGX_DECLINED;
@@ -382,6 +358,7 @@
     c->last_modified = h->last_modified;
     c->date = h->date;
     c->valid_msec = h->valid_msec;
+    c->header_start = h->header_start;
     c->body_start = h->body_start;
 
     r->cached = 1;
@@ -431,8 +408,46 @@
 }
 
 
+static ssize_t
+ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c)
+{
 #if (NGX_HAVE_FILE_AIO)
+    ssize_t                    n;
+    ngx_http_core_loc_conf_t  *clcf;
 
+    if (!ngx_file_aio) {
+        goto noaio;
+    }
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (!clcf->aio) {
+        goto noaio;
+    }
+
+    n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool);
+
+    if (n != NGX_AGAIN) {
+        return n;
+    }
+
+    c->file.aio->data = r;
+    c->file.aio->handler = ngx_http_cache_aio_event_handler;
+
+    r->main->blocked++;
+    r->aio = 1;
+
+    return NGX_AGAIN;
+
+noaio:
+
+#endif
+
+    return ngx_read_file(&c->file, c->buf->pos, c->body_start, 0);
+}
+
+
+#if (NGX_HAVE_FILE_AIO)
 
 static void
 ngx_http_cache_aio_event_handler(ngx_event_t *ev)
@@ -691,7 +706,7 @@
 void
 ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf)
 {
-    off_t                   size;
+    off_t                   size, length;
     ngx_int_t               rc;
     ngx_file_uniq_t         uniq;
     ngx_file_info_t         fi;
@@ -713,6 +728,7 @@
     cache = c->file_cache;
 
     uniq = 0;
+    length = 0;
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http file cache rename: \"%s\" to \"%s\"",
@@ -737,10 +753,11 @@
 
         } else {
             uniq = ngx_file_uniq(&fi);
+            length = ngx_file_size(&fi);
         }
     }
 
-    size = (c->length + cache->bsize - 1) / cache->bsize;
+    size = (length + cache->bsize - 1) / cache->bsize;
 
     ngx_shmtx_lock(&cache->shpool->mutex);
 
@@ -750,7 +767,7 @@
 
     size = size - (c->node->length + cache->bsize - 1) / cache->bsize;
 
-    c->node->length = c->length;
+    c->node->length = length;
 
     cache->sh->size += size;
 
@@ -789,6 +806,8 @@
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
+    r->header_only = (c->length - c->body_start) == 0;
+
     rc = ngx_http_send_header(r);
 
     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
@@ -798,7 +817,7 @@
     b->file_pos = c->body_start;
     b->file_last = c->length;
 
-    b->in_file = (c->length - c->body_start) ? 1: 0;
+    b->in_file = 1;
     b->last_buf = (r == r->main) ? 1: 0;
     b->last_in_chain = 1;
 
--- a/src/http/ngx_http_header_filter_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_header_filter_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -132,10 +132,6 @@
 ngx_http_header_out_t  ngx_http_headers_out[] = {
     { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) },
     { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) },
-#if 0
-    { ngx_string("Content-Type"),
-                 offsetof(ngx_http_headers_out_t, content_type) },
-#endif
     { ngx_string("Content-Length"),
                  offsetof(ngx_http_headers_out_t, content_length) },
     { ngx_string("Content-Encoding"),
@@ -399,8 +395,13 @@
     }
 
 #if (NGX_HTTP_GZIP)
-    if (r->gzip && clcf->gzip_vary) {
-        len += sizeof("Vary: Accept-Encoding" CRLF) - 1;
+    if (r->gzip_vary) {
+        if (clcf->gzip_vary) {
+            len += sizeof("Vary: Accept-Encoding" CRLF) - 1;
+
+        } else {
+            r->gzip_vary = 0;
+        }
     }
 #endif
 
@@ -533,8 +534,8 @@
 
         r->headers_out.location->value.len = b->last - p;
         r->headers_out.location->value.data = p;
-        r->headers_out.location->key.len = sizeof("Location: ") - 1;
-        r->headers_out.location->key.data = (u_char *) "Location: ";
+        r->headers_out.location->key.len = sizeof("Location") - 1;
+        r->headers_out.location->key.data = (u_char *) "Location";
 
         *b->last++ = CR; *b->last++ = LF;
     }
@@ -559,7 +560,7 @@
     }
 
 #if (NGX_HTTP_GZIP)
-    if (r->gzip && clcf->gzip_vary) {
+    if (r->gzip_vary) {
         b->last = ngx_cpymem(b->last, "Vary: Accept-Encoding" CRLF,
                              sizeof("Vary: Accept-Encoding" CRLF) - 1);
     }
--- a/src/http/ngx_http_parse.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_parse.c	Thu Mar 11 21:27:17 2010 +0300
@@ -1322,8 +1322,10 @@
 
 unsafe:
 
-    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                  "unsafe URI \"%V\" was detected", uri);
+    if (*flags & NGX_HTTP_LOG_UNSAFE) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "unsafe URI \"%V\" was detected", uri);
+    }
 
     return NGX_ERROR;
 }
--- a/src/http/ngx_http_parse_time.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_parse_time.c	Thu Mar 11 21:27:17 2010 +0300
@@ -8,13 +8,15 @@
 #include <ngx_core.h>
 
 
-static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static ngx_uint_t  mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
 time_t
 ngx_http_parse_time(u_char *value, size_t len)
 {
-    u_char  *p, *end;
-    int      day, month, year, hour, min, sec;
+    u_char      *p, *end;
+    ngx_int_t    month;
+    ngx_uint_t   day, year, hour, min, sec;
+    uint64_t     time;
     enum {
         no = 0,
         rfc822,   /* Tue, 10 Nov 2002 23:50:13   */
@@ -229,14 +231,6 @@
         return NGX_ERROR;
     }
 
-#if (NGX_TIME_T_SIZE <= 4)
-
-    if (year >= 2038) {
-        return NGX_ERROR;
-    }
-
-#endif
-
     /*
      * shift new year to March 1 and start months from 1 (not 0),
      * it is needed for Gauss' formula
@@ -249,7 +243,7 @@
 
     /* Gauss' formula for Grigorian days since March 1, 1 BC */
 
-    return (
+    time = (uint64_t) (
             /* days in years including leap years since March 1, 1 BC */
 
             365 * year + year / 4 - year / 100 + year / 400
@@ -268,4 +262,14 @@
              */
 
             - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
+
+#if (NGX_TIME_T_SIZE <= 4)
+
+    if (time > 0x7fffffff) {
+        return NGX_ERROR;
+    }
+
+#endif
+
+    return (time_t) time;
 }
--- a/src/http/ngx_http_request.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_request.c	Thu Mar 11 21:27:17 2010 +0300
@@ -31,7 +31,8 @@
 
 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
 static void ngx_http_process_request(ngx_http_request_t *r);
-static ssize_t ngx_http_validate_host(u_char *host, size_t len);
+static ssize_t ngx_http_validate_host(ngx_http_request_t *r, u_char **host,
+    size_t len, ngx_uint_t alloc);
 static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r,
     u_char *host, size_t len);
 
@@ -380,7 +381,7 @@
     r->virtual_names = addr_conf->virtual_names;
 
     /* the default server configuration for the address:port */
-    cscf = addr_conf->core_srv_conf;
+    cscf = addr_conf->default_server;
 
     r->main_conf = cscf->ctx->main_conf;
     r->srv_conf = cscf->ctx->srv_conf;
@@ -627,6 +628,7 @@
 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
 {
     size_t                    len;
+    u_char                   *host;
     const char               *servername;
     ngx_connection_t         *c;
     ngx_http_request_t       *r;
@@ -651,7 +653,15 @@
 
     r = c->data;
 
-    if (ngx_http_find_virtual_server(r, (u_char *) servername, len) != NGX_OK) {
+    host = (u_char *) servername;
+
+    len = ngx_http_validate_host(r, &host, len, 1);
+
+    if (len <= 0) {
+        return SSL_TLSEXT_ERR_NOACK;
+    }
+
+    if (ngx_http_find_virtual_server(r, host, len) != NGX_OK) {
         return SSL_TLSEXT_ERR_NOACK;
     }
 
@@ -670,6 +680,7 @@
 static void
 ngx_http_process_request_line(ngx_event_t *rev)
 {
+    u_char                    *host;
     ssize_t                    n;
     ngx_int_t                  rc, rv;
     ngx_connection_t          *c;
@@ -777,9 +788,11 @@
 
             p = r->uri.data + r->uri.len - 1;
 
-            if (*p == '.') {
-
-                while (--p > r->uri.data && *p == '.') { /* void */ }
+            if (*p == '.' || *p == ' ') {
+
+                while (--p > r->uri.data && (*p == '.' || *p == ' ')) {
+                    /* void */
+                }
 
                 r->uri.len = p + 1 - r->uri.data;
 
@@ -801,18 +814,25 @@
                            "http exten: \"%V\"", &r->exten);
 
             if (r->host_start && r->host_end) {
-                n = ngx_http_validate_host(r->host_start,
-                                           r->host_end - r->host_start);
-
-                if (n <= 0) {
+
+                host = r->host_start;
+                n = ngx_http_validate_host(r, &host,
+                                           r->host_end - r->host_start, 0);
+
+                if (n == 0) {
                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
                                   "client sent invalid host in request line");
                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                     return;
                 }
 
+                if (n < 0) {
+                    ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                    return;
+                }
+
                 r->headers_in.server.len = n;
-                r->headers_in.server.data = r->host_start;
+                r->headers_in.server.data = host;
             }
 
             if (r->http_version < NGX_HTTP_VERSION_10) {
@@ -936,9 +956,17 @@
                 }
 
                 if (rv == NGX_DECLINED) {
-                    len = r->header_in->end - r->header_name_start;
                     p = r->header_name_start;
 
+                    if (p == NULL) {
+                        ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                                      "client sent too large request");
+                        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                        return;
+                    }
+
+                    len = r->header_in->end - p;
+
                     if (len > NGX_MAX_ERROR_STR - 300) {
                         len = NGX_MAX_ERROR_STR - 300;
                         p[len++] = '.'; p[len++] = '.'; p[len++] = '.';
@@ -1312,27 +1340,34 @@
 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
 {
-    ssize_t  len;
+    u_char   *host;
+    ssize_t   len;
 
     if (r->headers_in.host == NULL) {
         r->headers_in.host = h;
     }
 
-    len = ngx_http_validate_host(h->value.data, h->value.len);
-
-    if (len <= 0) {
+    host = h->value.data;
+    len = ngx_http_validate_host(r, &host, h->value.len, 0);
+
+    if (len == 0) {
         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                       "client sent invalid host header");
         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
         return NGX_ERROR;
     }
 
+    if (len < 0) {
+        ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return NGX_ERROR;
+    }
+
     if (r->headers_in.server.len) {
         return NGX_OK;
     }
 
     r->headers_in.server.len = len;
-    r->headers_in.server.data = h->value.data;
+    r->headers_in.server.data = host;
 
     return NGX_OK;
 }
@@ -1412,6 +1447,12 @@
         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
             r->headers_in.gecko = 1;
 
+        } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
+            r->headers_in.chrome = 1;
+
+        } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)) {
+            r->headers_in.safari = 1;
+
         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
             r->headers_in.konqueror = 1;
         }
@@ -1588,21 +1629,23 @@
 
 
 static ssize_t
-ngx_http_validate_host(u_char *host, size_t len)
+ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
+    ngx_uint_t alloc)
 {
-    u_char      ch;
-    size_t      i, last;
-    ngx_uint_t  dot;
+    u_char      *h, ch;
+    size_t       i, last;
+    ngx_uint_t   dot;
 
     last = len;
+    h = *host;
     dot = 0;
 
     for (i = 0; i < len; i++) {
-        ch = host[i];
+        ch = h[i];
 
         if (ch == '.') {
             if (dot) {
-                return -1;
+                return 0;
             }
 
             dot = 1;
@@ -1617,7 +1660,11 @@
         }
 
         if (ngx_path_separator(ch) || ch == '\0') {
-            return -1;
+            return 0;
+        }
+
+        if (ch >= 'A' || ch < 'Z') {
+            alloc = 1;
         }
     }
 
@@ -1625,6 +1672,15 @@
         last--;
     }
 
+    if (alloc) {
+        *host = ngx_pnalloc(r->pool, last) ;
+        if (*host == NULL) {
+            return -1;
+        }
+
+        ngx_strlow(*host, h, last);
+    }
+
     return last;
 }
 
@@ -1632,29 +1688,15 @@
 static ngx_int_t
 ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
 {
-    u_char                    *server;
-    ngx_uint_t                 hash;
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
-    u_char                     buf[32];
 
     if (r->virtual_names == NULL) {
         return NGX_DECLINED;
     }
 
-    if (len <= 32) {
-        server = buf;
-
-    } else {
-        server = ngx_pnalloc(r->pool, len);
-        if (server == NULL) {
-            return NGX_ERROR;
-        }
-    }
-
-    hash = ngx_hash_strlow(server, host, len);
-
-    cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len);
+    cscf = ngx_hash_find_combined(&r->virtual_names->names,
+                                  ngx_hash_key(host, len), host, len);
 
     if (cscf) {
         goto found;
@@ -1662,64 +1704,31 @@
 
 #if (NGX_PCRE)
 
-    if (r->virtual_names->nregex) {
-        size_t                   ncaptures;
+    if (len && r->virtual_names->nregex) {
         ngx_int_t                n;
         ngx_uint_t               i;
         ngx_str_t                name;
         ngx_http_server_name_t  *sn;
 
         name.len = len;
-        name.data = server;
-
-        ncaptures = 0;
+        name.data = host;
 
         sn = r->virtual_names->regex;
 
         for (i = 0; i < r->virtual_names->nregex; i++) {
 
-            if (sn[i].captures && r->captures == NULL) {
-
-                ncaptures = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
-
-                r->captures = ngx_palloc(r->pool, ncaptures * sizeof(int));
-                if (r->captures == NULL) {
-                    return NGX_ERROR;
-                }
-
-                if (server == buf) {
-                    server = ngx_pnalloc(r->pool, len);
-                    if (server == NULL) {
-                        return NGX_ERROR;
-                    }
-
-                    ngx_memcpy(server, buf, len);
-                    name.data = server;
-                }
+            n = ngx_http_regex_exec(r, sn[i].regex, &name);
+
+            if (n == NGX_OK) {
+                cscf = sn[i].server;
+                goto found;
             }
 
-            n = ngx_regex_exec(sn[i].regex, &name, r->captures, ncaptures);
-
-            if (n == NGX_REGEX_NO_MATCHED) {
+            if (n == NGX_DECLINED) {
                 continue;
             }
 
-            if (n < 0) {
-                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                              ngx_regex_exec_n
-                              " failed: %d on \"%V\" using \"%V\"",
-                              n, &name, &sn[i].name);
-                return NGX_ERROR;
-            }
-
-            /* match */
-
-            cscf = sn[i].core_srv_conf;
-
-            r->ncaptures = ncaptures;
-            r->captures_data = server;
-
-            goto found;
+            return NGX_ERROR;
         }
     }
 
@@ -1993,6 +2002,7 @@
     }
 
     r->done = 1;
+    r->write_event_handler = ngx_http_request_empty_handler;
 
     if (!r->post_action) {
         r->request_complete = 1;
@@ -2032,6 +2042,10 @@
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http terminate request count:%d", mr->count);
 
+    if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
+        mr->headers_out.status = rc;
+    }
+
     cln = mr->cleanup;
     mr->cleanup = NULL;
 
@@ -2081,13 +2095,24 @@
 {
     ngx_http_core_loc_conf_t  *clcf;
 
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
     if (r->main->count != 1) {
+
+        if (r->discard_body) {
+            r->read_event_handler = ngx_http_discarded_request_body_handler;
+
+            if (r->lingering_time == 0) {
+                r->lingering_time = ngx_time()
+                                      + (time_t) (clcf->lingering_time / 1000);
+                ngx_add_timer(r->connection->read, clcf->lingering_timeout);
+            }
+        }
+
         ngx_http_close_request(r, 0);
         return;
     }
 
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
     if (!ngx_terminate
          && !ngx_exiting
          && r->keepalive
@@ -2113,7 +2138,9 @@
 
     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
 
-    r->read_event_handler = ngx_http_test_reading;
+    r->read_event_handler = r->discard_body ?
+                                ngx_http_discarded_request_body_handler:
+                                ngx_http_test_reading;
     r->write_event_handler = ngx_http_writer;
 
     wev = r->connection->write;
@@ -2215,6 +2242,8 @@
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
 
+    r->write_event_handler = ngx_http_request_empty_handler;
+
     ngx_http_finalize_request(r, rc);
 }
 
@@ -2391,6 +2420,8 @@
         }
     }
 
+    r->keepalive = 0;
+
     ngx_http_free_request(r, 0);
 
     c->data = hc;
@@ -2820,6 +2851,8 @@
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "post action: \"%V\"", &clcf->post_action);
 
+    r->main->count--;
+
     r->http_version = NGX_HTTP_VERSION_9;
     r->header_only = 1;
     r->post_action = 1;
--- a/src/http/ngx_http_request.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_request.h	Thu Mar 11 21:27:17 2010 +0300
@@ -10,7 +10,6 @@
 
 #define NGX_HTTP_MAX_URI_CHANGES           10
 #define NGX_HTTP_MAX_SUBREQUESTS           50
-#define NGX_HTTP_MAX_CAPTURES              9
 
 /* must be 2^n */
 #define NGX_HTTP_LC_HEADER_LEN             32
@@ -60,6 +59,7 @@
 #define NGX_HTTP_ZERO_IN_URI               1
 #define NGX_HTTP_SUBREQUEST_IN_MEMORY      2
 #define NGX_HTTP_SUBREQUEST_WAITED         4
+#define NGX_HTTP_LOG_UNSAFE                8
 
 
 #define NGX_HTTP_OK                        200
@@ -219,6 +219,8 @@
     unsigned                          msie6:1;
     unsigned                          opera:1;
     unsigned                          gecko:1;
+    unsigned                          chrome:1;
+    unsigned                          safari:1;
     unsigned                          konqueror:1;
 } ngx_http_headers_in_t;
 
@@ -456,7 +458,12 @@
 #if (NGX_HTTP_CACHE)
     unsigned                          cached:1;
 #endif
-    unsigned                          gzip:2;
+
+#if (NGX_HTTP_GZIP)
+    unsigned                          gzip_tested:1;
+    unsigned                          gzip_ok:1;
+    unsigned                          gzip_vary:1;
+#endif
 
     unsigned                          proxy:1;
     unsigned                          bypass_cache:1;
--- a/src/http/ngx_http_request_body.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_request_body.c	Thu Mar 11 21:27:17 2010 +0300
@@ -13,7 +13,6 @@
 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
 static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r,
     ngx_chain_t *body);
-static void ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r);
 static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
 static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r);
 
@@ -460,6 +459,7 @@
 
     if (size) {
         if (r->headers_in.content_length_n > size) {
+            r->header_in->pos += size;
             r->headers_in.content_length_n -= size;
 
         } else {
@@ -469,23 +469,26 @@
         }
     }
 
-    r->discard_body = 1;
-
-    r->read_event_handler = ngx_http_read_discarded_request_body_handler;
+    r->read_event_handler = ngx_http_discarded_request_body_handler;
 
     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    r->count++;
-    (void) ngx_http_read_discarded_request_body(r);
+    if (ngx_http_read_discarded_request_body(r) == NGX_OK) {
+        r->lingering_close = 0;
+
+    } else {
+        r->count++;
+        r->discard_body = 1;
+    }
 
     return NGX_OK;
 }
 
 
-static void
-ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r)
+void
+ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
 {
     ngx_int_t                  rc;
     ngx_msec_t                 timer;
@@ -499,7 +502,7 @@
     if (rev->timedout) {
         c->timedout = 1;
         c->error = 1;
-        ngx_http_finalize_request(r, 0);
+        ngx_http_finalize_request(r, NGX_ERROR);
         return;
     }
 
@@ -508,7 +511,8 @@
 
         if (timer <= 0) {
             r->discard_body = 0;
-            ngx_http_finalize_request(r, 0);
+            r->lingering_close = 0;
+            ngx_http_finalize_request(r, NGX_ERROR);
             return;
         }
 
@@ -519,13 +523,9 @@
     rc = ngx_http_read_discarded_request_body(r);
 
     if (rc == NGX_OK) {
-
         r->discard_body = 0;
-
-        if (r->done) {
-            ngx_http_finalize_request(r, 0);
-        }
-
+        r->lingering_close = 0;
+        ngx_http_finalize_request(r, NGX_DONE);
         return;
     }
 
@@ -533,7 +533,7 @@
 
     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
         c->error = 1;
-        ngx_http_finalize_request(r, rc);
+        ngx_http_finalize_request(r, NGX_ERROR);
         return;
     }
 
@@ -562,12 +562,16 @@
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http read discarded body");
 
-    do {
+    for ( ;; ) {
         if (r->headers_in.content_length_n == 0) {
             r->read_event_handler = ngx_http_block_reading;
             return NGX_OK;
         }
 
+        if (!r->connection->read->ready) {
+            return NGX_AGAIN;
+        }
+
         size = (r->headers_in.content_length_n > NGX_HTTP_DISCARD_BUFFER_SIZE) ?
                    NGX_HTTP_DISCARD_BUFFER_SIZE:
                    (size_t) r->headers_in.content_length_n;
@@ -588,10 +592,7 @@
         }
 
         r->headers_in.content_length_n -= n;
-
-    } while (r->connection->read->ready);
-
-    return NGX_AGAIN;
+    }
 }
 
 
--- a/src/http/ngx_http_script.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_script.c	Thu Mar 11 21:27:17 2010 +0300
@@ -251,8 +251,6 @@
             {
             ngx_uint_t  n;
 
-            /* NGX_HTTP_MAX_CAPTURES is 9 */
-
             if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
 
                 n = sc->source->data[i] - '0';
@@ -828,20 +826,9 @@
         e->line.data = e->sp->data;
     }
 
-    if (code->ncaptures && r->captures == NULL) {
+    rc = ngx_http_regex_exec(r, code->regex, &e->line);
 
-        r->captures = ngx_palloc(r->pool,
-                                 (NGX_HTTP_MAX_CAPTURES + 1) * 3 * sizeof(int));
-        if (r->captures == NULL) {
-            e->ip = ngx_http_script_exit;
-            e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
-            return;
-        }
-    }
-
-    rc = ngx_regex_exec(code->regex, &e->line, r->captures, code->ncaptures);
-
-    if (rc == NGX_REGEX_NO_MATCHED) {
+    if (rc == NGX_DECLINED) {
         if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
                           "\"%V\" does not match \"%V\"",
@@ -870,11 +857,7 @@
         return;
     }
 
-    if (rc < 0) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
-                      rc, &e->line, &code->name);
-
+    if (rc == NGX_ERROR) {
         e->ip = ngx_http_script_exit;
         e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
         return;
@@ -885,9 +868,6 @@
                       "\"%V\" matches \"%V\"", &code->name, &e->line);
     }
 
-    r->ncaptures = code->ncaptures;
-    r->captures_data = e->line.data;
-
     if (code->test) {
         if (code->negative_test) {
             e->sp->len = 0;
@@ -930,14 +910,14 @@
         e->buf.len = code->size;
 
         if (code->uri) {
-            if (rc && (r->quoted_uri || r->plus_in_uri)) {
+            if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
                 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
                                                  NGX_ESCAPE_ARGS);
             }
         }
 
-        for (n = 1; n < (ngx_uint_t) rc; n++) {
-            e->buf.len += r->captures[2 * n + 1] - r->captures[2 * n];
+        for (n = 2; n < r->ncaptures; n += 2) {
+            e->buf.len += r->captures[n + 1] - r->captures[n];
         }
 
     } else {
@@ -1407,6 +1387,7 @@
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
@@ -1417,7 +1398,10 @@
     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
         != NGX_OK)
     {
-        if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
+        if (of.err != NGX_ENOENT
+            && of.err != NGX_ENOTDIR
+            && of.err != NGX_ENAMETOOLONG)
+        {
             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
                           "%s \"%s\" failed", of.failed, value->data);
         }
--- a/src/http/ngx_http_script.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_script.h	Thu Mar 11 21:27:17 2010 +0300
@@ -114,10 +114,9 @@
 
 typedef struct {
     ngx_http_script_code_pt     code;
-    ngx_regex_t                *regex;
+    ngx_http_regex_t           *regex;
     ngx_array_t                *lengths;
     uintptr_t                   size;
-    uintptr_t                   ncaptures;
     uintptr_t                   status;
     uintptr_t                   next;
 
--- a/src/http/ngx_http_special_response.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_special_response.c	Thu Mar 11 21:27:17 2010 +0300
@@ -31,13 +31,13 @@
 ;
 
 
-static u_char ngx_http_msie_stub[] =
-"<!-- The padding to disable MSIE's friendly error page -->" CRLF
-"<!-- The padding to disable MSIE's friendly error page -->" CRLF
-"<!-- The padding to disable MSIE's friendly error page -->" CRLF
-"<!-- The padding to disable MSIE's friendly error page -->" CRLF
-"<!-- The padding to disable MSIE's friendly error page -->" CRLF
-"<!-- The padding to disable MSIE's friendly error page -->" CRLF
+static u_char ngx_http_msie_padding[] =
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 ;
 
 
@@ -598,12 +598,12 @@
             r->headers_out.content_length_n = ngx_http_error_pages[err].len
                                               + len;
             if (clcf->msie_padding
-                && r->headers_in.msie
+                && (r->headers_in.msie || r->headers_in.chrome)
                 && r->http_version >= NGX_HTTP_VERSION_10
                 && err >= NGX_HTTP_LEVEL_300)
             {
                 r->headers_out.content_length_n +=
-                                                sizeof(ngx_http_msie_stub) - 1;
+                                             sizeof(ngx_http_msie_padding) - 1;
                 msie_padding = 1;
             }
 
@@ -671,8 +671,8 @@
         }
 
         b->memory = 1;
-        b->pos = ngx_http_msie_stub;
-        b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1;
+        b->pos = ngx_http_msie_padding;
+        b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1;
 
         out[1].next = &out[2];
         out[2].buf = b;
--- a/src/http/ngx_http_upstream.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_upstream.c	Thu Mar 11 21:27:17 2010 +0300
@@ -366,6 +366,7 @@
         r->main->count++;
         ngx_http_upstream_cleanup(r);
         *u->cleanup = NULL;
+        u->cleanup = NULL;
     }
 
     u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
@@ -479,6 +480,8 @@
         return;
     }
 
+    u->peer.local = u->conf->local;
+
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     u->output.alignment = clcf->directio_alignment;
@@ -532,7 +535,8 @@
             if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
                 != NGX_OK)
             {
-                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
             }
 
@@ -564,7 +568,8 @@
 
         ctx = ngx_resolve_start(clcf->resolver, &temp);
         if (ctx == NULL) {
-            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
             return;
         }
 
@@ -572,7 +577,7 @@
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                           "no resolver defined to resolve %V", host);
 
-            ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
             return;
         }
 
@@ -586,7 +591,8 @@
 
         if (ngx_resolve_name(ctx) != NGX_OK) {
             u->resolved->ctx = NULL;
-            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
             return;
         }
 
@@ -596,7 +602,8 @@
 found:
 
     if (uscf->peer.init(r, uscf) != NGX_OK) {
-        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        ngx_http_upstream_finalize_request(r, u,
+                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
 
@@ -746,6 +753,11 @@
     r->cached = 1;
     c = r->cache;
 
+    if (c->header_start == c->body_start) {
+        r->http_version = NGX_HTTP_VERSION_9;
+        return ngx_http_cache_send(r);
+    }
+
     /* TODO: cache stack */
 
     u->buffer = *c->buf;
@@ -789,11 +801,13 @@
 ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
 {
     ngx_http_request_t            *r;
+    ngx_http_upstream_t           *u;
     ngx_http_upstream_resolved_t  *ur;
 
     r = ctx->data;
 
-    r->upstream->resolved->ctx = NULL;
+    u = r->upstream;
+    ur = u->resolved;
 
     if (ctx->state) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -801,12 +815,10 @@
                       &ctx->name, ctx->state,
                       ngx_resolver_strerror(ctx->state));
 
-        ngx_resolve_name_done(ctx);
-        ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
         return;
     }
 
-    ur = r->upstream->resolved;
     ur->naddrs = ctx->naddrs;
     ur->addrs = ctx->addrs;
 
@@ -827,14 +839,15 @@
 #endif
 
     if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) {
-        ngx_resolve_name_done(ctx);
-        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        ngx_http_upstream_finalize_request(r, u,
+                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
 
     ngx_resolve_name_done(ctx);
-
-    ngx_http_upstream_connect(r, r->upstream);
+    ur->ctx = NULL;
+
+    ngx_http_upstream_connect(r, u);
 }
 
 
@@ -921,10 +934,6 @@
         return;
     }
 
-    if (u->peer.connection == NULL) {
-        return;
-    }
-
 #if (NGX_HAVE_KQUEUE)
 
     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -956,7 +965,6 @@
         if (u->peer.connection == NULL) {
             ngx_http_upstream_finalize_request(r, u,
                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
-            return;
         }
 
         return;
@@ -1019,7 +1027,6 @@
     if (u->peer.connection == NULL) {
         ngx_http_upstream_finalize_request(r, u,
                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
-        return;
     }
 }
 
@@ -1542,7 +1549,7 @@
 
     /* rc == NGX_OK */
 
-    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST) {
+    if (u->headers_in.status_n > NGX_HTTP_SPECIAL_RESPONSE) {
 
         if (r->subrequest_in_memory) {
             u->buffer.last = u->buffer.pos;
@@ -1797,7 +1804,7 @@
         uri = &u->headers_in.x_accel_redirect->value;
         args.len = 0;
         args.data = NULL;
-        flags = 0;
+        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);
@@ -2099,11 +2106,6 @@
             r->cache->date = now;
             r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
 
-            if (r->headers_out.content_length_n != -1) {
-                r->cache->length = r->cache->body_start
-                                   + r->headers_out.content_length_n;
-            }
-
             ngx_http_file_cache_set_header(r, u->buffer.start);
 
         } else {
@@ -2837,6 +2839,7 @@
 
     if (u->resolved && u->resolved->ctx) {
         ngx_resolve_name_done(u->resolved->ctx);
+        u->resolved->ctx = NULL;
     }
 
     ngx_http_upstream_finalize_request(r, u, NGX_DONE);
@@ -2854,6 +2857,12 @@
 
     if (u->cleanup) {
         *u->cleanup = NULL;
+        u->cleanup = NULL;
+    }
+
+    if (u->resolved && u->resolved->ctx) {
+        ngx_resolve_name_done(u->resolved->ctx);
+        u->resolved->ctx = NULL;
     }
 
     if (u->state && u->state->response_sec) {
@@ -3035,7 +3044,7 @@
     n = 0;
 
     for (p += 8; p < last; p++) {
-        if (*p == ';' || *p == ' ') {
+        if (*p == ',' || *p == ';' || *p == ' ') {
             break;
         }
 
@@ -4196,6 +4205,41 @@
 }
 
 
+char *
+ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    char  *p = conf;
+
+    ngx_int_t     rc;
+    ngx_str_t    *value;
+    ngx_addr_t  **paddr;
+
+    paddr = (ngx_addr_t **) (p + cmd->offset);
+
+    *paddr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
+    if (*paddr == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value = cf->args->elts;
+
+    rc = ngx_parse_addr(cf->pool, *paddr, value[1].data, value[1].len);
+
+    switch (rc) {
+    case NGX_OK:
+        (*paddr)->name = value[1];
+        return NGX_CONF_OK;
+
+    case NGX_DECLINED:
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid address \"%V\"", &value[1]);
+    default:
+        return NGX_CONF_ERROR;
+    }
+}
+
+
 ngx_int_t
 ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
--- a/src/http/ngx_http_upstream.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_upstream.h	Thu Mar 11 21:27:17 2010 +0300
@@ -80,7 +80,7 @@
 
 
 typedef struct {
-    ngx_peer_addr_t                 *addrs;
+    ngx_addr_t                      *addrs;
     ngx_uint_t                       naddrs;
     ngx_uint_t                       weight;
     ngx_uint_t                       max_fails;
@@ -152,6 +152,8 @@
     ngx_array_t                     *hide_headers;
     ngx_array_t                     *pass_headers;
 
+    ngx_addr_t                      *local;
+
 #if (NGX_HTTP_CACHE)
     ngx_shm_zone_t                  *cache;
 
@@ -321,6 +323,8 @@
 void ngx_http_upstream_init(ngx_http_request_t *r);
 ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
     ngx_url_t *u, ngx_uint_t flags);
+char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
     ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);
@@ -334,5 +338,4 @@
 extern ngx_conf_bitmask_t  ngx_http_upstream_cache_method_mask[];
 
 
-
 #endif /* _NGX_HTTP_UPSTREAM_H_INCLUDED_ */
--- a/src/http/ngx_http_upstream_round_robin.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_upstream_round_robin.h	Thu Mar 11 21:27:17 2010 +0300
@@ -81,5 +81,4 @@
 #endif
 
 
-
 #endif /* _NGX_HTTP_UPSTREAM_ROUND_ROBIN_H_INCLUDED_ */
--- a/src/http/ngx_http_variables.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_variables.c	Thu Mar 11 21:27:17 2010 +0300
@@ -14,6 +14,8 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static void ngx_http_variable_request_set(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
@@ -25,6 +27,8 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
@@ -164,8 +168,7 @@
       offsetof(ngx_http_request_t, uri),
       NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
-    { ngx_string("request"), NULL, ngx_http_variable_request,
-      offsetof(ngx_http_request_t, request_line), 0, 0 },
+    { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },
 
     { ngx_string("document_root"), NULL,
       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
@@ -193,7 +196,8 @@
     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
 
     { ngx_string("request_method"), NULL,
-      ngx_http_variable_request_method, 0, 0, 0 },
+      ngx_http_variable_request_method, 0,
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
 
@@ -237,7 +241,7 @@
       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
 
     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
-      ngx_http_variable_request,
+      ngx_http_variable_request_get_size,
       offsetof(ngx_http_request_t, limit_rate),
       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
@@ -491,7 +495,7 @@
         return NULL;
     }
 
-    if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) {
+    if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
 
         if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
             == NGX_OK)
@@ -567,6 +571,28 @@
 }
 
 
+static ngx_int_t
+ngx_http_variable_request_get_size(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    size_t  *sp;
+
+    sp = (size_t *) ((char *) r + data);
+
+    v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
+    if (v->data == NULL) {
+        return NGX_ERROR;
+    }
+
+    v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+
+    return NGX_OK;
+}
+
+
 static void
 ngx_http_variable_request_set_size(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
@@ -751,6 +777,42 @@
 
 
 static ngx_int_t
+ngx_http_variable_request_line(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    u_char  *p, *s;
+
+    s = r->request_line.data;
+
+    if (s == NULL) {
+        s = r->request_start;
+
+        if (s == NULL) {
+            v->not_found = 1;
+            return NGX_OK;
+        }
+
+        for (p = s; p < r->header_in->last; p++) {
+            if (*p == CR || *p == LF) {
+                break;
+            }
+        }
+
+        r->request_line.len = p - s;
+        r->request_line.data = s;
+    }
+
+    v->len = r->request_line.len;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->data = s;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
     uintptr_t data)
 {
@@ -850,7 +912,7 @@
         v->valid = 1;
         v->no_cacheable = 0;
         v->not_found = 0;
-        v->data = (u_char *) &sin6->sin6_addr;
+        v->data = sin6->sin6_addr.s6_addr;
 
         break;
 #endif
@@ -1605,6 +1667,161 @@
 }
 
 
+#if (NGX_PCRE)
+
+static ngx_int_t
+ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
+    uintptr_t data)
+{
+    v->not_found = 1;
+    return NGX_OK;
+}
+
+
+ngx_http_regex_t *
+ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
+{
+    u_char                     *p;
+    size_t                      size;
+    ngx_str_t                   name;
+    ngx_uint_t                  i, n;
+    ngx_http_variable_t        *v;
+    ngx_http_regex_t           *re;
+    ngx_http_regex_variable_t  *rv;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    rc->pool = cf->pool;
+
+    if (ngx_regex_compile(rc) != NGX_OK) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
+        return NULL;
+    }
+
+    re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
+    if (re == NULL) {
+        return NULL;
+    }
+
+    re->regex = rc->regex;
+    re->ncaptures = rc->captures;
+
+    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+    cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
+
+    n = (ngx_uint_t) rc->named_captures;
+
+    if (n == 0) {
+        return re;
+    }
+
+    rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
+    if (rv == NULL) {
+        return NULL;
+    }
+
+    re->variables = rv;
+    re->nvariables = n;
+    re->name = rc->pattern;
+
+    size = rc->name_size;
+    p = rc->names;
+
+    for (i = 0; i < n; i++) {
+        rv[i].capture = 2 * ((p[0] << 8) + p[1]);
+
+        name.data = &p[2];
+        name.len = ngx_strlen(name.data);
+
+        v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
+        if (v == NULL) {
+            return NULL;
+        }
+
+        rv[i].index = ngx_http_get_variable_index(cf, &name);
+        if (rv[i].index == NGX_ERROR) {
+            return NULL;
+        }
+
+        v->get_handler = ngx_http_variable_not_found;
+
+        p += size;
+    }
+
+    return re;
+}
+
+
+ngx_int_t
+ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
+{
+    ngx_int_t                   rc, index;
+    ngx_uint_t                  i, n, len;
+    ngx_http_variable_value_t  *vv;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+    if (re->ncaptures) {
+        len = cmcf->ncaptures;
+
+        if (r->captures == NULL) {
+            r->captures = ngx_palloc(r->pool, len * sizeof(int));
+            if (r->captures == NULL) {
+                return NGX_ERROR;
+            }
+        }
+
+    } else {
+        len = 0;
+    }
+
+    rc = ngx_regex_exec(re->regex, s, r->captures, len);
+
+    if (rc == NGX_REGEX_NO_MATCHED) {
+        return NGX_DECLINED;
+    }
+
+    if (rc < 0) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+                      rc, s, &re->name);
+        return NGX_ERROR;
+    }
+
+    for (i = 0; i < re->nvariables; i++) {
+
+        n = re->variables[i].capture;
+        index = re->variables[i].index;
+        vv = &r->variables[index];
+
+        vv->len = r->captures[n + 1] - r->captures[n];
+        vv->valid = 1;
+        vv->no_cacheable = 0;
+        vv->not_found = 0;
+        vv->data = &s->data[r->captures[n]];
+
+#if (NGX_DEBUG)
+        {
+        ngx_http_variable_t  *v;
+
+        v = cmcf->variables.elts;
+
+        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "http regex set $%V to \"%*s\"",
+                       &v[index].name, vv->len, vv->data);
+        }
+#endif
+    }
+
+    r->ncaptures = rc * 2;
+    r->captures_data = s->data;
+
+    return NGX_OK;
+}
+
+#endif
+
+
 ngx_int_t
 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
 {
--- a/src/http/ngx_http_variables.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/http/ngx_http_variables.h	Thu Mar 11 21:27:17 2010 +0300
@@ -59,6 +59,31 @@
 #define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL;
 
 
+#if (NGX_PCRE)
+
+typedef struct {
+    ngx_uint_t                    capture;
+    ngx_int_t                     index;
+} ngx_http_regex_variable_t;
+
+
+typedef struct {
+    ngx_regex_t                  *regex;
+    ngx_uint_t                    ncaptures;
+    ngx_http_regex_variable_t    *variables;
+    ngx_uint_t                    nvariables;
+    ngx_str_t                     name;
+} ngx_http_regex_t;
+
+
+ngx_http_regex_t *ngx_http_regex_compile(ngx_conf_t *cf,
+    ngx_regex_compile_t *rc);
+ngx_int_t ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re,
+    ngx_str_t *s);
+
+#endif
+
+
 ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf);
 ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf);
 
--- a/src/mail/ngx_mail.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/mail/ngx_mail.h	Thu Mar 11 21:27:17 2010 +0300
@@ -394,7 +394,7 @@
 
 
 /* STUB */
-void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_peer_addr_t *peer);
+void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer);
 void ngx_mail_auth_http_init(ngx_mail_session_t *s);
 /**/
 
--- a/src/mail/ngx_mail_auth_http_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/mail/ngx_mail_auth_http_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -12,7 +12,7 @@
 
 
 typedef struct {
-    ngx_peer_addr_t                *peer;
+    ngx_addr_t                     *peer;
 
     ngx_msec_t                      timeout;
 
@@ -457,7 +457,7 @@
     time_t               timer;
     size_t               len, size;
     ngx_int_t            rc, port, n;
-    ngx_peer_addr_t     *peer;
+    ngx_addr_t          *peer;
     struct sockaddr_in  *sin;
 
     ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
@@ -764,7 +764,7 @@
                 return;
             }
 
-            peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_peer_addr_t));
+            peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t));
             if (peer == NULL) {
                 ngx_destroy_pool(ctx->pool);
                 ngx_mail_session_internal_server_error(s);
@@ -795,8 +795,7 @@
 
             sin->sin_port = htons((in_port_t) port);
 
-            ctx->addr.data[ctx->addr.len] = '\0';
-            sin->sin_addr.s_addr = inet_addr((char *) ctx->addr.data);
+            sin->sin_addr.s_addr = ngx_inet_addr(ctx->addr.data, ctx->addr.len);
             if (sin->sin_addr.s_addr == INADDR_NONE) {
                 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                               "auth http server %V sent invalid server "
@@ -1406,7 +1405,14 @@
 
     ahcf->peer = u.addrs;
 
-    ahcf->host_header = u.host;
+    if (u.family != AF_UNIX) {
+        ahcf->host_header = u.host;
+
+    } else {
+        ahcf->host_header.len = sizeof("localhost") - 1;
+        ahcf->host_header.data = (u_char *) "localhost";
+    }
+
     ahcf->uri = u.uri;
 
     if (ahcf->uri.len == 0) {
--- a/src/mail/ngx_mail_pop3_handler.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/mail/ngx_mail_pop3_handler.c	Thu Mar 11 21:27:17 2010 +0300
@@ -188,7 +188,6 @@
 
             default:
                 rc = NGX_MAIL_PARSE_INVALID_COMMAND;
-                s->mail_state = ngx_pop3_start;
                 break;
             }
 
@@ -215,7 +214,6 @@
 
             default:
                 rc = NGX_MAIL_PARSE_INVALID_COMMAND;
-                s->mail_state = ngx_pop3_start;
                 break;
             }
 
--- a/src/mail/ngx_mail_proxy_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/mail/ngx_mail_proxy_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -108,7 +108,7 @@
 
 
 void
-ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_peer_addr_t *peer)
+ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
 {
     int                        keepalive;
     ngx_int_t                  rc;
--- a/src/mail/ngx_mail_smtp_handler.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/mail/ngx_mail_smtp_handler.c	Thu Mar 11 21:27:17 2010 +0300
@@ -191,7 +191,7 @@
 
     if (ctx->state) {
         ngx_log_error(NGX_LOG_ERR, c->log, 0,
-                      "%V could not be resolved (%i: %s)",
+                      "\"%V\" could not be resolved (%i: %s)",
                       &ctx->name, ctx->state,
                       ngx_resolver_strerror(ctx->state));
 
--- a/src/mail/ngx_mail_ssl_module.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/mail/ngx_mail_ssl_module.c	Thu Mar 11 21:27:17 2010 +0300
@@ -9,7 +9,7 @@
 #include <ngx_mail.h>
 
 
-#define NGX_DEFAULT_CIPHERS  "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
+#define NGX_DEFAULT_CIPHERS  "HIGH:!ADH:!MD5"
 
 
 static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
@@ -198,8 +198,7 @@
                          prev->prefer_server_ciphers, 0);
 
     ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
-                         (NGX_CONF_BITMASK_SET
-                          |NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
+                         (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
 
     ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
     ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");
--- a/src/os/unix/ngx_alloc.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_alloc.c	Thu Mar 11 21:27:17 2010 +0300
@@ -21,7 +21,7 @@
     p = malloc(size);
     if (p == NULL) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
-                      "malloc() %uz bytes failed", size);
+                      "malloc(%uz) failed", size);
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);
@@ -51,15 +51,18 @@
 ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
 {
     void  *p;
+    int    err;
 
-    if (posix_memalign(&p, alignment, size) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
-                      "posix_memalign() %uz bytes aligned to %uz failed",
-                      size, alignment);
+    err = posix_memalign(&p, alignment, size);
+
+    if (err) {
+        ngx_log_error(NGX_LOG_EMERG, log, err,
+                      "posix_memalign(%uz, %uz) failed", alignment, size);
+        p = NULL;
     }
 
-    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0,
-                   "posix_memalign: %p:%uz", p, size);
+    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
+                   "posix_memalign: %p:%uz @%uz", p, size, alignment);
 
     return p;
 }
@@ -74,12 +77,11 @@
     p = memalign(alignment, size);
     if (p == NULL) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
-                      "memalign() %uz bytes aligned to %uz failed",
-                      size, alignment);
+                      "memalign(%uz, %uz) failed", alignment, size);
     }
 
-    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0,
-                   "memalign: %p:%uz", p, size);
+    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
+                   "memalign: %p:%uz @%uz", p, size, alignment);
 
     return p;
 }
--- a/src/os/unix/ngx_atomic.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_atomic.h	Thu Mar 11 21:27:17 2010 +0300
@@ -12,7 +12,32 @@
 #include <ngx_core.h>
 
 
-#if (NGX_DARWIN_ATOMIC)
+#if (NGX_HAVE_LIBATOMIC)
+
+#define AO_REQUIRE_CAS
+#include <atomic_ops.h>
+
+#define NGX_HAVE_ATOMIC_OPS  1
+
+typedef long                        ngx_atomic_int_t;
+typedef AO_t                        ngx_atomic_uint_t;
+typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
+
+#if (NGX_PTR_SIZE == 8)
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
+#else
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
+#endif
+
+#define ngx_atomic_cmp_set(lock, old, new)                                    \
+    AO_compare_and_swap(lock, old, new)
+#define ngx_atomic_fetch_add(value, add)                                      \
+    AO_fetch_and_add(value, add)
+#define ngx_memory_barrier()        AO_nop()
+#define ngx_cpu_pause()
+
+
+#elif (NGX_DARWIN_ATOMIC)
 
 /*
  * use Darwin 8 atomic(3) and barrier(3) operations
@@ -31,7 +56,7 @@
 
 typedef int64_t                     ngx_atomic_int_t;
 typedef uint64_t                    ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
 
 #define ngx_atomic_cmp_set(lock, old, new)                                    \
     OSAtomicCompareAndSwap64Barrier(old, new, (int64_t *) lock)
@@ -43,7 +68,7 @@
 
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
 
 #define ngx_atomic_cmp_set(lock, old, new)                                    \
     OSAtomicCompareAndSwap32Barrier(old, new, (int32_t *) lock)
@@ -60,15 +85,45 @@
 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
 
 
-#else /* !(NGX_DARWIN) */
+#elif (NGX_HAVE_GCC_ATOMIC)
+
+/* GCC 4.1 builtin atomic operations */
+
+#define NGX_HAVE_ATOMIC_OPS  1
+
+typedef long                        ngx_atomic_int_t;
+typedef unsigned long               ngx_atomic_uint_t;
+
+#if (NGX_PTR_SIZE == 8)
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
+#else
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
+#endif
+
+typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
 
 
-#if ( __i386__ || __i386 )
+#define ngx_atomic_cmp_set(lock, old, set)                                    \
+    __sync_bool_compare_and_swap(lock, old, set)
+
+#define ngx_atomic_fetch_add(value, add)                                      \
+    __sync_fetch_and_add(value, add)
+
+#define ngx_memory_barrier()        __sync_synchronize()
+
+#if ( __i386__ || __i386 || __amd64__ || __amd64 )
+#define ngx_cpu_pause()             __asm__ ("pause")
+#else
+#define ngx_cpu_pause()
+#endif
+
+
+#elif ( __i386__ || __i386 )
 
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;
 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
 
 
 #if ( __SUNPRO_C )
@@ -109,7 +164,7 @@
 typedef int64_t                     ngx_atomic_int_t;
 typedef uint64_t                    ngx_atomic_uint_t;
 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
 
 
 #if ( __SUNPRO_C )
@@ -151,13 +206,13 @@
 
 typedef int64_t                     ngx_atomic_int_t;
 typedef uint64_t                    ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
 
 #else
 
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
 
 #endif
 
@@ -188,13 +243,13 @@
 
 typedef int64_t                     ngx_atomic_int_t;
 typedef uint64_t                    ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-9223372036854775808") - 1)
 
 #else
 
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
 
 #endif
 
@@ -203,9 +258,6 @@
 
 #include "ngx_gcc_atomic_ppc.h"
 
-
-#endif
-
 #endif
 
 
@@ -216,7 +268,7 @@
 typedef int32_t                     ngx_atomic_int_t;
 typedef uint32_t                    ngx_atomic_uint_t;
 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
-#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
+#define NGX_ATOMIC_T_LEN            (sizeof("-2147483648") - 1)
 
 
 static ngx_inline ngx_atomic_uint_t
--- a/src/os/unix/ngx_channel.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_channel.c	Thu Mar 11 21:27:17 2010 +0300
@@ -36,7 +36,18 @@
         cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
         cmsg.cm.cmsg_level = SOL_SOCKET;
         cmsg.cm.cmsg_type = SCM_RIGHTS;
-        *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
+
+        /*
+         * We have to use ngx_memcpy() instead of simple
+         *   *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
+         * because some gcc 4.4 with -O2/3/s optimization issues the warning:
+         *   dereferencing type-punned pointer will break strict-aliasing rules
+         *
+         * Fortunately, gcc with -O1 compiles this ngx_memcpy()
+         * in the same simple assigment as in the code above
+         */
+
+        ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
     }
 
     msg.msg_flags = 0;
@@ -153,7 +164,9 @@
             return NGX_ERROR;
         }
 
-        ch->fd = *(int *) CMSG_DATA(&cmsg.cm);
+        /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */
+
+        ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int));
     }
 
     if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
--- a/src/os/unix/ngx_file_aio_read.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_file_aio_read.c	Thu Mar 11 21:27:17 2010 +0300
@@ -39,12 +39,11 @@
 ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
     ngx_pool_t *pool)
 {
-    int                 n;
-    ngx_event_t        *ev;
-    ngx_event_aio_t    *aio;
-    static ngx_uint_t   enosys = 0;
+    int               n;
+    ngx_event_t      *ev;
+    ngx_event_aio_t  *aio;
 
-    if (enosys) {
+    if (!ngx_file_aio) {
         return ngx_read_file(file, buf, size, offset);
     }
 
@@ -116,7 +115,7 @@
                       "aio_read(\"%V\") failed", &file->name);
 
         if (n == NGX_ENOSYS) {
-            enosys = 1;
+            ngx_file_aio = 0;
             return ngx_read_file(file, buf, size, offset);
         }
 
--- a/src/os/unix/ngx_files.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_files.c	Thu Mar 11 21:27:17 2010 +0300
@@ -8,6 +8,13 @@
 #include <ngx_core.h>
 
 
+#if (NGX_HAVE_FILE_AIO)
+
+ngx_uint_t  ngx_file_aio = 1;
+
+#endif
+
+
 ssize_t
 ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
 {
@@ -22,7 +29,7 @@
 
     if (n == -1) {
         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
-                      "pread() failed, file \"%s\"", file->name.data);
+                      "pread() \"%s\" failed", file->name.data);
         return NGX_ERROR;
     }
 
@@ -30,7 +37,8 @@
 
     if (file->sys_offset != offset) {
         if (lseek(file->fd, offset, SEEK_SET) == -1) {
-            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
+            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
+                          "lseek() \"%s\" failed", file->name.data);
             return NGX_ERROR;
         }
 
@@ -40,7 +48,8 @@
     n = read(file->fd, buf, size);
 
     if (n == -1) {
-        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed");
+        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
+                      "read() \"%s\" failed", file->name.data);
         return NGX_ERROR;
     }
 
@@ -57,57 +66,66 @@
 ssize_t
 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
 {
-    ssize_t  n;
+    ssize_t  n, written;
 
     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
                    "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
 
+    written = 0;
+
 #if (NGX_HAVE_PWRITE)
 
-    n = pwrite(file->fd, buf, size, offset);
+    for ( ;; ) {
+        n = pwrite(file->fd, buf, size, offset);
+
+        if (n == -1) {
+            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
+                          "pwrite() \"%s\" failed", file->name.data);
+            return NGX_ERROR;
+        }
 
-    if (n == -1) {
-        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed");
-        return NGX_ERROR;
-    }
+        file->offset += n;
+        written += n;
 
-    if ((size_t) n != size) {
-        ngx_log_error(NGX_LOG_CRIT, file->log, 0,
-                      "pwrite() has written only %z of %uz", n, size);
-        return NGX_ERROR;
+        if ((size_t) n == size) {
+            return written;
+        }
+
+        offset += n;
+        size -= n;
     }
 
 #else
 
     if (file->sys_offset != offset) {
         if (lseek(file->fd, offset, SEEK_SET) == -1) {
-            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
+            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
+                          "lseek() \"%s\" failed", file->name.data);
             return NGX_ERROR;
         }
 
         file->sys_offset = offset;
     }
 
-    n = write(file->fd, buf, size);
+    for ( ;; ) {
+        n = write(file->fd, buf, size);
 
-    if (n == -1) {
-        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed");
-        return NGX_ERROR;
-    }
+        if (n == -1) {
+            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
+                          "write() \"%s\" failed", file->name.data);
+            return NGX_ERROR;
+        }
 
-    if ((size_t) n != size) {
-        ngx_log_error(NGX_LOG_CRIT, file->log, 0,
-                      "write() has written only %z of %uz", n, size);
-        return NGX_ERROR;
-    }
+        file->offset += n;
+        written += n;
 
-    file->sys_offset += n;
-
-#endif
+        if ((size_t) n == size) {
+            return written;
+        }
 
-    file->offset += n;
-
-    return n;
+        size -= n;
+    }
+#endif
 }
 
 
@@ -191,7 +209,7 @@
         if (file->sys_offset != offset) {
             if (lseek(file->fd, offset, SEEK_SET) == -1) {
                 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
-                              "lseek() failed");
+                              "lseek() \"%s\" failed", file->name.data);
                 return NGX_ERROR;
             }
 
@@ -202,13 +220,14 @@
 
         if (n == -1) {
             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
-                          "writev() failed");
+                          "writev() \"%s\" failed", file->name.data);
             return NGX_ERROR;
         }
 
         if ((size_t) n != size) {
             ngx_log_error(NGX_LOG_CRIT, file->log, 0,
-                          "writev() has written only %z of %uz", n, size);
+                          "writev() \"%s\" has written only %z of %uz",
+                          file->name.data, n, size);
             return NGX_ERROR;
         }
 
@@ -262,9 +281,8 @@
     if (dir->de) {
 #if (NGX_HAVE_D_TYPE)
         dir->type = dir->de->d_type;
-        dir->valid_type = dir->type ? 1 : 0;
 #else
-        dir->valid_type = 0;
+        dir->type = 0;
 #endif
         return NGX_OK;
     }
@@ -384,6 +402,26 @@
 }
 
 
+#if (NGX_HAVE_POSIX_FADVISE)
+
+ngx_int_t
+ngx_read_ahead(ngx_fd_t fd, size_t n)
+{
+    int  err;
+
+    err = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+
+    if (err == 0) {
+        return 0;
+    }
+
+    ngx_set_errno(err);
+    return NGX_FILE_ERROR;
+}
+
+#endif
+
+
 #if (NGX_HAVE_O_DIRECT)
 
 ngx_int_t
@@ -394,7 +432,7 @@
     flags = fcntl(fd, F_GETFL);
 
     if (flags == -1) {
-        return -1;
+        return NGX_FILE_ERROR;
     }
 
     return fcntl(fd, F_SETFL, flags | O_DIRECT);
@@ -409,7 +447,7 @@
     flags = fcntl(fd, F_GETFL);
 
     if (flags == -1) {
-        return -1;
+        return NGX_FILE_ERROR;
     }
 
     return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
--- a/src/os/unix/ngx_files.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_files.h	Thu Mar 11 21:27:17 2010 +0300
@@ -24,7 +24,6 @@
 
     unsigned                     type:8;
     unsigned                     valid_info:1;
-    unsigned                     valid_type:1;
 } ngx_dir_t;
 
 
@@ -142,7 +141,7 @@
 #define ngx_is_dir(sb)           (S_ISDIR((sb)->st_mode))
 #define ngx_is_file(sb)          (S_ISREG((sb)->st_mode))
 #define ngx_is_link(sb)          (S_ISLNK((sb)->st_mode))
-#define ngx_is_exec(sb)          ((sb)->st_mode & S_IXUSR)
+#define ngx_is_exec(sb)          (((sb)->st_mode & S_IXUSR) == S_IXUSR)
 #define ngx_file_access(sb)      ((sb)->st_mode & 0777)
 #define ngx_file_size(sb)        (sb)->st_size
 #define ngx_file_mtime(sb)       (sb)->st_mtime
@@ -200,31 +199,31 @@
 #else
 #define ngx_de_namelen(dir)      ngx_strlen((dir)->de->d_name)
 #endif
-#define ngx_de_info(name, dir)   stat((const char *) name, &(dir)->info)
+
+static ngx_inline ngx_int_t
+ngx_de_info(u_char *name, ngx_dir_t *dir)
+{
+    dir->type = 0;
+    return stat((const char *) name, &dir->info);
+}
+
 #define ngx_de_info_n            "stat()"
 #define ngx_de_link_info(name, dir)  lstat((const char *) name, &(dir)->info)
 #define ngx_de_link_info_n       "lstat()"
 
 #if (NGX_HAVE_D_TYPE)
 
-#if (NGX_LINUX)
-
-/* XFS on Linux does not set dirent.d_type */
+/*
+ * some file systems (e.g. XFS on Linux and CD9660 on FreeBSD)
+ * do not set dirent.d_type
+ */
 
 #define ngx_de_is_dir(dir)                                                   \
     (((dir)->type) ? ((dir)->type == DT_DIR) : (S_ISDIR((dir)->info.st_mode)))
 #define ngx_de_is_file(dir)                                                  \
     (((dir)->type) ? ((dir)->type == DT_REG) : (S_ISREG((dir)->info.st_mode)))
 #define ngx_de_is_link(dir)                                                  \
-    (((dir)->type) ? ((dir)->type == DT_LINK) : (S_ISLNK((dir)->info.st_mode)))
-
-#else
-
-#define ngx_de_is_dir(dir)       ((dir)->type == DT_DIR)
-#define ngx_de_is_file(dir)      ((dir)->type == DT_REG)
-#define ngx_de_is_link(dir)      ((dir)->type == DT_LINK)
-
-#endif /* NGX_LINUX */
+    (((dir)->type) ? ((dir)->type == DT_LNK) : (S_ISLNK((dir)->info.st_mode)))
 
 #else
 
@@ -254,6 +253,28 @@
 #define ngx_unlock_fd_n          "fcntl(F_SETLK, F_UNLCK)"
 
 
+#if (NGX_HAVE_F_READAHEAD)
+
+#define NGX_HAVE_READ_AHEAD      1
+
+#define ngx_read_ahead(fd, n)    fcntl(fd, F_READAHEAD, (int) n)
+#define ngx_read_ahead_n         "fcntl(fd, F_READAHEAD)"
+
+#elif (NGX_HAVE_POSIX_FADVISE)
+
+#define NGX_HAVE_READ_AHEAD      1
+
+ngx_int_t ngx_read_ahead(ngx_fd_t fd, size_t n);
+#define ngx_read_ahead_n         "posix_fadvise(POSIX_FADV_SEQUENTIAL)"
+
+#else
+
+#define ngx_read_ahead(fd, n)    0
+#define ngx_read_ahead_n         "ngx_read_ahead_n"
+
+#endif
+
+
 #if (NGX_HAVE_O_DIRECT)
 
 ngx_int_t ngx_directio_on(ngx_fd_t fd);
@@ -292,6 +313,8 @@
 ssize_t ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size,
     off_t offset, ngx_pool_t *pool);
 
+extern ngx_uint_t  ngx_file_aio;
+
 #endif
 
 
--- a/src/os/unix/ngx_freebsd_rfork_thread.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_freebsd_rfork_thread.h	Thu Mar 11 21:27:17 2010 +0300
@@ -118,5 +118,4 @@
 typedef int (*ngx_rfork_thread_func_pt)(void *arg);
 
 
-
 #endif /* _NGX_FREEBSD_RFORK_THREAD_H_INCLUDED_ */
--- a/src/os/unix/ngx_gcc_atomic_x86.h	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_gcc_atomic_x86.h	Thu Mar 11 21:27:17 2010 +0300
@@ -122,5 +122,5 @@
 
 #define ngx_memory_barrier()    __asm__ volatile ("" ::: "memory")
 
-/* old as does not support "pause" opcode */
+/* old "as" does not support "pause" opcode */
 #define ngx_cpu_pause()         __asm__ (".byte 0xf3, 0x90")
--- a/src/os/unix/ngx_linux_aio_read.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_linux_aio_read.c	Thu Mar 11 21:27:17 2010 +0300
@@ -27,13 +27,12 @@
 ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
     ngx_pool_t *pool)
 {
-    long                n;
-    struct iocb        *piocb[1];
-    ngx_event_t        *ev;
-    ngx_event_aio_t    *aio;
-    static ngx_uint_t   enosys = 0;
+    long              n;
+    struct iocb      *piocb[1];
+    ngx_event_t      *ev;
+    ngx_event_aio_t  *aio;
 
-    if (enosys) {
+    if (!ngx_file_aio) {
         return ngx_read_file(file, buf, size, offset);
     }
 
@@ -109,7 +108,7 @@
                   "io_submit(\"%V\") failed", &file->name);
 
     if (n == NGX_ENOSYS) {
-        enosys = 1;
+        ngx_file_aio = 0;
         return ngx_read_file(file, buf, size, offset);
     }
 
--- a/src/os/unix/ngx_posix_init.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_posix_init.c	Thu Mar 11 21:27:17 2010 +0300
@@ -44,8 +44,6 @@
     ngx_pagesize = getpagesize();
     ngx_cacheline_size = NGX_CPU_CACHE_LINE;
 
-    n = ngx_pagesize;
-
     for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
 
     if (ngx_ncpu == 0) {
--- a/src/os/unix/ngx_process.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_process.c	Thu Mar 11 21:27:17 2010 +0300
@@ -388,6 +388,7 @@
         break;
 
     case NGX_PROCESS_WORKER:
+    case NGX_PROCESS_HELPER:
         switch (signo) {
 
         case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
--- a/src/os/unix/ngx_process_cycle.c	Tue Sep 15 03:43:40 2009 +0400
+++ b/src/os/unix/ngx_process_cycle.c	Thu Mar 11 21:27:17 2010 +0300
@@ -86,7 +86,7 @@
     u_char            *p;
     size_t             size;
     ngx_int_t          i;
-    ngx_uint_t         n;
+    ngx_uint_t         n, sigio;
     sigset_t           set;
     struct itimerval   itv;
     ngx_uint_t         live;
@@ -139,11 +139,13 @@
 
     ngx_new_binary = 0;
     delay = 0;
+    sigio = 0;
     live = 1;
 
     for ( ;; ) {
         if (delay) {
             if (ngx_sigalrm) {
+                sigio = 0;
                 delay *= 2;
                 ngx_sigalrm = 0;
             }
@@ -168,7 +170,8 @@
 
         ngx_time_update(0, 0);
 
-        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up");
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                       "wake up, sigio %i", sigio);
 
         if (ngx_reap) {
             ngx_reap = 0;
@@ -186,6 +189,13 @@
                 delay = 50;
             }
 
+            if (sigio) {
+                sigio--;
+                continue;
+            }
+
+            sigio = ccf->worker_processes + 2 /* cache processes */;
+
             if (delay > 1000) {
                 ngx_signal_worker_processes(cycle, SIGKILL);
             } else {
@@ -675,6 +685,8 @@
         }
     }
 
+    ngx_close_listening_sockets(cycle);
+
     /*