Codebase list nginx / 59c5403
Imported Upstream version 1.6.0 Christos Trochalakis 10 years ago
164 changed file(s) with 9235 addition(s) and 2861 deletion(s). Raw diff Collapse all Expand all
00
1 Changes with nginx 1.4.7 18 Mar 2014
1 Changes with nginx 1.6.0 24 Apr 2014
2
3 *) 1.6.x stable branch.
4
5
6 Changes with nginx 1.5.13 08 Apr 2014
7
8 *) Change: improved hash table handling; the default values of the
9 "variables_hash_max_size" and "types_hash_bucket_size" were changed
10 to 1024 and 64 respectively.
11
12 *) Feature: the ngx_http_mp4_module now supports the "end" argument.
13
14 *) Feature: byte ranges support in the ngx_http_mp4_module and while
15 saving responses to cache.
16
17 *) Bugfix: alerts "ngx_slab_alloc() failed: no memory" no longer logged
18 when using shared memory in the "ssl_session_cache" directive and in
19 the ngx_http_limit_req_module.
20
21 *) Bugfix: the "underscores_in_headers" directive did not allow
22 underscore as a first character of a header.
23 Thanks to Piotr Sikora.
24
25 *) Bugfix: cache manager might hog CPU on exit in nginx/Windows.
26
27 *) Bugfix: nginx/Windows terminated abnormally if the
28 "ssl_session_cache" directive was used with the "shared" parameter.
29
30 *) Bugfix: in the ngx_http_spdy_module.
31
32
33 Changes with nginx 1.5.12 18 Mar 2014
234
335 *) Security: a heap memory buffer overflow might occur in a worker
436 process while handling a specially crafted request by
739 Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr.
840 Manuel Sadosky, Buenos Aires, Argentina.
941
42 *) Feature: the "proxy_protocol" parameters of the "listen" and
43 "real_ip_header" directives, the $proxy_protocol_addr variable.
44
1045 *) Bugfix: in the "fastcgi_next_upstream" directive.
1146 Thanks to Lucas Molas.
1247
1348
14 Changes with nginx 1.4.6 04 Mar 2014
49 Changes with nginx 1.5.11 04 Mar 2014
50
51 *) Security: memory corruption might occur in a worker process on 32-bit
52 platforms while handling a specially crafted request by
53 ngx_http_spdy_module, potentially resulting in arbitrary code
54 execution (CVE-2014-0088); the bug had appeared in 1.5.10.
55 Thanks to Lucas Molas, researcher at Programa STIC, Fundación Dr.
56 Manuel Sadosky, Buenos Aires, Argentina.
57
58 *) Feature: the $ssl_session_reused variable.
1559
1660 *) Bugfix: the "client_max_body_size" directive might not work when
1761 reading a request body using chunked transfer encoding; the bug had
2165 *) Bugfix: a segmentation fault might occur in a worker process when
2266 proxying WebSocket connections.
2367
24
25 Changes with nginx 1.4.5 11 Feb 2014
68 *) Bugfix: a segmentation fault might occur in a worker process if the
69 ngx_http_spdy_module was used on 32-bit platforms; the bug had
70 appeared in 1.5.10.
71
72 *) Bugfix: the $upstream_status variable might contain wrong data if the
73 "proxy_cache_use_stale" or "proxy_cache_revalidate" directives were
74 used.
75 Thanks to Piotr Sikora.
76
77 *) Bugfix: a segmentation fault might occur in a worker process if
78 errors with code 400 were redirected to a named location using the
79 "error_page" directive.
80
81 *) Bugfix: nginx/Windows could not be built with Visual Studio 2013.
82
83
84 Changes with nginx 1.5.10 04 Feb 2014
85
86 *) Feature: the ngx_http_spdy_module now uses SPDY 3.1 protocol.
87 Thanks to Automattic and MaxCDN for sponsoring this work.
88
89 *) Feature: the ngx_http_mp4_module now skips tracks too short for a
90 seek requested.
91
92 *) Bugfix: a segmentation fault might occur in a worker process if the
93 $ssl_session_id variable was used in logs; the bug had appeared in
94 1.5.9.
95
96 *) Bugfix: the $date_local and $date_gmt variables used wrong format
97 outside of the ngx_http_ssi_filter_module.
98
99 *) Bugfix: client connections might be immediately closed if deferred
100 accept was used; the bug had appeared in 1.3.15.
101
102 *) Bugfix: alerts "getsockopt(TCP_FASTOPEN) ... failed" appeared in logs
103 during binary upgrade on Linux; the bug had appeared in 1.5.8.
104 Thanks to Piotr Sikora.
105
106
107 Changes with nginx 1.5.9 22 Jan 2014
108
109 *) Change: now nginx expects escaped URIs in "X-Accel-Redirect" headers.
110
111 *) Feature: the "ssl_buffer_size" directive.
112
113 *) Feature: the "limit_rate" directive can now be used to rate limit
114 responses sent in SPDY connections.
115
116 *) Feature: the "spdy_chunk_size" directive.
117
118 *) Feature: the "ssl_session_tickets" directive.
119 Thanks to Dirkjan Bussink.
26120
27121 *) Bugfix: the $ssl_session_id variable contained full session
28122 serialized instead of just a session id.
29123 Thanks to Ivan Ristić.
30124
31 *) Bugfix: client connections might be immediately closed if deferred
32 accept was used; the bug had appeared in 1.3.15.
125 *) Bugfix: nginx incorrectly handled escaped "?" character in the
126 "include" SSI command.
127
128 *) Bugfix: the ngx_http_dav_module did not unescape destination URI of
129 the COPY and MOVE methods.
130
131 *) Bugfix: resolver did not understand domain names with a trailing dot.
132 Thanks to Yichun Zhang.
33133
34134 *) Bugfix: alerts "zero size buf in output" might appear in logs while
35135 proxying; the bug had appeared in 1.3.9.
40140 *) Bugfix: proxied WebSocket connections might hang right after
41141 handshake if the select, poll, or /dev/poll methods were used.
42142
143 *) Bugfix: the "xclient" directive of the mail proxy module incorrectly
144 handled IPv6 client addresses.
145
146
147 Changes with nginx 1.5.8 17 Dec 2013
148
149 *) Feature: IPv6 support in resolver.
150
151 *) Feature: the "listen" directive supports the "fastopen" parameter.
152 Thanks to Mathew Rodley.
153
154 *) Feature: SSL support in the ngx_http_uwsgi_module.
155 Thanks to Roberto De Ioris.
156
157 *) Feature: vim syntax highlighting scripts were added to contrib.
158 Thanks to Evan Miller.
159
43160 *) Bugfix: a timeout might occur while reading client request body in an
44161 SSL connection using chunked transfer encoding.
45162
46 *) Bugfix: memory leak in nginx/Windows.
47
48
49 Changes with nginx 1.4.4 19 Nov 2013
163 *) Bugfix: the "master_process" directive did not work correctly in
164 nginx/Windows.
165
166 *) Bugfix: the "setfib" parameter of the "listen" directive might not
167 work.
168
169 *) Bugfix: in the ngx_http_spdy_module.
170
171
172 Changes with nginx 1.5.7 19 Nov 2013
50173
51174 *) Security: a character following an unescaped space in a request line
52175 was handled incorrectly (CVE-2013-4547); the bug had appeared in
53176 0.8.41.
54177 Thanks to Ivan Fratric of the Google Security Team.
55178
56
57 Changes with nginx 1.4.3 08 Oct 2013
179 *) Change: a logging level of auth_basic errors about no user/password
180 provided has been lowered from "error" to "info".
181
182 *) Feature: the "proxy_cache_revalidate", "fastcgi_cache_revalidate",
183 "scgi_cache_revalidate", and "uwsgi_cache_revalidate" directives.
184
185 *) Feature: the "ssl_session_ticket_key" directive.
186 Thanks to Piotr Sikora.
187
188 *) Bugfix: the directive "add_header Cache-Control ''" added a
189 "Cache-Control" response header line with an empty value.
190
191 *) Bugfix: the "satisfy any" directive might return 403 error instead of
192 401 if auth_request and auth_basic directives were used.
193 Thanks to Jan Marc Hoffmann.
194
195 *) Bugfix: the "accept_filter" and "deferred" parameters of the "listen"
196 directive were ignored for listen sockets created during binary
197 upgrade.
198 Thanks to Piotr Sikora.
199
200 *) Bugfix: some data received from a backend with unbufferred proxy
201 might not be sent to a client immediately if "gzip" or "gunzip"
202 directives were used.
203 Thanks to Yichun Zhang.
204
205 *) Bugfix: in error handling in ngx_http_gunzip_filter_module.
206
207 *) Bugfix: responses might hang if the ngx_http_spdy_module was used
208 with the "auth_request" directive.
209
210 *) Bugfix: memory leak in nginx/Windows.
211
212
213 Changes with nginx 1.5.6 01 Oct 2013
214
215 *) Feature: the "fastcgi_buffering" directive.
216
217 *) Feature: the "proxy_ssl_protocols" and "proxy_ssl_ciphers"
218 directives.
219 Thanks to Piotr Sikora.
220
221 *) Feature: optimization of SSL handshakes when using long certificate
222 chains.
223
224 *) Feature: the mail proxy supports SMTP pipelining.
225
226 *) Bugfix: in the ngx_http_auth_basic_module when using "$apr1$"
227 password encryption method.
228 Thanks to Markus Linnala.
229
230 *) Bugfix: in MacOSX, Cygwin, and nginx/Windows incorrect location might
231 be used to process a request if locations were given using characters
232 in different cases.
233
234 *) Bugfix: automatic redirect with appended trailing slash for proxied
235 locations might not work.
236
237 *) Bugfix: in the mail proxy server.
238
239 *) Bugfix: in the ngx_http_spdy_module.
240
241
242 Changes with nginx 1.5.5 17 Sep 2013
243
244 *) Change: now nginx assumes HTTP/1.0 by default if it is not able to
245 detect protocol reliably.
246
247 *) Feature: the "disable_symlinks" directive now uses O_PATH on Linux.
248
249 *) Feature: now nginx uses EPOLLRDHUP events to detect premature
250 connection close by clients if the "epoll" method is used.
251
252 *) Bugfix: in the "valid_referers" directive if the "server_names"
253 parameter was used.
254
255 *) Bugfix: the $request_time variable did not work in nginx/Windows.
256
257 *) Bugfix: in the "image_filter" directive.
258 Thanks to Lanshun Zhou.
259
260 *) Bugfix: OpenSSL 1.0.1f compatibility.
261 Thanks to Piotr Sikora.
262
263
264 Changes with nginx 1.5.4 27 Aug 2013
265
266 *) Change: the "js" extension MIME type has been changed to
267 "application/javascript"; default value of the "charset_types"
268 directive was changed accordingly.
269
270 *) Change: now the "image_filter" directive with the "size" parameter
271 returns responses with the "application/json" MIME type.
272
273 *) Feature: the ngx_http_auth_request_module.
274
275 *) Bugfix: a segmentation fault might occur on start or during
276 reconfiguration if the "try_files" directive was used with an empty
277 parameter.
278
279 *) Bugfix: memory leak if relative paths were specified using variables
280 in the "root" or "auth_basic_user_file" directives.
281
282 *) Bugfix: the "valid_referers" directive incorrectly executed regular
283 expressions if a "Referer" header started with "https://".
284 Thanks to Liangbin Li.
285
286 *) Bugfix: responses might hang if subrequests were used and an SSL
287 handshake error happened during subrequest processing.
288 Thanks to Aviram Cohen.
289
290 *) Bugfix: in the ngx_http_autoindex_module.
291
292 *) Bugfix: in the ngx_http_spdy_module.
293
294
295 Changes with nginx 1.5.3 30 Jul 2013
296
297 *) Change in internal API: now u->length defaults to -1 if working with
298 backends in unbuffered mode.
299
300 *) Change: now after receiving an incomplete response from a backend
301 server nginx tries to send an available part of the response to a
302 client, and then closes client connection.
58303
59304 *) Bugfix: a segmentation fault might occur in a worker process if the
60305 ngx_http_spdy_module was used with the "client_body_in_file_only"
61306 directive.
62307
63 *) Bugfix: a segmentation fault might occur on start or during
64 reconfiguration if the "try_files" directive was used with an empty
65 parameter.
66
67 *) Bugfix: the $request_time variable did not work in nginx/Windows.
68
69 *) Bugfix: in the ngx_http_auth_basic_module when using "$apr1$"
70 password encryption method.
71 Thanks to Markus Linnala.
72
73 *) Bugfix: in the ngx_http_autoindex_module.
74
75 *) Bugfix: in the mail proxy server.
76
77
78 Changes with nginx 1.4.2 17 Jul 2013
308 *) Bugfix: the "so_keepalive" parameter of the "listen" directive might
309 be handled incorrectly on DragonFlyBSD.
310 Thanks to Sepherosa Ziehau.
311
312 *) Bugfix: in the ngx_http_xslt_filter_module.
313
314 *) Bugfix: in the ngx_http_sub_filter_module.
315
316
317 Changes with nginx 1.5.2 02 Jul 2013
318
319 *) Feature: now several "error_log" directives can be used.
79320
80321 *) Bugfix: the $r->header_in() embedded perl method did not return value
81322 of the "Cookie" and "X-Forwarded-For" request header lines; the bug
82323 had appeared in 1.3.14.
83324
325 *) Bugfix: in the ngx_http_spdy_module.
326 Thanks to Jim Radford.
327
328 *) Bugfix: nginx could not be built on Linux with x32 ABI.
329 Thanks to Serguei Ivantsov.
330
331
332 Changes with nginx 1.5.1 04 Jun 2013
333
334 *) Feature: the "ssi_last_modified", "sub_filter_last_modified", and
335 "xslt_last_modified" directives.
336 Thanks to Alexey Kolpakov.
337
338 *) Feature: the "http_403" parameter of the "proxy_next_upstream",
339 "fastcgi_next_upstream", "scgi_next_upstream", and
340 "uwsgi_next_upstream" directives.
341
342 *) Feature: the "allow" and "deny" directives now support unix domain
343 sockets.
344
84345 *) Bugfix: nginx could not be built with the ngx_mail_ssl_module, but
85346 without ngx_http_ssl_module; the bug had appeared in 1.3.14.
86347
87348 *) Bugfix: in the "proxy_set_body" directive.
349 Thanks to Lanshun Zhou.
350
351 *) Bugfix: in the "lingering_time" directive.
88352 Thanks to Lanshun Zhou.
89353
90354 *) Bugfix: the "fail_timeout" parameter of the "server" directive in the
95359 "ssl_stapling" directive was used.
96360 Thanks to Piotr Sikora.
97361
362 *) Bugfix: in the mail proxy server.
363 Thanks to Filipe Da Silva.
364
98365 *) Bugfix: nginx/Windows might stop accepting connections if several
99366 worker processes were used.
100367
101368
102 Changes with nginx 1.4.1 07 May 2013
369 Changes with nginx 1.5.0 07 May 2013
103370
104371 *) Security: a stack-based buffer overflow might occur in a worker
105372 process while handling a specially crafted request, potentially
60966363 *) Bugfix: the compressed response encrypted by SSL may not transferred
60976364 complete.
60986365
6099 *) Bugfix: the TCP-specific TCP_NODELAY, TCP_NOPSUH, and TCP_CORK
6366 *) Bugfix: the TCP-specific TCP_NODELAY, TCP_NOPUSH, and TCP_CORK
61006367 options, are not used for the unix domain sockets.
61016368
61026369 *) Feature: the rewrite directive supports the arguments rewriting.
00
1 Изменения в nginx 1.4.7 18.03.2014
1 Изменения в nginx 1.6.0 24.04.2014
2
3 *) Стабильная ветка 1.6.x.
4
5
6 Изменения в nginx 1.5.13 08.04.2014
7
8 *) Изменение: улучшена обработка хэш-таблиц; в директивах
9 variables_hash_max_size и types_hash_bucket_size значения по
10 умолчанию изменены на 1024 и 64 соответственно.
11
12 *) Добавление: модуль ngx_http_mp4_module теперь понимает аргумент end.
13
14 *) Добавление: поддержка byte ranges модулем ngx_http_mp4_module и при
15 сохранении ответов в кэш.
16
17 *) Исправление: теперь nginx не пишет в лог сообщения "ngx_slab_alloc()
18 failed: no memory" при использовании разделяемой памяти в
19 ssl_session_cache и в модуле ngx_http_limit_req_module.
20
21 *) Исправление: директива underscores_in_headers не разрешала
22 подчёркивание в первом символе заголовка.
23 Спасибо Piotr Sikora.
24
25 *) Исправление: cache manager мог нагружать процессор при выходе в
26 nginx/Windows.
27
28 *) Исправление: при использовании ssl_session_cache с параметром shared
29 рабочий процесс nginx/Windows завершался аварийно.
30
31 *) Исправление: в модуле ngx_http_spdy_module.
32
33
34 Изменения в nginx 1.5.12 18.03.2014
235
336 *) Безопасность: при обработке специально созданного запроса модулем
437 ngx_http_spdy_module могло происходить переполнение буфера в рабочем
740 Спасибо Lucas Molas из Programa STIC, Fundación Dr. Manuel Sadosky,
841 Buenos Aires, Argentina.
942
43 *) Добавление: параметр proxy_protocol в директивах listen и
44 real_ip_header, переменная $proxy_protocol_addr.
45
1046 *) Исправление: в директиве fastcgi_next_upstream.
1147 Спасибо Lucas Molas.
1248
1349
14 Изменения в nginx 1.4.6 04.03.2014
50 Изменения в nginx 1.5.11 04.03.2014
51
52 *) Безопасность: при обработке специально созданного запроса модулем
53 ngx_http_spdy_module на 32-битных платформах могла повреждаться
54 память рабочего процесса, что потенциально могло приводить к
55 выполнению произвольного кода (CVE-2014-0088); ошибка появилась в
56 1.5.10.
57 Спасибо Lucas Molas из Programa STIC, Fundación Dr. Manuel Sadosky,
58 Buenos Aires, Argentina.
59
60 *) Добавление: переменная $ssl_session_reused.
1561
1662 *) Исправление: директива client_max_body_size могла не работать при
1763 чтении тела запроса с использованием chunked transfer encoding;
2167 *) Исправление: при проксировании WebSocket-соединений в рабочем
2268 процессе мог произойти segmentation fault.
2369
24
25 Изменения в nginx 1.4.5 11.02.2014
70 *) Исправление: в рабочем процессе мог произойти segmentation fault,
71 если использовался модуль ngx_http_spdy_module на 32-битных
72 платформах; ошибка появилась в 1.5.10.
73
74 *) Исправление: значение переменной $upstream_status могло быть
75 неверным, если использовались директивы proxy_cache_use_stale или
76 proxy_cache_revalidate.
77 Спасибо Piotr Sikora.
78
79 *) Исправление: в рабочем процессе мог произойти segmentation fault,
80 если ошибки с кодом 400 с помощью директивы error_page
81 перенаправлялись в именованный location.
82
83 *) Исправление: nginx/Windows не собирался с Visual Studio 2013.
84
85
86 Изменения в nginx 1.5.10 04.02.2014
87
88 *) Добавление: модуль ngx_http_spdy_module теперь использует протокол
89 SPDY 3.1.
90 Спасибо Automattic и MaxCDN за спонсирование разработки.
91
92 *) Добавление: модуль ngx_http_mp4_module теперь пропускает дорожки,
93 имеющие меньшую длину, чем запрошенная перемотка.
94
95 *) Исправление: в рабочем процессе мог произойти segmentation fault,
96 если переменная $ssl_session_id использовалась при логгировании;
97 ошибка появилась в 1.5.9.
98
99 *) Исправление: переменные $date_local и $date_gmt использовали неверный
100 формат вне модуля ngx_http_ssi_filter_module.
101
102 *) Исправление: клиентские соединения могли сразу закрываться, если
103 использовался отложенный accept; ошибка появилась в 1.3.15.
104
105 *) Исправление: сообщения "getsockopt(TCP_FASTOPEN) ... failed"
106 записывались в лог в процессе обновления исполняемого файла на Linux;
107 ошибка появилась в 1.5.8.
108 Спасибо Piotr Sikora.
109
110
111 Изменения в nginx 1.5.9 22.01.2014
112
113 *) Изменение: теперь в заголовке X-Accel-Redirect nginx ожидает
114 закодированный URI.
115
116 *) Добавление: директива ssl_buffer_size.
117
118 *) Добавление: директиву limit_rate теперь можно использовать для
119 ограничения скорости передачи ответов клиенту в SPDY-соединениях.
120
121 *) Добавление: директива spdy_chunk_size.
122
123 *) Добавление: директива ssl_session_tickets.
124 Спасибо Dirkjan Bussink.
26125
27126 *) Исправление: переменная $ssl_session_id содержала всю сессию в
28127 сериализованном виде вместо её идентификатора.
29128 Спасибо Ivan Ristić.
30129
31 *) Исправление: клиентские соединения могли сразу закрываться, если
32 использовался отложенный accept; ошибка появилась в 1.3.15.
130 *) Исправление: nginx неправильно обрабатывал закодированный символ "?"
131 в команде SSI include.
132
133 *) Исправление: модуль ngx_http_dav_module не раскодировал целевой URI
134 при обработке методов COPY и MOVE.
135
136 *) Исправление: resolver не понимал доменные имена с точкой в конце.
137 Спасибо Yichun Zhang.
33138
34139 *) Исправление: при проксировании в логах могли появляться сообщения
35140 "zero size buf in output"; ошибка появилась в 1.3.9.
41146 poll и /dev/poll проксируемые WebSocket-соединения могли зависать
42147 сразу после открытия.
43148
149 *) Исправление: директива xclient почтового прокси-сервера некорректно
150 передавала IPv6-адреса.
151
152
153 Изменения в nginx 1.5.8 17.12.2013
154
155 *) Добавление: теперь resolver поддерживает IPv6.
156
157 *) Добавление: директива listen поддерживает параметр fastopen.
158 Спасибо Mathew Rodley.
159
160 *) Добавление: поддержка SSL в модуле ngx_http_uwsgi_module.
161 Спасибо Roberto De Ioris.
162
163 *) Добавление: скрипты подсветки синтаксиса для vim добавлены в contrib.
164 Спасибо Evan Miller.
165
44166 *) Исправление: при чтении тела запроса с использованием chunked
45167 transfer encoding по SSL-соединению мог произойти таймаут.
46168
47 *) Исправление: утечки памяти в nginx/Windows.
48
49
50 Изменения в nginx 1.4.4 19.11.2013
169 *) Исправление: директива master_process работала неправильно в
170 nginx/Windows.
171
172 *) Исправление: параметр setfib директивы listen мог не работать.
173
174 *) Исправление: в модуле ngx_http_spdy_module.
175
176
177 Изменения в nginx 1.5.7 19.11.2013
51178
52179 *) Безопасность: символ, следующий за незакодированным пробелом в строке
53180 запроса, обрабатывался неправильно (CVE-2013-4547); ошибка появилась
54181 в 0.8.41.
55182 Спасибо Ivan Fratric из Google Security Team.
56183
57
58 Изменения в nginx 1.4.3 08.10.2013
184 *) Изменение: уровень логгирования ошибок auth_basic об отсутствии
185 пароля понижен с уровня error до info.
186
187 *) Добавление: директивы proxy_cache_revalidate,
188 fastcgi_cache_revalidate, scgi_cache_revalidate и
189 uwsgi_cache_revalidate.
190
191 *) Добавление: директива ssl_session_ticket_key.
192 Спасибо Piotr Sikora.
193
194 *) Исправление: директива "add_header Cache-Control ''" добавляла строку
195 заголовка ответа "Cache-Control" с пустым значением.
196
197 *) Исправление: директива "satisfy any" могла вернуть ошибку 403 вместо
198 401 при использовании директив auth_request и auth_basic.
199 Спасибо Jan Marc Hoffmann.
200
201 *) Исправление: параметры accept_filter и deferred директивы listen
202 игнорировались для listen-сокетов, создаваемых в процессе обновления
203 исполняемого файла.
204 Спасибо Piotr Sikora.
205
206 *) Исправление: часть данных, полученных от бэкенда при
207 небуферизированном проксировании, могла не отправляться клиенту
208 сразу, если использовались директивы gzip или gunzip.
209 Спасибо Yichun Zhang.
210
211 *) Исправление: в обработке ошибок в модуле
212 ngx_http_gunzip_filter_module.
213
214 *) Исправление: ответы могли зависать, если использовался модуль
215 ngx_http_spdy_module и директива auth_request.
216
217 *) Исправление: утечки памяти в nginx/Windows.
218
219
220 Изменения в nginx 1.5.6 01.10.2013
221
222 *) Добавление: директива fastcgi_buffering.
223
224 *) Добавление: директивы proxy_ssl_protocols и proxy_ssl_ciphers.
225 Спасибо Piotr Sikora.
226
227 *) Добавление: оптимизация SSL handshake при использовании длинных
228 цепочек сертификатов.
229
230 *) Добавление: почтовый прокси-сервер поддерживает SMTP pipelining.
231
232 *) Исправление: в модуле ngx_http_auth_basic_module при использовании
233 метода шифрования паролей "$apr1$".
234 Спасибо Markus Linnala.
235
236 *) Исправление: на MacOSX, Cygwin и nginx/Windows для обработки запроса
237 мог использоваться неверный location, если для задания location'ов
238 использовались символы разных регистров.
239
240 *) Исправление: автоматическое перенаправление с добавлением
241 завершающего слэша для проксированных location'ов могло не работать.
242
243 *) Исправление: в почтовом прокси-сервере.
244
245 *) Исправление: в модуле ngx_http_spdy_module.
246
247
248 Изменения в nginx 1.5.5 17.09.2013
249
250 *) Изменение: теперь nginx по умолчанию использует HTTP/1.0, если точно
251 определить протокол не удалось.
252
253 *) Добавление: директива disable_symlinks теперь использует O_PATH на
254 Linux.
255
256 *) Добавление: для определения того, что клиент закрыл соединение, при
257 использовании метода epoll теперь используются события EPOLLRDHUP.
258
259 *) Исправление: в директиве valid_referers при использовании параметра
260 server_names.
261
262 *) Исправление: переменная $request_time не работала в nginx/Windows.
263
264 *) Исправление: в директиве image_filter.
265 Спасибо Lanshun Zhou.
266
267 *) Исправление: совместимость с OpenSSL 1.0.1f.
268 Спасибо Piotr Sikora.
269
270
271 Изменения в nginx 1.5.4 27.08.2013
272
273 *) Изменение: MIME-тип для расширения js изменён на
274 "application/javascript"; значение по умолчанию директивы
275 charset_types изменено соответственно.
276
277 *) Изменение: теперь директива image_filter с параметром size возвращает
278 ответ с MIME-типом "application/json".
279
280 *) Добавление: модуль ngx_http_auth_request_module.
281
282 *) Исправление: на старте или во время переконфигурации мог произойти
283 segmentation fault, если использовалась директива try_files с пустым
284 параметром.
285
286 *) Исправление: утечки памяти при использовании в директивах root и
287 auth_basic_user_file относительных путей, заданных с помощью
288 переменных.
289
290 *) Исправление: директива valid_referers неправильно выполняла
291 регулярные выражения, если заголовок Referer начинался с "https://".
292 Спасибо Liangbin Li.
293
294 *) Исправление: ответы могли зависать, если использовались подзапросы и
295 при обработке подзапроса происходила ошибка во время SSL handshake с
296 бэкендом.
297 Спасибо Aviram Cohen.
298
299 *) Исправление: в модуле ngx_http_autoindex_module.
300
301 *) Исправление: в модуле ngx_http_spdy_module.
302
303
304 Изменения в nginx 1.5.3 30.07.2013
305
306 *) Изменение во внутреннем API: теперь при небуферизированной работе с
307 бэкендами u->length по умолчанию устанавливается в -1.
308
309 *) Изменение: теперь при получении неполного ответа от бэкенда nginx
310 отправляет полученную часть ответа, после чего закрывает соединение с
311 клиентом.
59312
60313 *) Исправление: в рабочем процессе мог произойти segmentation fault,
61314 если использовался модуль ngx_http_spdy_module и директива
62315 client_body_in_file_only.
63316
64 *) Исправление: на старте или во время переконфигурации мог произойти
65 segmentation fault, если использовалась директива try_files с пустым
66 параметром.
67
68 *) Исправление: переменная $request_time не работала в nginx/Windows.
69
70 *) Исправление: в модуле ngx_http_auth_basic_module при использовании
71 метода шифрования паролей "$apr1$".
72 Спасибо Markus Linnala.
73
74 *) Исправление: в модуле ngx_http_autoindex_module.
75
76 *) Исправление: в почтовом прокси-сервере.
77
78
79 Изменения в nginx 1.4.2 17.07.2013
317 *) Исправление: параметр so_keepalive директивы listen мог работать
318 некорректно на DragonFlyBSD.
319 Спасибо Sepherosa Ziehau.
320
321 *) Исправление: в модуле ngx_http_xslt_filter_module.
322
323 *) Исправление: в модуле ngx_http_sub_filter_module.
324
325
326 Изменения в nginx 1.5.2 02.07.2013
327
328 *) Добавление: теперь можно использовать несколько директив error_log.
80329
81330 *) Исправление: метод $r->header_in() встроенного перла не возвращал
82331 значения строк "Cookie" и "X-Forwarded-For" из заголовка запроса;
83332 ошибка появилась в 1.3.14.
84333
334 *) Исправление: в модуле ngx_http_spdy_module.
335 Спасибо Jim Radford.
336
337 *) Исправление: nginx не собирался на Linux при использовании x32 ABI.
338 Спасибо Сергею Иванцову.
339
340
341 Изменения в nginx 1.5.1 04.06.2013
342
343 *) Добавление: директивы ssi_last_modified, sub_filter_last_modified и
344 xslt_last_modified.
345 Спасибо Алексею Колпакову.
346
347 *) Добавление: параметр http_403 в директивах proxy_next_upstream,
348 fastcgi_next_upstream, scgi_next_upstream и uwsgi_next_upstream.
349
350 *) Добавление: директивы allow и deny теперь поддерживают unix domain
351 сокеты.
352
85353 *) Исправление: nginx не собирался с модулем ngx_mail_ssl_module, но без
86354 модуля ngx_http_ssl_module; ошибка появилась в 1.3.14.
87355
88356 *) Исправление: в директиве proxy_set_body.
357 Спасибо Lanshun Zhou.
358
359 *) Исправление: в директиве lingering_time.
89360 Спасибо Lanshun Zhou.
90361
91362 *) Исправление: параметр fail_timeout директивы server в блоке upstream
96367 если использовалась директива ssl_stapling.
97368 Спасибо Piotr Sikora.
98369
370 *) Исправление: в почтовом прокси-сервере.
371 Спасибо Filipe Da Silva.
372
99373 *) Исправление: nginx/Windows мог перестать принимать соединения, если
100374 использовалось несколько рабочих процессов.
101375
102376
103 Изменения в nginx 1.4.1 07.05.2013
377 Изменения в nginx 1.5.0 07.05.2013
104378
105379 *) Безопасность: при обработке специально созданного запроса мог
106380 перезаписываться стек рабочего процесса, что могло приводить к
426700 *) Изменение: параметр single директивы keepalive теперь игнорируется.
427701
428702 *) Изменение: сжатие SSL теперь отключено в том числе при использовании
429 OpenSSL cтарее 1.0.0.
703 OpenSSL старее 1.0.0.
430704
431705 *) Добавление: директиву "ip_hash" теперь можно использовать для
432706 балансировки IPv6 клиентов.
27032977 умолчанию; ошибка появилась в 0.7.18.
27042978 Спасибо Максиму Дунину.
27052979
2706 *) Исправление: при проксировании SMPT nginx выдавал сообщение
2980 *) Исправление: при проксировании SMTP nginx выдавал сообщение
27072981 "250 2.0.0 OK" вместо "235 2.0.0 OK"; ошибка появилась в 0.7.22.
27082982 Спасибо Максиму Дунину.
27092983
61896463 *) Исправление: при использовании SSL сжатый ответ мог передаваться не
61906464 до конца.
61916465
6192 *) Исправление: опции TCP_NODELAY, TCP_NOPSUH и TCP_CORK, специфичные
6466 *) Исправление: опции TCP_NODELAY, TCP_NOPUSH и TCP_CORK, специфичные
61936467 для TCP сокетов, не используются для unix domain сокетов.
61946468
61956469 *) Добавление: директива rewrite поддерживает перезаписывание
62536527 *) Изменение: если в URI встречался символ %3F, то он считался началом
62546528 строки аргументов.
62556529
6256 *) Добавление: поддержка unix domain сoкетов в модуле
6530 *) Добавление: поддержка unix domain сокетов в модуле
62576531 ngx_http_proxy_module.
62586532
62596533 *) Добавление: директивы ssl_engine и ssl_ciphers.
44 # clang
55
66
7 NGX_CLANG_VER=`$CC -v 2>&1 | grep 'clang version' 2>&1 \
8 | sed -e 's/^.*clang version \(.*\)/\1/'`
7 NGX_CLANG_VER=`$CC -v 2>&1 | grep '\(clang\|LLVM\) version' 2>&1 \
8 | sed -e 's/^.* version \(.*\)/\1/'`
99
1010 echo " + clang version: $NGX_CLANG_VER"
1111
8181 # warnings
8282
8383 CFLAGS="$CFLAGS $NGX_CLANG_OPT -Wall -Wextra -Wpointer-arith"
84 CFLAGS="$CFLAGS -Wconditional-uninitialized"
8485 #CFLAGS="$CFLAGS -Wmissing-prototypes"
8586
8687 # we have a lot of unused function arguments
8788 CFLAGS="$CFLAGS -Wno-unused-parameter"
8889
8990 # stop on warning
90 #CFLAGS="$CFLAGS -Werror"
91 CFLAGS="$CFLAGS -Werror"
9192
9293 # debug
9394 CFLAGS="$CFLAGS -g"
4040 # Compaq C V6.5-207
4141
4242 ngx_include_opt="-I"
43 ;;
44
45 sunc)
46
47 case "$NGX_MACHINE" in
48
49 i86pc)
50 NGX_AUX=" src/os/unix/ngx_sunpro_x86.il"
51 ;;
52
53 sun4u | sun4v)
54 NGX_AUX=" src/os/unix/ngx_sunpro_sparc64.il"
55 ;;
56
57 esac
58
59 case $CPU in
60
61 amd64)
62 NGX_AUX=" src/os/unix/ngx_sunpro_amd64.il"
63 ;;
64
65 esac
4366 ;;
4467
4568 esac
105105
106106 # precompiled headers
107107 CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
108 CORE_LINK="$CORE_LINK $NGX_OBJS/ngx_pch.obj"
108109 NGX_PCH="$NGX_OBJS/ngx_config.pch"
109110 NGX_BUILD_PCH="-Ycngx_config.h -Fp$NGX_OBJS/ngx_config.pch"
110111 NGX_USE_PCH="-Yungx_config.h -Fp$NGX_OBJS/ngx_config.pch"
6666 NGX_CC_NAME=gcc
6767 echo " + using GNU C compiler"
6868
69 elif `$CC -v 2>&1 | grep 'clang version' >/dev/null 2>&1`; then
69 elif `$CC -v 2>&1 | grep '\(clang\|LLVM\) version' >/dev/null 2>&1`; then
7070 NGX_CC_NAME=clang
7171 echo " + using Clang C compiler"
7272
6464
6565
6666 # the precompiled headers
67 CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
68 NGX_PCH="$NGX_OBJS/ngx_config.pch"
69 NGX_BUILD_PCH="-fhq=$NGX_OBJS/ngx_config.pch"
70 NGX_USE_PCH="-fh=$NGX_OBJS/ngx_config.pch"
67 #CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
68 #NGX_PCH="$NGX_OBJS/ngx_config.pch"
69 #NGX_BUILD_PCH="-fhq=$NGX_OBJS/ngx_config.pch"
70 #NGX_USE_PCH="-fh=$NGX_OBJS/ngx_config.pch"
7171
7272
7373 # the link flags, built target is NT GUI mode application
2929 ngx_sunc_ver=`$NGX_AUTOTEST`
3030 fi
3131
32 rm $NGX_AUTOTEST*
32 rm -rf $NGX_AUTOTEST*
3333
3434 # 1424 == 0x590, Sun Studio 12
3535
3333 echo " big endian"
3434 fi
3535
36 rm $NGX_AUTOTEST*
36 rm -rf $NGX_AUTOTEST*
3737
3838 else
39 rm $NGX_AUTOTEST*
39 rm -rf $NGX_AUTOTEST*
4040
4141 echo
4242 echo "$0: error: cannot detect system byte ordering"
119119 echo "----------" >> $NGX_AUTOCONF_ERR
120120 fi
121121
122 rm $NGX_AUTOTEST*
122 rm -rf $NGX_AUTOTEST*
5757 echo "----------" >> $NGX_AUTOCONF_ERR
5858 fi
5959
60 rm $NGX_AUTOTEST*
60 rm -rf $NGX_AUTOTEST*
88 cd $NGX_LIBATOMIC && \$(MAKE)
99
1010 $NGX_LIBATOMIC/Makefile: $NGX_MAKEFILE
11 cd $NGX_LIBATOMIC && ./configure
11 cd $NGX_LIBATOMIC \\
12 && if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
13 && ./configure
1214
1315 END
3232 CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
3333 CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a"
3434 CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
35
36 if [ "$NGX_PLATFORM" = win32 ]; then
37 CORE_LIBS="$CORE_LIBS -lgdi32 -lcrypt32 -lws2_32"
38 fi
3539 ;;
3640 esac
3741
5454
5555 $OPENSSL/.openssl/include/openssl/ssl.h: $NGX_MAKEFILE
5656 cd $OPENSSL \\
57 && \$(MAKE) clean \\
57 && if [ -f Makefile ]; then \$(MAKE) clean; fi \\
5858 && ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\
5959 && \$(MAKE) \\
6060 && \$(MAKE) install LIBDIR=lib
7272
7373 *)
7474 have=NGX_PCRE . auto/have
75
76 if [ "$NGX_PLATFORM" = win32 ]; then
77 have=PCRE_STATIC . auto/have
78 fi
79
7580 CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
7681 LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a"
7782 CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a"
2222 ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
2323 ;;
2424
25 *)
26 ngx_makefile=
27 ;;
28
2529 esac
2630
2731
28 case "$NGX_PLATFORM" in
32 if [ -n "$ngx_makefile" ]; then
2933
30 win32)
34 cat << END >> $NGX_MAKEFILE
3135
32 cat << END >> $NGX_MAKEFILE
33
34 `echo "$PCRE/pcre.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
36 `echo "$PCRE/pcre.lib: $PCRE/pcre.h $NGX_MAKEFILE" \
37 | sed -e "s/\//$ngx_regex_dirsep/g"`
3538 \$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre $ngx_opt
3639
3740 `echo "$PCRE/pcre.h:" | sed -e "s/\//$ngx_regex_dirsep/g"`
3942
4043 END
4144
42 ;;
45 else
4346
44 *)
45 cat << END >> $NGX_MAKEFILE
47 cat << END >> $NGX_MAKEFILE
4648
4749 $PCRE/pcre.h: $PCRE/Makefile
4850
5860
5961 END
6062
61 ;;
62
63 esac
63 fi
33
44
55 CFLAGS = -q -O2 -tWM -w-8004 $(CPU_OPT)
6 PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
6 PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 \
7 -DSUPPORT_PCRE8 -DHAVE_MEMMOVE
78
89
910 pcre.lib:
1112
1213 bcc32 -c $(CFLAGS) -I. $(PCREFLAGS) pcre_*.c
1314
14 > pcre.lst
15 for %n in (*.obj) do @echo +%n & >> pcre.lst
15 copy /y nul pcre.lst
16 for %n in (*.obj) do @echo +%n ^^& >> pcre.lst
1617 echo + >> pcre.lst
1718
1819 tlib pcre.lib @pcre.lst
33
44
55 CFLAGS = -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT)
6 PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
6 PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 \
7 -DSUPPORT_PCRE8 -DHAVE_MEMMOVE
78
89
910 pcre.lib:
33
44
55 CFLAGS = -c -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT)
6 PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
6 PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 &
7 -DSUPPORT_PCRE8 -DHAVE_MEMMOVE
78
89
910 pcre.lib:
1717
1818
1919 $NGX_OBJS/src/http/modules/perl/Makefile: \\
20 $NGX_AUTO_CONFIG_H \\
2021 src/core/nginx.h \\
2122 src/http/modules/perl/Makefile.PL \\
2223 src/http/modules/perl/nginx.pm \\
3636 echo " not found"
3737 fi
3838
39 rm $NGX_AUTOTEST*
39 rm -rf $NGX_AUTOTEST*
2323 ngx_zlib=`echo \-DZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"`
2424 ;;
2525
26 *)
27 ngx_makefile=
28 ;;
29
2630 esac
2731
2832
3236 case "$NGX_PLATFORM" in
3337
3438 win32)
35 cat << END >> $NGX_MAKEFILE
39
40 if [ -n "$ngx_makefile" ]; then
41 cat << END >> $NGX_MAKEFILE
3642
3743 `echo "$ZLIB/zlib.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
3844 \$(MAKE) -f auto/lib/zlib/$ngx_makefile $ngx_opt $ngx_zlib
3945
4046 END
47
48 else
49
50 cat << END >> $NGX_MAKEFILE
51
52 $ZLIB/libz.a: $NGX_MAKEFILE
53 cd $ZLIB \\
54 && \$(MAKE) distclean \\
55 && \$(MAKE) -f win32/Makefile.gcc \\
56 CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\
57 libz.a
58
59 END
60
61 fi
4162
4263 done=YES
4364 ;;
4141
4242 if [ $NGX_TEST_BUILD_EPOLL = YES ]; then
4343 have=NGX_HAVE_EPOLL . auto/have
44 have=NGX_HAVE_EPOLLRDHUP . auto/have
4445 have=NGX_HAVE_EVENTFD . auto/have
4546 have=NGX_TEST_BUILD_EPOLL . auto/have
4647 EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
219220 HTTP_SRCS="$HTTP_SRCS $HTTP_RANDOM_INDEX_SRCS"
220221 fi
221222
223 if [ $HTTP_AUTH_REQUEST = YES ]; then
224 HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_REQUEST_MODULE"
225 HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_REQUEST_SRCS"
226 fi
227
222228 if [ $HTTP_AUTH_BASIC = YES ]; then
223229 USE_MD5=YES
224230 USE_SHA1=YES
476482
477483 modules="$modules $MAIL_PROXY_MODULE"
478484 MAIL_SRCS="$MAIL_SRCS $MAIL_PROXY_SRCS"
485
486 NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(MAIL_DEPS)"
479487 fi
480488
481489
7070 HTTP_DAV=NO
7171 HTTP_ACCESS=YES
7272 HTTP_AUTH_BASIC=YES
73 HTTP_AUTH_REQUEST=NO
7374 HTTP_USERID=YES
7475 HTTP_AUTOINDEX=YES
7576 HTTP_RANDOM_INDEX=NO
214215 --with-http_mp4_module) HTTP_MP4=YES ;;
215216 --with-http_gunzip_module) HTTP_GUNZIP=YES ;;
216217 --with-http_gzip_static_module) HTTP_GZIP_STATIC=YES ;;
218 --with-http_auth_request_module) HTTP_AUTH_REQUEST=YES ;;
217219 --with-http_random_index_module) HTTP_RANDOM_INDEX=YES ;;
218220 --with-http_secure_link_module) HTTP_SECURE_LINK=YES ;;
219221 --with-http_degradation_module) HTTP_DEGRADATION=YES ;;
362364 --with-http_mp4_module enable ngx_http_mp4_module
363365 --with-http_gunzip_module enable ngx_http_gunzip_module
364366 --with-http_gzip_static_module enable ngx_http_gzip_static_module
367 --with-http_auth_request_module enable ngx_http_auth_request_module
365368 --with-http_random_index_module enable ngx_http_random_index_module
366369 --with-http_secure_link_module enable ngx_http_secure_link_module
367370 --with-http_degradation_module enable ngx_http_degradation_module
111111 ngx_feature_path=
112112 ngx_feature_libs=
113113 ngx_feature_test="int32_t lock, n;
114 n = OSAtomicCompareAndSwap32Barrier(0, 1, lock)"
114 n = OSAtomicCompareAndSwap32Barrier(0, 1, &lock)"
115115 . auto/feature
6464 CORE_SRCS="$CORE_SRCS $EPOLL_SRCS"
6565 EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
6666 EVENT_FOUND=YES
67
68
69 # EPOLLRDHUP appeared in Linux 2.6.17, glibc 2.8
70
71 ngx_feature="EPOLLRDHUP"
72 ngx_feature_name="NGX_HAVE_EPOLLRDHUP"
73 ngx_feature_run=no
74 ngx_feature_incs="#include <sys/epoll.h>"
75 ngx_feature_path=
76 ngx_feature_libs=
77 ngx_feature_test="int efd = 0, fd = 0;
78 struct epoll_event ee;
79 ee.events = EPOLLIN|EPOLLRDHUP|EPOLLET;
80 ee.data.ptr = NULL;
81 epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
82 . auto/feature
6783 fi
84
85
86 # O_PATH and AT_EMPTY_PATH were introduced in 2.6.39, glibc 2.14
87
88 ngx_feature="O_PATH"
89 ngx_feature_name="NGX_HAVE_O_PATH"
90 ngx_feature_run=no
91 ngx_feature_incs="#include <sys/types.h>
92 #include <sys/stat.h>
93 #include <fcntl.h>"
94 ngx_feature_path=
95 ngx_feature_libs=
96 ngx_feature_test="int fd; struct stat sb;
97 fd = openat(AT_FDCWD, \".\", O_PATH|O_DIRECTORY|O_NOFOLLOW);
98 if (fstatat(fd, \"\", &sb, AT_EMPTY_PATH) != 0) return 1"
99 . auto/feature
68100
69101
70102 # sendfile()
88 CORE_DEPS="$WIN32_DEPS"
99 CORE_SRCS="$WIN32_SRCS $IOCP_SRCS"
1010 OS_CONFIG="$WIN32_CONFIG"
11 CORE_LIBS="$CORE_LIBS advapi32.lib ws2_32.lib"
1211 NGX_ICONS="$NGX_WIN32_ICONS"
1312 SELECT_SRCS=$WIN32_SELECT_SRCS
13
14 case "$NGX_CC_NAME" in
15
16 gcc)
17 CORE_LIBS="$CORE_LIBS -ladvapi32 -lws2_32"
18 ;;
19
20 *)
21 CORE_LIBS="$CORE_LIBS advapi32.lib ws2_32.lib"
22 ;;
23
24 esac
1425
1526 EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE"
1627 EVENT_FOUND=YES
3535 src/core/ngx_conf_file.h \
3636 src/core/ngx_resolver.h \
3737 src/core/ngx_open_file_cache.h \
38 src/core/ngx_crypt.h"
38 src/core/ngx_crypt.h \
39 src/core/ngx_proxy_protocol.h"
3940
4041
4142 CORE_SRCS="src/core/nginx.c \
6667 src/core/ngx_conf_file.c \
6768 src/core/ngx_resolver.c \
6869 src/core/ngx_open_file_cache.c \
69 src/core/ngx_crypt.c"
70 src/core/ngx_crypt.c \
71 src/core/ngx_proxy_protocol.c"
7072
7173
7274 REGEX_MODULE=ngx_regex_module
385387 HTTP_AUTH_BASIC_SRCS=src/http/modules/ngx_http_auth_basic_module.c
386388
387389
390 HTTP_AUTH_REQUEST_MODULE=ngx_http_auth_request_module
391 HTTP_AUTH_REQUEST_SRCS=src/http/modules/ngx_http_auth_request_module.c
392
393
388394 HTTP_AUTOINDEX_MODULE=ngx_http_autoindex_module
389395 HTTP_AUTOINDEX_SRCS=src/http/modules/ngx_http_autoindex_module.c
390396
4444 fi
4545
4646
47 rm -f $NGX_AUTOTEST
47 rm -rf $NGX_AUTOTEST*
4848
4949
5050 case $ngx_size in
4848 fi
4949 fi
5050
51 rm -f $NGX_AUTOTEST
51 rm -rf $NGX_AUTOTEST*
5252
5353 if [ $ngx_found = no ]; then
5454 echo $ngx_n " $ngx_try not found$ngx_c"
3232 echo $ngx_n " uintptr_t not found" $ngx_c
3333 fi
3434
35 rm $NGX_AUTOTEST*
35 rm -rf $NGX_AUTOTEST*
3636
3737
3838 if [ $found = no ]; then
329329 . auto/feature
330330
331331
332 ngx_feature="TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT"
332 ngx_feature="TCP_KEEPIDLE"
333333 ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
334334 ngx_feature_run=no
335335 ngx_feature_incs="#include <sys/socket.h>
340340 ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
341341 setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
342342 setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
343 . auto/feature
344
345
346 ngx_feature="TCP_FASTOPEN"
347 ngx_feature_name="NGX_HAVE_TCP_FASTOPEN"
348 ngx_feature_run=no
349 ngx_feature_incs="#include <sys/socket.h>
350 #include <netinet/in.h>
351 #include <netinet/tcp.h>"
352 ngx_feature_path=
353 ngx_feature_libs=
354 ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_FASTOPEN, NULL, 0)"
343355 . auto/feature
344356
345357
44 text/xml xml;
55 image/gif gif;
66 image/jpeg jpeg jpg;
7 application/x-javascript js;
7 application/javascript js;
88 application/atom+xml atom;
99 application/rss+xml rss;
1010
2323 image/svg+xml svg svgz;
2424 image/webp webp;
2525
26 application/font-woff woff;
2627 application/java-archive jar war ear;
28 application/json json;
2729 application/mac-binhex40 hqx;
2830 application/msword doc;
2931 application/pdf pdf;
3032 application/postscript ps eps ai;
3133 application/rtf rtf;
34 application/vnd.apple.mpegurl m3u8;
3235 application/vnd.ms-excel xls;
36 application/vnd.ms-fontobject eot;
3337 application/vnd.ms-powerpoint ppt;
3438 application/vnd.wap.wmlc wmlc;
3539 application/vnd.google-earth.kml+xml kml;
5054 application/x-x509-ca-cert der pem crt;
5155 application/x-xpinstall xpi;
5256 application/xhtml+xml xhtml;
57 application/xspf+xml xspf;
5358 application/zip zip;
5459
5560 application/octet-stream bin exe dll;
5661 application/octet-stream deb;
5762 application/octet-stream dmg;
58 application/octet-stream eot;
5963 application/octet-stream iso img;
6064 application/octet-stream msi msp msm;
65
66 application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
67 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
68 application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
6169
6270 audio/midi mid midi kar;
6371 audio/mpeg mp3;
6674 audio/x-realaudio ra;
6775
6876 video/3gpp 3gpp 3gp;
77 video/mp2t ts;
6978 video/mp4 mp4;
7079 video/mpeg mpeg mpg;
7180 video/quicktime mov;
9595 # HTTPS server
9696 #
9797 #server {
98 # listen 443;
98 # listen 443 ssl;
9999 # server_name localhost;
100100
101 # ssl on;
102101 # ssl_certificate cert.pem;
103102 # ssl_certificate_key cert.key;
104103
104 # ssl_session_cache shared:SSL:1m;
105105 # ssl_session_timeout 5m;
106106
107 # ssl_protocols SSLv2 SSLv3 TLSv1;
108107 # ssl_ciphers HIGH:!aNULL:!MD5;
109 # ssl_prefer_server_ciphers on;
108 # ssl_prefer_server_ciphers on;
110109
111110 # location / {
112111 # root html;
1212 configuration file format.
1313 Two generated full maps for windows-1251 and koi8-r.
1414
15
16 vim by Evan Miller
17
18 Syntax highlighting of nginx configuration for vim, to be
19 placed into ~/.vim/.
20
0 au BufRead,BufNewFile *.nginx set ft=nginx
1 au BufRead,BufNewFile */etc/nginx/* set ft=nginx
2 au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx
3 au BufRead,BufNewFile nginx.conf set ft=nginx
0 if exists("b:did_indent")
1 finish
2 endif
3 let b:did_indent = 1
4
5 setlocal indentexpr=
6
7 " cindent actually works for nginx' simple file structure
8 setlocal cindent
9 " Just make sure that the comments are not reset as defs would be.
10 setlocal cinkeys-=0#
0 " Vim syntax file
1 " Language: nginx.conf
2
3 if exists("b:current_syntax")
4 finish
5 end
6
7 setlocal iskeyword+=.
8 setlocal iskeyword+=/
9 setlocal iskeyword+=:
10
11 syn match ngxVariable '\$\(\w\+\|{\w\+}\)'
12 syn match ngxVariableBlock '\$\(\w\+\|{\w\+}\)' contained
13 syn match ngxVariableString '\$\(\w\+\|{\w\+}\)' contained
14 syn region ngxBlock start=+^+ end=+{+ skip=+\${+ contains=ngxComment,ngxDirectiveBlock,ngxVariableBlock,ngxString oneline
15 syn region ngxString start=+\z(["']\)+ end=+\z1+ skip=+\\\\\|\\\z1+ contains=ngxVariableString
16 syn match ngxComment ' *#.*$'
17
18 syn keyword ngxBoolean on
19 syn keyword ngxBoolean off
20
21 syn keyword ngxDirectiveBlock http contained
22 syn keyword ngxDirectiveBlock mail contained
23 syn keyword ngxDirectiveBlock events contained
24 syn keyword ngxDirectiveBlock server contained
25 syn keyword ngxDirectiveBlock types contained
26 syn keyword ngxDirectiveBlock location contained
27 syn keyword ngxDirectiveBlock upstream contained
28 syn keyword ngxDirectiveBlock charset_map contained
29 syn keyword ngxDirectiveBlock limit_except contained
30 syn keyword ngxDirectiveBlock if contained
31 syn keyword ngxDirectiveBlock geo contained
32 syn keyword ngxDirectiveBlock map contained
33
34 syn keyword ngxDirectiveImportant include
35 syn keyword ngxDirectiveImportant root
36 syn keyword ngxDirectiveImportant server
37 syn keyword ngxDirectiveImportant server_name
38 syn keyword ngxDirectiveImportant listen
39 syn keyword ngxDirectiveImportant internal
40 syn keyword ngxDirectiveImportant proxy_pass
41 syn keyword ngxDirectiveImportant memcached_pass
42 syn keyword ngxDirectiveImportant fastcgi_pass
43 syn keyword ngxDirectiveImportant try_files
44
45 syn keyword ngxDirectiveControl break
46 syn keyword ngxDirectiveControl return
47 syn keyword ngxDirectiveControl rewrite
48 syn keyword ngxDirectiveControl set
49
50 syn keyword ngxDirectiveError error_page
51 syn keyword ngxDirectiveError post_action
52
53 syn keyword ngxDirectiveDeprecated connections
54 syn keyword ngxDirectiveDeprecated imap
55 syn keyword ngxDirectiveDeprecated open_file_cache_retest
56 syn keyword ngxDirectiveDeprecated optimize_server_names
57 syn keyword ngxDirectiveDeprecated satisfy_any
58
59 syn keyword ngxDirective accept_mutex
60 syn keyword ngxDirective accept_mutex_delay
61 syn keyword ngxDirective access_log
62 syn keyword ngxDirective add_after_body
63 syn keyword ngxDirective add_before_body
64 syn keyword ngxDirective add_header
65 syn keyword ngxDirective addition_types
66 syn keyword ngxDirective aio
67 syn keyword ngxDirective alias
68 syn keyword ngxDirective allow
69 syn keyword ngxDirective ancient_browser
70 syn keyword ngxDirective ancient_browser_value
71 syn keyword ngxDirective auth_basic
72 syn keyword ngxDirective auth_basic_user_file
73 syn keyword ngxDirective auth_http
74 syn keyword ngxDirective auth_http_header
75 syn keyword ngxDirective auth_http_timeout
76 syn keyword ngxDirective autoindex
77 syn keyword ngxDirective autoindex_exact_size
78 syn keyword ngxDirective autoindex_localtime
79 syn keyword ngxDirective charset
80 syn keyword ngxDirective charset_types
81 syn keyword ngxDirective client_body_buffer_size
82 syn keyword ngxDirective client_body_in_file_only
83 syn keyword ngxDirective client_body_in_single_buffer
84 syn keyword ngxDirective client_body_temp_path
85 syn keyword ngxDirective client_body_timeout
86 syn keyword ngxDirective client_header_buffer_size
87 syn keyword ngxDirective client_header_timeout
88 syn keyword ngxDirective client_max_body_size
89 syn keyword ngxDirective connection_pool_size
90 syn keyword ngxDirective create_full_put_path
91 syn keyword ngxDirective daemon
92 syn keyword ngxDirective dav_access
93 syn keyword ngxDirective dav_methods
94 syn keyword ngxDirective debug_connection
95 syn keyword ngxDirective debug_points
96 syn keyword ngxDirective default_type
97 syn keyword ngxDirective degradation
98 syn keyword ngxDirective degrade
99 syn keyword ngxDirective deny
100 syn keyword ngxDirective devpoll_changes
101 syn keyword ngxDirective devpoll_events
102 syn keyword ngxDirective directio
103 syn keyword ngxDirective directio_alignment
104 syn keyword ngxDirective empty_gif
105 syn keyword ngxDirective env
106 syn keyword ngxDirective epoll_events
107 syn keyword ngxDirective error_log
108 syn keyword ngxDirective eventport_events
109 syn keyword ngxDirective expires
110 syn keyword ngxDirective fastcgi_bind
111 syn keyword ngxDirective fastcgi_buffer_size
112 syn keyword ngxDirective fastcgi_buffers
113 syn keyword ngxDirective fastcgi_busy_buffers_size
114 syn keyword ngxDirective fastcgi_cache
115 syn keyword ngxDirective fastcgi_cache_key
116 syn keyword ngxDirective fastcgi_cache_methods
117 syn keyword ngxDirective fastcgi_cache_min_uses
118 syn keyword ngxDirective fastcgi_cache_path
119 syn keyword ngxDirective fastcgi_cache_use_stale
120 syn keyword ngxDirective fastcgi_cache_valid
121 syn keyword ngxDirective fastcgi_catch_stderr
122 syn keyword ngxDirective fastcgi_connect_timeout
123 syn keyword ngxDirective fastcgi_hide_header
124 syn keyword ngxDirective fastcgi_ignore_client_abort
125 syn keyword ngxDirective fastcgi_ignore_headers
126 syn keyword ngxDirective fastcgi_index
127 syn keyword ngxDirective fastcgi_intercept_errors
128 syn keyword ngxDirective fastcgi_max_temp_file_size
129 syn keyword ngxDirective fastcgi_next_upstream
130 syn keyword ngxDirective fastcgi_param
131 syn keyword ngxDirective fastcgi_pass_header
132 syn keyword ngxDirective fastcgi_pass_request_body
133 syn keyword ngxDirective fastcgi_pass_request_headers
134 syn keyword ngxDirective fastcgi_read_timeout
135 syn keyword ngxDirective fastcgi_send_lowat
136 syn keyword ngxDirective fastcgi_send_timeout
137 syn keyword ngxDirective fastcgi_split_path_info
138 syn keyword ngxDirective fastcgi_store
139 syn keyword ngxDirective fastcgi_store_access
140 syn keyword ngxDirective fastcgi_temp_file_write_size
141 syn keyword ngxDirective fastcgi_temp_path
142 syn keyword ngxDirective fastcgi_upstream_fail_timeout
143 syn keyword ngxDirective fastcgi_upstream_max_fails
144 syn keyword ngxDirective flv
145 syn keyword ngxDirective geoip_city
146 syn keyword ngxDirective geoip_country
147 syn keyword ngxDirective google_perftools_profiles
148 syn keyword ngxDirective gzip
149 syn keyword ngxDirective gzip_buffers
150 syn keyword ngxDirective gzip_comp_level
151 syn keyword ngxDirective gzip_disable
152 syn keyword ngxDirective gzip_hash
153 syn keyword ngxDirective gzip_http_version
154 syn keyword ngxDirective gzip_min_length
155 syn keyword ngxDirective gzip_no_buffer
156 syn keyword ngxDirective gzip_proxied
157 syn keyword ngxDirective gzip_static
158 syn keyword ngxDirective gzip_types
159 syn keyword ngxDirective gzip_vary
160 syn keyword ngxDirective gzip_window
161 syn keyword ngxDirective if_modified_since
162 syn keyword ngxDirective ignore_invalid_headers
163 syn keyword ngxDirective image_filter
164 syn keyword ngxDirective image_filter_buffer
165 syn keyword ngxDirective image_filter_jpeg_quality
166 syn keyword ngxDirective image_filter_transparency
167 syn keyword ngxDirective imap_auth
168 syn keyword ngxDirective imap_capabilities
169 syn keyword ngxDirective imap_client_buffer
170 syn keyword ngxDirective index
171 syn keyword ngxDirective ip_hash
172 syn keyword ngxDirective keepalive_requests
173 syn keyword ngxDirective keepalive_timeout
174 syn keyword ngxDirective kqueue_changes
175 syn keyword ngxDirective kqueue_events
176 syn keyword ngxDirective large_client_header_buffers
177 syn keyword ngxDirective limit_conn
178 syn keyword ngxDirective limit_conn_log_level
179 syn keyword ngxDirective limit_rate
180 syn keyword ngxDirective limit_rate_after
181 syn keyword ngxDirective limit_req
182 syn keyword ngxDirective limit_req_log_level
183 syn keyword ngxDirective limit_req_zone
184 syn keyword ngxDirective limit_zone
185 syn keyword ngxDirective lingering_time
186 syn keyword ngxDirective lingering_timeout
187 syn keyword ngxDirective lock_file
188 syn keyword ngxDirective log_format
189 syn keyword ngxDirective log_not_found
190 syn keyword ngxDirective log_subrequest
191 syn keyword ngxDirective map_hash_bucket_size
192 syn keyword ngxDirective map_hash_max_size
193 syn keyword ngxDirective master_process
194 syn keyword ngxDirective memcached_bind
195 syn keyword ngxDirective memcached_buffer_size
196 syn keyword ngxDirective memcached_connect_timeout
197 syn keyword ngxDirective memcached_next_upstream
198 syn keyword ngxDirective memcached_read_timeout
199 syn keyword ngxDirective memcached_send_timeout
200 syn keyword ngxDirective memcached_upstream_fail_timeout
201 syn keyword ngxDirective memcached_upstream_max_fails
202 syn keyword ngxDirective merge_slashes
203 syn keyword ngxDirective min_delete_depth
204 syn keyword ngxDirective modern_browser
205 syn keyword ngxDirective modern_browser_value
206 syn keyword ngxDirective msie_padding
207 syn keyword ngxDirective msie_refresh
208 syn keyword ngxDirective multi_accept
209 syn keyword ngxDirective open_file_cache
210 syn keyword ngxDirective open_file_cache_errors
211 syn keyword ngxDirective open_file_cache_events
212 syn keyword ngxDirective open_file_cache_min_uses
213 syn keyword ngxDirective open_file_cache_valid
214 syn keyword ngxDirective open_log_file_cache
215 syn keyword ngxDirective output_buffers
216 syn keyword ngxDirective override_charset
217 syn keyword ngxDirective perl
218 syn keyword ngxDirective perl_modules
219 syn keyword ngxDirective perl_require
220 syn keyword ngxDirective perl_set
221 syn keyword ngxDirective pid
222 syn keyword ngxDirective pop3_auth
223 syn keyword ngxDirective pop3_capabilities
224 syn keyword ngxDirective port_in_redirect
225 syn keyword ngxDirective postpone_gzipping
226 syn keyword ngxDirective postpone_output
227 syn keyword ngxDirective protocol
228 syn keyword ngxDirective proxy
229 syn keyword ngxDirective proxy_bind
230 syn keyword ngxDirective proxy_buffer
231 syn keyword ngxDirective proxy_buffer_size
232 syn keyword ngxDirective proxy_buffering
233 syn keyword ngxDirective proxy_buffers
234 syn keyword ngxDirective proxy_busy_buffers_size
235 syn keyword ngxDirective proxy_cache
236 syn keyword ngxDirective proxy_cache_key
237 syn keyword ngxDirective proxy_cache_methods
238 syn keyword ngxDirective proxy_cache_min_uses
239 syn keyword ngxDirective proxy_cache_path
240 syn keyword ngxDirective proxy_cache_use_stale
241 syn keyword ngxDirective proxy_cache_valid
242 syn keyword ngxDirective proxy_connect_timeout
243 syn keyword ngxDirective proxy_headers_hash_bucket_size
244 syn keyword ngxDirective proxy_headers_hash_max_size
245 syn keyword ngxDirective proxy_hide_header
246 syn keyword ngxDirective proxy_ignore_client_abort
247 syn keyword ngxDirective proxy_ignore_headers
248 syn keyword ngxDirective proxy_intercept_errors
249 syn keyword ngxDirective proxy_max_temp_file_size
250 syn keyword ngxDirective proxy_method
251 syn keyword ngxDirective proxy_next_upstream
252 syn keyword ngxDirective proxy_pass_error_message
253 syn keyword ngxDirective proxy_pass_header
254 syn keyword ngxDirective proxy_pass_request_body
255 syn keyword ngxDirective proxy_pass_request_headers
256 syn keyword ngxDirective proxy_read_timeout
257 syn keyword ngxDirective proxy_redirect
258 syn keyword ngxDirective proxy_send_lowat
259 syn keyword ngxDirective proxy_send_timeout
260 syn keyword ngxDirective proxy_set_body
261 syn keyword ngxDirective proxy_set_header
262 syn keyword ngxDirective proxy_ssl_session_reuse
263 syn keyword ngxDirective proxy_store
264 syn keyword ngxDirective proxy_store_access
265 syn keyword ngxDirective proxy_temp_file_write_size
266 syn keyword ngxDirective proxy_temp_path
267 syn keyword ngxDirective proxy_timeout
268 syn keyword ngxDirective proxy_upstream_fail_timeout
269 syn keyword ngxDirective proxy_upstream_max_fails
270 syn keyword ngxDirective random_index
271 syn keyword ngxDirective read_ahead
272 syn keyword ngxDirective real_ip_header
273 syn keyword ngxDirective recursive_error_pages
274 syn keyword ngxDirective request_pool_size
275 syn keyword ngxDirective reset_timedout_connection
276 syn keyword ngxDirective resolver
277 syn keyword ngxDirective resolver_timeout
278 syn keyword ngxDirective rewrite_log
279 syn keyword ngxDirective rtsig_overflow_events
280 syn keyword ngxDirective rtsig_overflow_test
281 syn keyword ngxDirective rtsig_overflow_threshold
282 syn keyword ngxDirective rtsig_signo
283 syn keyword ngxDirective satisfy
284 syn keyword ngxDirective secure_link_secret
285 syn keyword ngxDirective send_lowat
286 syn keyword ngxDirective send_timeout
287 syn keyword ngxDirective sendfile
288 syn keyword ngxDirective sendfile_max_chunk
289 syn keyword ngxDirective server_name_in_redirect
290 syn keyword ngxDirective server_names_hash_bucket_size
291 syn keyword ngxDirective server_names_hash_max_size
292 syn keyword ngxDirective server_tokens
293 syn keyword ngxDirective set_real_ip_from
294 syn keyword ngxDirective smtp_auth
295 syn keyword ngxDirective smtp_capabilities
296 syn keyword ngxDirective smtp_client_buffer
297 syn keyword ngxDirective smtp_greeting_delay
298 syn keyword ngxDirective so_keepalive
299 syn keyword ngxDirective source_charset
300 syn keyword ngxDirective ssi
301 syn keyword ngxDirective ssi_ignore_recycled_buffers
302 syn keyword ngxDirective ssi_min_file_chunk
303 syn keyword ngxDirective ssi_silent_errors
304 syn keyword ngxDirective ssi_types
305 syn keyword ngxDirective ssi_value_length
306 syn keyword ngxDirective ssl
307 syn keyword ngxDirective ssl_certificate
308 syn keyword ngxDirective ssl_certificate_key
309 syn keyword ngxDirective ssl_ciphers
310 syn keyword ngxDirective ssl_client_certificate
311 syn keyword ngxDirective ssl_crl
312 syn keyword ngxDirective ssl_dhparam
313 syn keyword ngxDirective ssl_engine
314 syn keyword ngxDirective ssl_prefer_server_ciphers
315 syn keyword ngxDirective ssl_protocols
316 syn keyword ngxDirective ssl_session_cache
317 syn keyword ngxDirective ssl_session_timeout
318 syn keyword ngxDirective ssl_verify_client
319 syn keyword ngxDirective ssl_verify_depth
320 syn keyword ngxDirective starttls
321 syn keyword ngxDirective stub_status
322 syn keyword ngxDirective sub_filter
323 syn keyword ngxDirective sub_filter_once
324 syn keyword ngxDirective sub_filter_types
325 syn keyword ngxDirective tcp_nodelay
326 syn keyword ngxDirective tcp_nopush
327 syn keyword ngxDirective thread_stack_size
328 syn keyword ngxDirective timeout
329 syn keyword ngxDirective timer_resolution
330 syn keyword ngxDirective types_hash_bucket_size
331 syn keyword ngxDirective types_hash_max_size
332 syn keyword ngxDirective underscores_in_headers
333 syn keyword ngxDirective uninitialized_variable_warn
334 syn keyword ngxDirective use
335 syn keyword ngxDirective user
336 syn keyword ngxDirective userid
337 syn keyword ngxDirective userid_domain
338 syn keyword ngxDirective userid_expires
339 syn keyword ngxDirective userid_mark
340 syn keyword ngxDirective userid_name
341 syn keyword ngxDirective userid_p3p
342 syn keyword ngxDirective userid_path
343 syn keyword ngxDirective userid_service
344 syn keyword ngxDirective valid_referers
345 syn keyword ngxDirective variables_hash_bucket_size
346 syn keyword ngxDirective variables_hash_max_size
347 syn keyword ngxDirective worker_connections
348 syn keyword ngxDirective worker_cpu_affinity
349 syn keyword ngxDirective worker_priority
350 syn keyword ngxDirective worker_processes
351 syn keyword ngxDirective worker_rlimit_core
352 syn keyword ngxDirective worker_rlimit_nofile
353 syn keyword ngxDirective worker_rlimit_sigpending
354 syn keyword ngxDirective worker_threads
355 syn keyword ngxDirective working_directory
356 syn keyword ngxDirective xclient
357 syn keyword ngxDirective xml_entities
358 syn keyword ngxDirective xslt_stylesheet
359 syn keyword ngxDirective xslt_types
360
361 " 3rd party module list:
362 " http://wiki.nginx.org/Nginx3rdPartyModules
363
364 " Accept Language Module <http://wiki.nginx.org/NginxAcceptLanguageModule>
365 " Parses the Accept-Language header and gives the most suitable locale from a list of supported locales.
366 syn keyword ngxDirectiveThirdParty set_from_accept_language
367
368 " Access Key Module <http://wiki.nginx.org/NginxHttpAccessKeyModule>
369 " Denies access unless the request URL contains an access key.
370 syn keyword ngxDirectiveThirdParty accesskey
371 syn keyword ngxDirectiveThirdParty accesskey_arg
372 syn keyword ngxDirectiveThirdParty accesskey_hashmethod
373 syn keyword ngxDirectiveThirdParty accesskey_signature
374
375 " Auth PAM Module <http://web.iti.upv.es/~sto/nginx/>
376 " HTTP Basic Authentication using PAM.
377 syn keyword ngxDirectiveThirdParty auth_pam
378 syn keyword ngxDirectiveThirdParty auth_pam_service_name
379
380 " Cache Purge Module <http://labs.frickle.com/nginx_ngx_cache_purge/>
381 " Module adding ability to purge content from FastCGI and proxy caches.
382 syn keyword ngxDirectiveThirdParty fastcgi_cache_purge
383 syn keyword ngxDirectiveThirdParty proxy_cache_purge
384
385 " Chunkin Module <http://wiki.nginx.org/NginxHttpChunkinModule>
386 " HTTP 1.1 chunked-encoding request body support for Nginx.
387 syn keyword ngxDirectiveThirdParty chunkin
388 syn keyword ngxDirectiveThirdParty chunkin_keepalive
389 syn keyword ngxDirectiveThirdParty chunkin_max_chunks_per_buf
390 syn keyword ngxDirectiveThirdParty chunkin_resume
391
392 " Circle GIF Module <http://wiki.nginx.org/NginxHttpCircleGifModule>
393 " Generates simple circle images with the colors and size specified in the URL.
394 syn keyword ngxDirectiveThirdParty circle_gif
395 syn keyword ngxDirectiveThirdParty circle_gif_max_radius
396 syn keyword ngxDirectiveThirdParty circle_gif_min_radius
397 syn keyword ngxDirectiveThirdParty circle_gif_step_radius
398
399 " Drizzle Module <http://github.com/chaoslawful/drizzle-nginx-module>
400 " Make nginx talk directly to mysql, drizzle, and sqlite3 by libdrizzle.
401 syn keyword ngxDirectiveThirdParty drizzle_connect_timeout
402 syn keyword ngxDirectiveThirdParty drizzle_dbname
403 syn keyword ngxDirectiveThirdParty drizzle_keepalive
404 syn keyword ngxDirectiveThirdParty drizzle_module_header
405 syn keyword ngxDirectiveThirdParty drizzle_pass
406 syn keyword ngxDirectiveThirdParty drizzle_query
407 syn keyword ngxDirectiveThirdParty drizzle_recv_cols_timeout
408 syn keyword ngxDirectiveThirdParty drizzle_recv_rows_timeout
409 syn keyword ngxDirectiveThirdParty drizzle_send_query_timeout
410 syn keyword ngxDirectiveThirdParty drizzle_server
411
412 " Echo Module <http://wiki.nginx.org/NginxHttpEchoModule>
413 " Brings 'echo', 'sleep', 'time', 'exec' and more shell-style goodies to Nginx config file.
414 syn keyword ngxDirectiveThirdParty echo
415 syn keyword ngxDirectiveThirdParty echo_after_body
416 syn keyword ngxDirectiveThirdParty echo_before_body
417 syn keyword ngxDirectiveThirdParty echo_blocking_sleep
418 syn keyword ngxDirectiveThirdParty echo_duplicate
419 syn keyword ngxDirectiveThirdParty echo_end
420 syn keyword ngxDirectiveThirdParty echo_exec
421 syn keyword ngxDirectiveThirdParty echo_flush
422 syn keyword ngxDirectiveThirdParty echo_foreach_split
423 syn keyword ngxDirectiveThirdParty echo_location
424 syn keyword ngxDirectiveThirdParty echo_location_async
425 syn keyword ngxDirectiveThirdParty echo_read_request_body
426 syn keyword ngxDirectiveThirdParty echo_request_body
427 syn keyword ngxDirectiveThirdParty echo_reset_timer
428 syn keyword ngxDirectiveThirdParty echo_sleep
429 syn keyword ngxDirectiveThirdParty echo_subrequest
430 syn keyword ngxDirectiveThirdParty echo_subrequest_async
431
432 " Events Module <http://docs.dutov.org/nginx_modules_events_en.html>
433 " Privides options for start/stop events.
434 syn keyword ngxDirectiveThirdParty on_start
435 syn keyword ngxDirectiveThirdParty on_stop
436
437 " EY Balancer Module <http://github.com/ry/nginx-ey-balancer>
438 " Adds a request queue to Nginx that allows the limiting of concurrent requests passed to the upstream.
439 syn keyword ngxDirectiveThirdParty max_connections
440 syn keyword ngxDirectiveThirdParty max_connections_max_queue_length
441 syn keyword ngxDirectiveThirdParty max_connections_queue_timeout
442
443 " Fancy Indexes Module <https://connectical.com/projects/ngx-fancyindex/wiki>
444 " Like the built-in autoindex module, but fancier.
445 syn keyword ngxDirectiveThirdParty fancyindex
446 syn keyword ngxDirectiveThirdParty fancyindex_exact_size
447 syn keyword ngxDirectiveThirdParty fancyindex_footer
448 syn keyword ngxDirectiveThirdParty fancyindex_header
449 syn keyword ngxDirectiveThirdParty fancyindex_localtime
450 syn keyword ngxDirectiveThirdParty fancyindex_readme
451 syn keyword ngxDirectiveThirdParty fancyindex_readme_mode
452
453 " GeoIP Module (DEPRECATED) <http://wiki.nginx.org/NginxHttp3rdPartyGeoIPModule>
454 " Country code lookups via the MaxMind GeoIP API.
455 syn keyword ngxDirectiveThirdParty geoip_country_file
456
457 " Headers More Module <http://wiki.nginx.org/NginxHttpHeadersMoreModule>
458 " Set and clear input and output headers...more than "add"!
459 syn keyword ngxDirectiveThirdParty more_clear_headers
460 syn keyword ngxDirectiveThirdParty more_clear_input_headers
461 syn keyword ngxDirectiveThirdParty more_set_headers
462 syn keyword ngxDirectiveThirdParty more_set_input_headers
463
464 " HTTP Push Module <http://pushmodule.slact.net/>
465 " Turn Nginx into an adept long-polling HTTP Push (Comet) server.
466 syn keyword ngxDirectiveThirdParty push_buffer_size
467 syn keyword ngxDirectiveThirdParty push_listener
468 syn keyword ngxDirectiveThirdParty push_message_timeout
469 syn keyword ngxDirectiveThirdParty push_queue_messages
470 syn keyword ngxDirectiveThirdParty push_sender
471
472 " HTTP Redis Module <http://people.FreeBSD.ORG/~osa/ngx_http_redis-0.3.1.tar.gz>>
473 " Redis <http://code.google.com/p/redis/> support.>
474 syn keyword ngxDirectiveThirdParty redis_bind
475 syn keyword ngxDirectiveThirdParty redis_buffer_size
476 syn keyword ngxDirectiveThirdParty redis_connect_timeout
477 syn keyword ngxDirectiveThirdParty redis_next_upstream
478 syn keyword ngxDirectiveThirdParty redis_pass
479 syn keyword ngxDirectiveThirdParty redis_read_timeout
480 syn keyword ngxDirectiveThirdParty redis_send_timeout
481
482 " HTTP JavaScript Module <http://wiki.github.com/kung-fu-tzu/ngx_http_js_module>
483 " Embedding SpiderMonkey. Nearly full port on Perl module.
484 syn keyword ngxDirectiveThirdParty js
485 syn keyword ngxDirectiveThirdParty js_filter
486 syn keyword ngxDirectiveThirdParty js_filter_types
487 syn keyword ngxDirectiveThirdParty js_load
488 syn keyword ngxDirectiveThirdParty js_maxmem
489 syn keyword ngxDirectiveThirdParty js_require
490 syn keyword ngxDirectiveThirdParty js_set
491 syn keyword ngxDirectiveThirdParty js_utf8
492
493 " Log Request Speed <http://wiki.nginx.org/NginxHttpLogRequestSpeed>
494 " Log the time it took to process each request.
495 syn keyword ngxDirectiveThirdParty log_request_speed_filter
496 syn keyword ngxDirectiveThirdParty log_request_speed_filter_timeout
497
498 " Memc Module <http://wiki.nginx.org/NginxHttpMemcModule>
499 " An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands.
500 syn keyword ngxDirectiveThirdParty memc_buffer_size
501 syn keyword ngxDirectiveThirdParty memc_cmds_allowed
502 syn keyword ngxDirectiveThirdParty memc_connect_timeout
503 syn keyword ngxDirectiveThirdParty memc_flags_to_last_modified
504 syn keyword ngxDirectiveThirdParty memc_next_upstream
505 syn keyword ngxDirectiveThirdParty memc_pass
506 syn keyword ngxDirectiveThirdParty memc_read_timeout
507 syn keyword ngxDirectiveThirdParty memc_send_timeout
508 syn keyword ngxDirectiveThirdParty memc_upstream_fail_timeout
509 syn keyword ngxDirectiveThirdParty memc_upstream_max_fails
510
511 " Mogilefs Module <http://www.grid.net.ru/nginx/mogilefs.en.html>
512 " Implements a MogileFS client, provides a replace to the Perlbal reverse proxy of the original MogileFS.
513 syn keyword ngxDirectiveThirdParty mogilefs_connect_timeout
514 syn keyword ngxDirectiveThirdParty mogilefs_domain
515 syn keyword ngxDirectiveThirdParty mogilefs_methods
516 syn keyword ngxDirectiveThirdParty mogilefs_noverify
517 syn keyword ngxDirectiveThirdParty mogilefs_pass
518 syn keyword ngxDirectiveThirdParty mogilefs_read_timeout
519 syn keyword ngxDirectiveThirdParty mogilefs_send_timeout
520 syn keyword ngxDirectiveThirdParty mogilefs_tracker
521
522 " MP4 Streaming Lite Module <http://wiki.nginx.org/NginxMP4StreamingLite>
523 " Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL.
524 syn keyword ngxDirectiveThirdParty mp4
525
526 " Nginx Notice Module <http://xph.us/software/nginx-notice/>
527 " Serve static file to POST requests.
528 syn keyword ngxDirectiveThirdParty notice
529 syn keyword ngxDirectiveThirdParty notice_type
530
531 " Phusion Passenger <http://www.modrails.com/documentation.html>
532 " Easy and robust deployment of Ruby on Rails application on Apache and Nginx webservers.
533 syn keyword ngxDirectiveThirdParty passenger_base_uri
534 syn keyword ngxDirectiveThirdParty passenger_default_user
535 syn keyword ngxDirectiveThirdParty passenger_enabled
536 syn keyword ngxDirectiveThirdParty passenger_log_level
537 syn keyword ngxDirectiveThirdParty passenger_max_instances_per_app
538 syn keyword ngxDirectiveThirdParty passenger_max_pool_size
539 syn keyword ngxDirectiveThirdParty passenger_pool_idle_time
540 syn keyword ngxDirectiveThirdParty passenger_root
541 syn keyword ngxDirectiveThirdParty passenger_ruby
542 syn keyword ngxDirectiveThirdParty passenger_use_global_queue
543 syn keyword ngxDirectiveThirdParty passenger_user_switching
544 syn keyword ngxDirectiveThirdParty rack_env
545 syn keyword ngxDirectiveThirdParty rails_app_spawner_idle_time
546 syn keyword ngxDirectiveThirdParty rails_env
547 syn keyword ngxDirectiveThirdParty rails_framework_spawner_idle_time
548 syn keyword ngxDirectiveThirdParty rails_spawn_method
549
550 " RDS JSON Module <http://github.com/agentzh/rds-json-nginx-module>
551 " Help ngx_drizzle and other DBD modules emit JSON data.
552 syn keyword ngxDirectiveThirdParty rds_json
553 syn keyword ngxDirectiveThirdParty rds_json_content_type
554 syn keyword ngxDirectiveThirdParty rds_json_format
555 syn keyword ngxDirectiveThirdParty rds_json_ret
556
557 " RRD Graph Module <http://wiki.nginx.org/NginxNgx_rrd_graph>
558 " This module provides an HTTP interface to RRDtool's graphing facilities.
559 syn keyword ngxDirectiveThirdParty rrd_graph
560 syn keyword ngxDirectiveThirdParty rrd_graph_root
561
562 " Secure Download <http://wiki.nginx.org/NginxHttpSecureDownload>
563 " Create expiring links.
564 syn keyword ngxDirectiveThirdParty secure_download
565 syn keyword ngxDirectiveThirdParty secure_download_fail_location
566 syn keyword ngxDirectiveThirdParty secure_download_path_mode
567 syn keyword ngxDirectiveThirdParty secure_download_secret
568
569 " SlowFS Cache Module <http://labs.frickle.com/nginx_ngx_slowfs_cache/>
570 " Module adding ability to cache static files.
571 syn keyword ngxDirectiveThirdParty slowfs_big_file_size
572 syn keyword ngxDirectiveThirdParty slowfs_cache
573 syn keyword ngxDirectiveThirdParty slowfs_cache_key
574 syn keyword ngxDirectiveThirdParty slowfs_cache_min_uses
575 syn keyword ngxDirectiveThirdParty slowfs_cache_path
576 syn keyword ngxDirectiveThirdParty slowfs_cache_purge
577 syn keyword ngxDirectiveThirdParty slowfs_cache_valid
578 syn keyword ngxDirectiveThirdParty slowfs_temp_path
579
580 " Strip Module <http://wiki.nginx.org/NginxHttpStripModule>
581 " Whitespace remover.
582 syn keyword ngxDirectiveThirdParty strip
583
584 " Substitutions Module <http://wiki.nginx.org/NginxHttpSubsModule>
585 " A filter module which can do both regular expression and fixed string substitutions on response bodies.
586 syn keyword ngxDirectiveThirdParty subs_filter
587 syn keyword ngxDirectiveThirdParty subs_filter_types
588
589 " Supervisord Module <http://labs.frickle.com/nginx_ngx_supervisord/>
590 " Module providing nginx with API to communicate with supervisord and manage (start/stop) backends on-demand.
591 syn keyword ngxDirectiveThirdParty supervisord
592 syn keyword ngxDirectiveThirdParty supervisord_inherit_backend_status
593 syn keyword ngxDirectiveThirdParty supervisord_name
594 syn keyword ngxDirectiveThirdParty supervisord_start
595 syn keyword ngxDirectiveThirdParty supervisord_stop
596
597 " Upload Module <http://www.grid.net.ru/nginx/upload.en.html>
598 " Parses multipart/form-data allowing arbitrary handling of uploaded files.
599 syn keyword ngxDirectiveThirdParty upload_aggregate_form_field
600 syn keyword ngxDirectiveThirdParty upload_buffer_size
601 syn keyword ngxDirectiveThirdParty upload_cleanup
602 syn keyword ngxDirectiveThirdParty upload_limit_rate
603 syn keyword ngxDirectiveThirdParty upload_max_file_size
604 syn keyword ngxDirectiveThirdParty upload_max_output_body_len
605 syn keyword ngxDirectiveThirdParty upload_max_part_header_len
606 syn keyword ngxDirectiveThirdParty upload_pass
607 syn keyword ngxDirectiveThirdParty upload_pass_args
608 syn keyword ngxDirectiveThirdParty upload_pass_form_field
609 syn keyword ngxDirectiveThirdParty upload_set_form_field
610 syn keyword ngxDirectiveThirdParty upload_store
611 syn keyword ngxDirectiveThirdParty upload_store_access
612
613 " Upload Progress Module <http://wiki.nginx.org/NginxHttpUploadProgressModule>
614 " Tracks and reports upload progress.
615 syn keyword ngxDirectiveThirdParty report_uploads
616 syn keyword ngxDirectiveThirdParty track_uploads
617 syn keyword ngxDirectiveThirdParty upload_progress
618 syn keyword ngxDirectiveThirdParty upload_progress_content_type
619 syn keyword ngxDirectiveThirdParty upload_progress_header
620 syn keyword ngxDirectiveThirdParty upload_progress_json_output
621 syn keyword ngxDirectiveThirdParty upload_progress_template
622
623 " Upstream Fair Balancer <http://wiki.nginx.org/NginxHttpUpstreamFairModule>
624 " Sends an incoming request to the least-busy backend server, rather than distributing requests round-robin.
625 syn keyword ngxDirectiveThirdParty fair
626 syn keyword ngxDirectiveThirdParty upstream_fair_shm_size
627
628 " Upstream Consistent Hash <http://wiki.nginx.org/NginxHttpUpstreamConsistentHash>
629 " Select backend based on Consistent hash ring.
630 syn keyword ngxDirectiveThirdParty consistent_hash
631
632 " Upstream Hash Module <http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule>
633 " Provides simple upstream load distribution by hashing a configurable variable.
634 syn keyword ngxDirectiveThirdParty hash
635 syn keyword ngxDirectiveThirdParty hash_again
636
637 " XSS Module <http://github.com/agentzh/xss-nginx-module>
638 " Native support for cross-site scripting (XSS) in an nginx.
639 syn keyword ngxDirectiveThirdParty xss_callback_arg
640 syn keyword ngxDirectiveThirdParty xss_get
641 syn keyword ngxDirectiveThirdParty xss_input_types
642 syn keyword ngxDirectiveThirdParty xss_output_type
643
644 " uWSGI Module <http://wiki.nginx.org/HttpUwsgiModule>
645 " Allows Nginx to interact with uWSGI processes and control what parameters are passed to the process.
646 syn keyword ngxDirectiveThirdParty uwsgi_bind
647 syn keyword ngxDirectiveThirdParty uwsgi_buffer_size
648 syn keyword ngxDirectiveThirdParty uwsgi_buffering
649 syn keyword ngxDirectiveThirdParty uwsgi_buffers
650 syn keyword ngxDirectiveThirdParty uwsgi_busy_buffers_size
651 syn keyword ngxDirectiveThirdParty uwsgi_cache
652 syn keyword ngxDirectiveThirdParty uwsgi_cache_bypass
653 syn keyword ngxDirectiveThirdParty uwsgi_cache_key
654 syn keyword ngxDirectiveThirdParty uwsgi_cache_lock
655 syn keyword ngxDirectiveThirdParty uwsgi_cache_lock_timeout
656 syn keyword ngxDirectiveThirdParty uwsgi_cache_methods
657 syn keyword ngxDirectiveThirdParty uwsgi_cache_min_uses
658 syn keyword ngxDirectiveThirdParty uwsgi_cache_path
659 syn keyword ngxDirectiveThirdParty uwsgi_cache_use_stale
660 syn keyword ngxDirectiveThirdParty uwsgi_cache_valid
661 syn keyword ngxDirectiveThirdParty uwsgi_connect_timeout
662 syn keyword ngxDirectiveThirdParty uwsgi_hide_header
663 syn keyword ngxDirectiveThirdParty uwsgi_ignore_client_abort
664 syn keyword ngxDirectiveThirdParty uwsgi_ignore_headers
665 syn keyword ngxDirectiveThirdParty uwsgi_intercept_errors
666 syn keyword ngxDirectiveThirdParty uwsgi_max_temp_file_size
667 syn keyword ngxDirectiveThirdParty uwsgi_modifier1
668 syn keyword ngxDirectiveThirdParty uwsgi_modifier2
669 syn keyword ngxDirectiveThirdParty uwsgi_next_upstream
670 syn keyword ngxDirectiveThirdParty uwsgi_no_cache
671 syn keyword ngxDirectiveThirdParty uwsgi_param
672 syn keyword ngxDirectiveThirdParty uwsgi_pass
673 syn keyword ngxDirectiveThirdParty uwsgi_pass_header
674 syn keyword ngxDirectiveThirdParty uwsgi_pass_request_body
675 syn keyword ngxDirectiveThirdParty uwsgi_pass_request_headers
676 syn keyword ngxDirectiveThirdParty uwsgi_read_timeout
677 syn keyword ngxDirectiveThirdParty uwsgi_send_timeout
678 syn keyword ngxDirectiveThirdParty uwsgi_store
679 syn keyword ngxDirectiveThirdParty uwsgi_store_access
680 syn keyword ngxDirectiveThirdParty uwsgi_string
681 syn keyword ngxDirectiveThirdParty uwsgi_temp_file_write_size
682 syn keyword ngxDirectiveThirdParty uwsgi_temp_path
683
684 " highlight
685
686 hi link ngxComment Comment
687 hi link ngxVariable Identifier
688 hi link ngxVariableBlock Identifier
689 hi link ngxVariableString PreProc
690 hi link ngxBlock Normal
691 hi link ngxString String
692
693 hi link ngxBoolean Boolean
694 hi link ngxDirectiveBlock Statement
695 hi link ngxDirectiveImportant Type
696 hi link ngxDirectiveControl Keyword
697 hi link ngxDirectiveError Constant
698 hi link ngxDirectiveDeprecated Error
699 hi link ngxDirective Identifier
700 hi link ngxDirectiveThirdParty Special
701
702 let b:current_syntax = "nginx"
386386 return 1;
387387 }
388388
389 if (cycle->log->file->fd != ngx_stderr) {
390
391 if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
392 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
393 ngx_set_stderr_n " failed");
394 return 1;
395 }
389 if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
390 return 1;
396391 }
397392
398393 if (log->file->fd != ngx_stderr) {
88 #define _NGINX_H_INCLUDED_
99
1010
11 #define nginx_version 1004007
12 #define NGINX_VERSION "1.4.7"
11 #define nginx_version 1006000
12 #define NGINX_VERSION "1.6.0"
1313 #define NGINX_VER "nginx/" NGINX_VERSION
1414
1515 #define NGINX_VAR "NGINX"
1111
1212 static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
1313 static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
14 static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name);
1514 static void ngx_conf_flush_files(ngx_cycle_t *cycle);
1615
1716
224223 * "types { ... }" directive
225224 */
226225
226 if (rc == NGX_CONF_BLOCK_START) {
227 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
228 goto failed;
229 }
230
227231 rv = (*cf->handler)(cf, NULL, cf->handler_conf);
228232 if (rv == NGX_CONF_OK) {
229233 continue;
795799 ngx_int_t
796800 ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
797801 {
798 size_t len;
799 u_char *p, *n, *prefix;
800 ngx_int_t rc;
801
802 rc = ngx_conf_test_full_name(name);
803
804 if (rc == NGX_OK) {
805 return rc;
806 }
807
808 if (conf_prefix) {
809 len = cycle->conf_prefix.len;
810 prefix = cycle->conf_prefix.data;
811
812 } else {
813 len = cycle->prefix.len;
814 prefix = cycle->prefix.data;
815 }
816
817 #if (NGX_WIN32)
818
819 if (rc == 2) {
820 len = rc;
821 }
822
823 #endif
824
825 n = ngx_pnalloc(cycle->pool, len + name->len + 1);
826 if (n == NULL) {
827 return NGX_ERROR;
828 }
829
830 p = ngx_cpymem(n, prefix, len);
831 ngx_cpystrn(p, name->data, name->len + 1);
832
833 name->len += len;
834 name->data = n;
835
836 return NGX_OK;
837 }
838
839
840 static ngx_int_t
841 ngx_conf_test_full_name(ngx_str_t *name)
842 {
843 #if (NGX_WIN32)
844 u_char c0, c1;
845
846 c0 = name->data[0];
847
848 if (name->len < 2) {
849 if (c0 == '/') {
850 return 2;
851 }
852
853 return NGX_DECLINED;
854 }
855
856 c1 = name->data[1];
857
858 if (c1 == ':') {
859 c0 |= 0x20;
860
861 if ((c0 >= 'a' && c0 <= 'z')) {
862 return NGX_OK;
863 }
864
865 return NGX_DECLINED;
866 }
867
868 if (c1 == '/') {
869 return NGX_OK;
870 }
871
872 if (c0 == '/') {
873 return 2;
874 }
875
876 return NGX_DECLINED;
877
878 #else
879
880 if (name->data[0] == '/') {
881 return NGX_OK;
882 }
883
884 return NGX_DECLINED;
885
886 #endif
802 ngx_str_t *prefix;
803
804 prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix;
805
806 return ngx_get_full_name(cycle->pool, prefix, name);
887807 }
888808
889809
44 */
55
66
7 #ifndef _NGX_HTTP_CONF_FILE_H_INCLUDED_
8 #define _NGX_HTTP_CONF_FILE_H_INCLUDED_
7 #ifndef _NGX_CONF_FILE_H_INCLUDED_
8 #define _NGX_CONF_FILE_H_INCLUDED_
99
1010
1111 #include <ngx_config.h>
336336 extern ngx_module_t *ngx_modules[];
337337
338338
339 #endif /* _NGX_HTTP_CONF_FILE_H_INCLUDED_ */
339 #endif /* _NGX_CONF_FILE_H_INCLUDED_ */
7979 typedef intptr_t ngx_flag_t;
8080
8181
82 #define NGX_INT32_LEN sizeof("-2147483648") - 1
83 #define NGX_INT64_LEN sizeof("-9223372036854775808") - 1
82 #define NGX_INT32_LEN (sizeof("-2147483648") - 1)
83 #define NGX_INT64_LEN (sizeof("-9223372036854775808") - 1)
8484
8585 #if (NGX_PTR_SIZE == 4)
8686 #define NGX_INT_T_LEN NGX_INT32_LEN
4040 ls->sockaddr = sa;
4141 ls->socklen = socklen;
4242
43 len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
43 len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
4444 ls->addr_text.len = len;
4545
4646 switch (ls->sockaddr->sa_family) {
7979
8080 #if (NGX_HAVE_SETFIB)
8181 ls->setfib = -1;
82 #endif
83
84 #if (NGX_HAVE_TCP_FASTOPEN)
85 ls->fastopen = -1;
8286 #endif
8387
8488 return ls;
9296 ngx_uint_t i;
9397 ngx_listening_t *ls;
9498 socklen_t olen;
99 #if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
100 ngx_err_t err;
101 #endif
95102 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
96 ngx_err_t err;
97103 struct accept_filter_arg af;
98104 #endif
99105 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
122128 #if (NGX_HAVE_INET6)
123129 case AF_INET6:
124130 ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
125 len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
131 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
126132 break;
127133 #endif
128134
151157 return NGX_ERROR;
152158 }
153159
154 len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data, len, 1);
160 len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
161 ls[i].addr_text.data, len, 1);
155162 if (len == 0) {
156163 return NGX_ERROR;
157164 }
191198
192199 #if (NGX_HAVE_SETFIB)
193200
194 if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB,
201 olen = sizeof(int);
202
203 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
195204 (void *) &ls[i].setfib, &olen)
196205 == -1)
197206 {
205214 #endif
206215 #endif
207216
217 #if (NGX_HAVE_TCP_FASTOPEN)
218
219 olen = sizeof(int);
220
221 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
222 (void *) &ls[i].fastopen, &olen)
223 == -1)
224 {
225 err = ngx_socket_errno;
226
227 if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) {
228 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
229 "getsockopt(TCP_FASTOPEN) %V failed, ignored",
230 &ls[i].addr_text);
231 }
232
233 ls[i].fastopen = -1;
234 }
235
236 #endif
237
208238 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
209239
210240 ngx_memzero(&af, sizeof(struct accept_filter_arg));
213243 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
214244 == -1)
215245 {
216 err = ngx_errno;
246 err = ngx_socket_errno;
217247
218248 if (err == NGX_EINVAL) {
219249 continue;
246276 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
247277 == -1)
248278 {
249 ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
279 err = ngx_socket_errno;
280
281 if (err == NGX_EOPNOTSUPP) {
282 continue;
283 }
284
285 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
250286 "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
251287 &ls[i].addr_text);
252288 continue;
295331 continue;
296332 }
297333
298 if (ls[i].fd != -1) {
334 if (ls[i].fd != (ngx_socket_t) -1) {
299335 continue;
300336 }
301337
310346
311347 s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
312348
313 if (s == -1) {
349 if (s == (ngx_socket_t) -1) {
314350 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
315351 ngx_socket_n " %V failed", &ls[i].addr_text);
316352 return NGX_ERROR;
462498 void
463499 ngx_configure_listening_sockets(ngx_cycle_t *cycle)
464500 {
465 int keepalive;
501 int value;
466502 ngx_uint_t i;
467503 ngx_listening_t *ls;
468504
469505 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
470506 struct accept_filter_arg af;
471 #endif
472 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
473 int timeout;
474507 #endif
475508
476509 ls = cycle->listening.elts;
501534 }
502535
503536 if (ls[i].keepalive) {
504 keepalive = (ls[i].keepalive == 1) ? 1 : 0;
537 value = (ls[i].keepalive == 1) ? 1 : 0;
505538
506539 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
507 (const void *) &keepalive, sizeof(int))
540 (const void *) &value, sizeof(int))
508541 == -1)
509542 {
510543 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
511544 "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
512 keepalive, &ls[i].addr_text);
545 value, &ls[i].addr_text);
513546 }
514547 }
515548
516549 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
517550
518551 if (ls[i].keepidle) {
552 value = ls[i].keepidle;
553
554 #if (NGX_KEEPALIVE_FACTOR)
555 value *= NGX_KEEPALIVE_FACTOR;
556 #endif
557
519558 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
520 (const void *) &ls[i].keepidle, sizeof(int))
559 (const void *) &value, sizeof(int))
521560 == -1)
522561 {
523562 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
524563 "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
525 ls[i].keepidle, &ls[i].addr_text);
564 value, &ls[i].addr_text);
526565 }
527566 }
528567
529568 if (ls[i].keepintvl) {
569 value = ls[i].keepintvl;
570
571 #if (NGX_KEEPALIVE_FACTOR)
572 value *= NGX_KEEPALIVE_FACTOR;
573 #endif
574
530575 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
531 (const void *) &ls[i].keepintvl, sizeof(int))
576 (const void *) &value, sizeof(int))
532577 == -1)
533578 {
534579 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
535580 "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
536 ls[i].keepintvl, &ls[i].addr_text);
581 value, &ls[i].addr_text);
537582 }
538583 }
539584
563608 }
564609 #endif
565610
611 #if (NGX_HAVE_TCP_FASTOPEN)
612 if (ls[i].fastopen != -1) {
613 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
614 (const void *) &ls[i].fastopen, sizeof(int))
615 == -1)
616 {
617 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
618 "setsockopt(TCP_FASTOPEN, %d) %V failed, ignored",
619 ls[i].fastopen, &ls[i].addr_text);
620 }
621 }
622 #endif
623
566624 #if 0
567625 if (1) {
568626 int tcp_nodelay = 1;
602660 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
603661 == -1)
604662 {
605 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
663 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
606664 "setsockopt(SO_ACCEPTFILTER, NULL) "
607665 "for %V failed, ignored",
608666 &ls[i].addr_text);
629687 &af, sizeof(struct accept_filter_arg))
630688 == -1)
631689 {
632 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
690 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
633691 "setsockopt(SO_ACCEPTFILTER, \"%s\") "
634692 "for %V failed, ignored",
635693 ls[i].accept_filter, &ls[i].addr_text);
652710 * if syncookies were used), hence we use 1 second timeout
653711 * here.
654712 */
655 timeout = 1;
713 value = 1;
656714
657715 } else {
658 timeout = 0;
716 value = 0;
659717 }
660718
661719 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
662 &timeout, sizeof(int))
720 &value, sizeof(int))
663721 == -1)
664722 {
665 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
723 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
666724 "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
667725 "ignored",
668 timeout, &ls[i].addr_text);
726 value, &ls[i].addr_text);
669727
670728 continue;
671729 }
858916 ngx_uint_t log_error, level;
859917 ngx_socket_t fd;
860918
861 if (c->fd == -1) {
919 if (c->fd == (ngx_socket_t) -1) {
862920 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
863921 return;
864922 }
10331091 struct sockaddr_in6 *sin6;
10341092 #endif
10351093
1094 if (c->local_socklen == 0) {
1095 return NGX_ERROR;
1096 }
1097
10361098 switch (c->local_sockaddr->sa_family) {
10371099
10381100 #if (NGX_HAVE_INET6)
10431105 addr |= sin6->sin6_addr.s6_addr[i];
10441106 }
10451107
1108 break;
1109 #endif
1110
1111 #if (NGX_HAVE_UNIX_DOMAIN)
1112 case AF_UNIX:
1113 addr = 1;
10461114 break;
10471115 #endif
10481116
10671135 }
10681136
10691137 ngx_memcpy(c->local_sockaddr, &sa, len);
1138
1139 c->local_socklen = len;
10701140 }
10711141
10721142 if (s == NULL) {
10731143 return NGX_OK;
10741144 }
10751145
1076 s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, port);
1146 s->len = ngx_sock_ntop(c->local_sockaddr, c->local_socklen,
1147 s->data, s->len, port);
10771148
10781149 return NGX_OK;
10791150 }
7979 int setfib;
8080 #endif
8181
82 #if (NGX_HAVE_TCP_FASTOPEN)
83 int fastopen;
84 #endif
85
8286 };
8387
8488
107111
108112 #define NGX_LOWLEVEL_BUFFERED 0x0f
109113 #define NGX_SSL_BUFFERED 0x01
114 #define NGX_SPDY_BUFFERED 0x02
110115
111116
112117 struct ngx_connection_s {
133138 socklen_t socklen;
134139 ngx_str_t addr_text;
135140
141 ngx_str_t proxy_protocol_addr;
142
136143 #if (NGX_SSL)
137144 ngx_ssl_connection_t *ssl;
138145 #endif
139146
140147 struct sockaddr *local_sockaddr;
148 socklen_t local_socklen;
141149
142150 ngx_buf_t *buffer;
143151
165173 unsigned tcp_nodelay:2; /* ngx_connection_tcp_nodelay_e */
166174 unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */
167175
176 unsigned need_last_buf:1;
177
168178 #if (NGX_HAVE_IOCP)
169179 unsigned accept_context_updated:1;
170180 #endif
171181
172182 #if (NGX_HAVE_AIO_SENDFILE)
173183 unsigned aio_sendfile:1;
184 unsigned busy_count:2;
174185 ngx_buf_t *busy_sendfile;
175186 #endif
176187
7676 #include <ngx_open_file_cache.h>
7777 #include <ngx_os.h>
7878 #include <ngx_connection.h>
79 #include <ngx_proxy_protocol.h>
7980
8081
8182 #define LF (u_char) 10
1010
1111
1212 static void ngx_destroy_cycle_pools(ngx_conf_t *conf);
13 static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2);
1413 static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle,
1514 ngx_shm_zone_t *shm_zone);
1615 static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
3433 /* STUB NAME */
3534 static ngx_connection_t dumb;
3635 /* STUB */
37
38 static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
3936
4037
4138 ngx_cycle_t *
8380
8481 cycle->pool = pool;
8582 cycle->log = log;
86 cycle->new_log.log_level = NGX_LOG_ERR;
8783 cycle->old_cycle = old_cycle;
8884
8985 cycle->conf_prefix.len = old_cycle->conf_prefix.len;
338334 }
339335
340336
341 if (cycle->new_log.file == NULL) {
342 cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);
343 if (cycle->new_log.file == NULL) {
344 goto failed;
345 }
337 if (ngx_log_open_default(cycle) != NGX_OK) {
338 goto failed;
346339 }
347340
348341 /* open the new files */
499492 continue;
500493 }
501494
502 if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)
495 if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen,
496 ls[i].sockaddr, ls[i].socklen, 1)
497 == NGX_OK)
503498 {
504499 nls[n].fd = ls[i].fd;
505500 nls[n].previous = &ls[i];
506501 ls[i].remain = 1;
507502
508 if (ls[n].backlog != nls[i].backlog) {
503 if (ls[i].backlog != nls[n].backlog) {
509504 nls[n].listen = 1;
510505 }
511506
536531
537532 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
538533
539 if (ls[n].deferred_accept && !nls[n].deferred_accept) {
534 if (ls[i].deferred_accept && !nls[n].deferred_accept) {
540535 nls[n].delete_deferred = 1;
541536
542537 } else if (ls[i].deferred_accept != nls[n].deferred_accept)
548543 }
549544 }
550545
551 if (nls[n].fd == -1) {
546 if (nls[n].fd == (ngx_socket_t) -1) {
552547 nls[n].open = 1;
548 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
549 if (nls[n].accept_filter) {
550 nls[n].add_deferred = 1;
551 }
552 #endif
553 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
554 if (nls[n].deferred_accept) {
555 nls[n].add_deferred = 1;
556 }
557 #endif
553558 }
554559 }
555560
581586
582587 /* commit the new cycle configuration */
583588
584 if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) {
585
586 if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
587 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
588 ngx_set_stderr_n " failed");
589 }
589 if (!ngx_use_stderr) {
590 (void) ngx_log_redirect_stderr(cycle);
590591 }
591592
592593 pool->log = cycle->log;
658659 ls = old_cycle->listening.elts;
659660 for (i = 0; i < old_cycle->listening.nelts; i++) {
660661
661 if (ls[i].remain || ls[i].fd == -1) {
662 if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) {
662663 continue;
663664 }
664665
822823
823824 ls = cycle->listening.elts;
824825 for (i = 0; i < cycle->listening.nelts; i++) {
825 if (ls[i].fd == -1 || !ls[i].open) {
826 if (ls[i].fd == (ngx_socket_t) -1 || !ls[i].open) {
826827 continue;
827828 }
828829
844845 {
845846 ngx_destroy_pool(conf->temp_pool);
846847 ngx_destroy_pool(conf->pool);
847 }
848
849
850 static ngx_int_t
851 ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2)
852 {
853 struct sockaddr_in *sin1, *sin2;
854 #if (NGX_HAVE_INET6)
855 struct sockaddr_in6 *sin61, *sin62;
856 #endif
857 #if (NGX_HAVE_UNIX_DOMAIN)
858 struct sockaddr_un *saun1, *saun2;
859 #endif
860
861 if (sa1->sa_family != sa2->sa_family) {
862 return NGX_DECLINED;
863 }
864
865 switch (sa1->sa_family) {
866
867 #if (NGX_HAVE_INET6)
868 case AF_INET6:
869 sin61 = (struct sockaddr_in6 *) sa1;
870 sin62 = (struct sockaddr_in6 *) sa2;
871
872 if (sin61->sin6_port != sin62->sin6_port) {
873 return NGX_DECLINED;
874 }
875
876 if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
877 return NGX_DECLINED;
878 }
879
880 break;
881 #endif
882
883 #if (NGX_HAVE_UNIX_DOMAIN)
884 case AF_UNIX:
885 saun1 = (struct sockaddr_un *) sa1;
886 saun2 = (struct sockaddr_un *) sa2;
887
888 if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
889 sizeof(saun1->sun_path))
890 != 0)
891 {
892 return NGX_DECLINED;
893 }
894
895 break;
896 #endif
897
898 default: /* AF_INET */
899
900 sin1 = (struct sockaddr_in *) sa1;
901 sin2 = (struct sockaddr_in *) sa2;
902
903 if (sin1->sin_port != sin2->sin_port) {
904 return NGX_DECLINED;
905 }
906
907 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
908 return NGX_DECLINED;
909 }
910
911 break;
912 }
913
914 return NGX_OK;
915848 }
916849
917850
12271160 file[i].fd = fd;
12281161 }
12291162
1230 #if !(NGX_WIN32)
1231
1232 if (cycle->log->file->fd != STDERR_FILENO) {
1233 if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
1234 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1235 "dup2(STDERR) failed");
1236 }
1237 }
1238
1239 #endif
1163 (void) ngx_log_redirect_stderr(cycle);
12401164 }
12411165
12421166
3939
4040 ngx_log_t *log;
4141 ngx_log_t new_log;
42
43 ngx_uint_t log_use_stderr; /* unsigned log_use_stderr:1; */
4244
4345 ngx_connection_t **files;
4446 ngx_connection_t *free_connections;
88 #include <ngx_core.h>
99
1010
11 static ngx_int_t ngx_test_full_name(ngx_str_t *name);
12
13
1114 static ngx_atomic_t temp_number = 0;
1215 ngx_atomic_t *ngx_temp_number = &temp_number;
1316 ngx_atomic_int_t ngx_random_number = 123456;
17
18
19 ngx_int_t
20 ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix, ngx_str_t *name)
21 {
22 size_t len;
23 u_char *p, *n;
24 ngx_int_t rc;
25
26 rc = ngx_test_full_name(name);
27
28 if (rc == NGX_OK) {
29 return rc;
30 }
31
32 len = prefix->len;
33
34 #if (NGX_WIN32)
35
36 if (rc == 2) {
37 len = rc;
38 }
39
40 #endif
41
42 n = ngx_pnalloc(pool, len + name->len + 1);
43 if (n == NULL) {
44 return NGX_ERROR;
45 }
46
47 p = ngx_cpymem(n, prefix->data, len);
48 ngx_cpystrn(p, name->data, name->len + 1);
49
50 name->len += len;
51 name->data = n;
52
53 return NGX_OK;
54 }
55
56
57 static ngx_int_t
58 ngx_test_full_name(ngx_str_t *name)
59 {
60 #if (NGX_WIN32)
61 u_char c0, c1;
62
63 c0 = name->data[0];
64
65 if (name->len < 2) {
66 if (c0 == '/') {
67 return 2;
68 }
69
70 return NGX_DECLINED;
71 }
72
73 c1 = name->data[1];
74
75 if (c1 == ':') {
76 c0 |= 0x20;
77
78 if ((c0 >= 'a' && c0 <= 'z')) {
79 return NGX_OK;
80 }
81
82 return NGX_DECLINED;
83 }
84
85 if (c1 == '/') {
86 return NGX_OK;
87 }
88
89 if (c0 == '/') {
90 return 2;
91 }
92
93 return NGX_DECLINED;
94
95 #else
96
97 if (name->data[0] == '/') {
98 return NGX_OK;
99 }
100
101 return NGX_DECLINED;
102
103 #endif
104 }
14105
15106
16107 ssize_t
267358 return NULL;
268359 }
269360
270 path->len = 0;
271 path->manager = NULL;
272 path->loader = NULL;
273361 path->conf_file = cf->conf_file->file.name.data;
274362 path->line = cf->conf_file->line;
275363
310398 return NGX_CONF_OK;
311399 }
312400
313 *path = ngx_palloc(cf->pool, sizeof(ngx_path_t));
401 *path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t));
314402 if (*path == NULL) {
315403 return NGX_CONF_ERROR;
316404 }
328416 (*path)->len = init->level[0] + (init->level[0] ? 1 : 0)
329417 + init->level[1] + (init->level[1] ? 1 : 0)
330418 + init->level[2] + (init->level[2] ? 1 : 0);
331
332 (*path)->manager = NULL;
333 (*path)->loader = NULL;
334 (*path)->conf_file = NULL;
335419
336420 if (ngx_add_path(cf, path) != NGX_OK) {
337421 return NGX_CONF_ERROR;
416500 if (p[i]->name.len == path->name.len
417501 && ngx_strcmp(p[i]->name.data, path->name.data) == 0)
418502 {
503 if (p[i]->data != path->data) {
504 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
505 "the same path name \"%V\" "
506 "used in %s:%ui and",
507 &p[i]->name, p[i]->conf_file, p[i]->line);
508 return NGX_ERROR;
509 }
510
419511 for (n = 0; n < 3; n++) {
420512 if (p[i]->level[n] != path->level[n]) {
421513 if (path->conf_file == NULL) {
121121 };
122122
123123
124 ngx_int_t ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix,
125 ngx_str_t *name);
126
124127 ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain);
125128 ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path,
126129 ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean,
281281 start = hinit->max_size - 1000;
282282 }
283283
284 for (size = start; size < hinit->max_size; size++) {
284 for (size = start; size <= hinit->max_size; size++) {
285285
286286 ngx_memzero(test, size * sizeof(u_short));
287287
311311 continue;
312312 }
313313
314 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
315 "could not build the %s, you should increase "
316 "either %s_max_size: %i or %s_bucket_size: %i",
314 ngx_log_error(NGX_LOG_WARN, hinit->pool->log, 0,
315 "could not build optimal %s, you should increase "
316 "either %s_max_size: %i or %s_bucket_size: %i; "
317 "ignoring %s_bucket_size",
317318 hinit->name, hinit->name, hinit->max_size,
318 hinit->name, hinit->bucket_size);
319
320 ngx_free(test);
321
322 return NGX_ERROR;
319 hinit->name, hinit->bucket_size, hinit->name);
323320
324321 found:
325322
173173
174174
175175 size_t
176 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
176 ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len,
177 ngx_uint_t port)
177178 {
178179 u_char *p;
179180 struct sockaddr_in *sin;
229230 case AF_UNIX:
230231 saun = (struct sockaddr_un *) sa;
231232
233 /* on Linux sockaddr might not include sun_path at all */
234
235 if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
236 p = ngx_snprintf(text, len, "unix:%Z");
237
238 } else {
239 p = ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path);
240 }
241
232242 /* we do not include trailing zero in address length */
233243
234 return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
244 return (p - text - 1);
235245
236246 #endif
237247
952962 ngx_memzero(&hints, sizeof(struct addrinfo));
953963 hints.ai_family = AF_UNSPEC;
954964 hints.ai_socktype = SOCK_STREAM;
965 #ifdef AI_ADDRCONFIG
966 hints.ai_flags = AI_ADDRCONFIG;
967 #endif
955968
956969 if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
957970 u->err = "host not found";
10191032 goto failed;
10201033 }
10211034
1022 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
1035 len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1);
10231036
10241037 u->addrs[i].name.len = len;
10251038 u->addrs[i].name.data = p;
10521065 goto failed;
10531066 }
10541067
1055 len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
1068 len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p,
1069 len, 1);
10561070
10571071 u->addrs[i].name.len = len;
10581072 u->addrs[i].name.data = p;
11371151 return NGX_ERROR;
11381152 }
11391153
1140 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
1154 len = ngx_sock_ntop((struct sockaddr *) sin,
1155 sizeof(struct sockaddr_in), p, len, 1);
11411156
11421157 u->addrs[i].name.len = len;
11431158 u->addrs[i].name.data = p;
11801195 }
11811196
11821197 #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
1198
1199
1200 ngx_int_t
1201 ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
1202 struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
1203 {
1204 struct sockaddr_in *sin1, *sin2;
1205 #if (NGX_HAVE_INET6)
1206 struct sockaddr_in6 *sin61, *sin62;
1207 #endif
1208 #if (NGX_HAVE_UNIX_DOMAIN)
1209 struct sockaddr_un *saun1, *saun2;
1210 #endif
1211
1212 if (sa1->sa_family != sa2->sa_family) {
1213 return NGX_DECLINED;
1214 }
1215
1216 switch (sa1->sa_family) {
1217
1218 #if (NGX_HAVE_INET6)
1219 case AF_INET6:
1220
1221 sin61 = (struct sockaddr_in6 *) sa1;
1222 sin62 = (struct sockaddr_in6 *) sa2;
1223
1224 if (cmp_port && sin61->sin6_port != sin62->sin6_port) {
1225 return NGX_DECLINED;
1226 }
1227
1228 if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
1229 return NGX_DECLINED;
1230 }
1231
1232 break;
1233 #endif
1234
1235 #if (NGX_HAVE_UNIX_DOMAIN)
1236 case AF_UNIX:
1237
1238 /* TODO length */
1239
1240 saun1 = (struct sockaddr_un *) sa1;
1241 saun2 = (struct sockaddr_un *) sa2;
1242
1243 if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
1244 sizeof(saun1->sun_path))
1245 != 0)
1246 {
1247 return NGX_DECLINED;
1248 }
1249
1250 break;
1251 #endif
1252
1253 default: /* AF_INET */
1254
1255 sin1 = (struct sockaddr_in *) sa1;
1256 sin2 = (struct sockaddr_in *) sa2;
1257
1258 if (cmp_port && sin1->sin_port != sin2->sin_port) {
1259 return NGX_DECLINED;
1260 }
1261
1262 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1263 return NGX_DECLINED;
1264 }
1265
1266 break;
1267 }
1268
1269 return NGX_OK;
1270 }
106106 ngx_int_t ngx_inet6_addr(u_char *p, size_t len, u_char *addr);
107107 size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
108108 #endif
109 size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
110 ngx_uint_t port);
109 size_t ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text,
110 size_t len, ngx_uint_t port);
111111 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
112112 ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
113113 ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
114114 size_t len);
115115 ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
116116 ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
117 ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
118 struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port);
117119
118120
119121 #endif /* _NGX_INET_H_INCLUDED_ */
1818 return NULL;
1919 }
2020
21 list->part.elts = ngx_palloc(pool, n * size);
22 if (list->part.elts == NULL) {
21 if (ngx_list_init(list, pool, n, size) != NGX_OK) {
2322 return NULL;
2423 }
25
26 list->part.nelts = 0;
27 list->part.next = NULL;
28 list->last = &list->part;
29 list->size = size;
30 list->nalloc = n;
31 list->pool = pool;
3224
3325 return list;
3426 }
99
1010
1111 static char *ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
12 static char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
13 static void ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log);
1214
1315
1416 static ngx_command_t ngx_errlog_commands[] = {
8587 #endif
8688 {
8789 #if (NGX_HAVE_VARIADIC_MACROS)
88 va_list args;
89 #endif
90 u_char *p, *last, *msg;
91 u_char errstr[NGX_MAX_ERROR_STR];
92
93 if (log->file->fd == NGX_INVALID_FILE) {
94 return;
95 }
90 va_list args;
91 #endif
92 u_char *p, *last, *msg;
93 u_char errstr[NGX_MAX_ERROR_STR];
94 ngx_uint_t wrote_stderr, debug_connection;
9695
9796 last = errstr + NGX_MAX_ERROR_STR;
9897
139138
140139 ngx_linefeed(p);
141140
142 (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
141 wrote_stderr = 0;
142 debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;
143
144 while (log) {
145
146 if (log->log_level < level && !debug_connection) {
147 break;
148 }
149
150 (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
151
152 if (log->file->fd == ngx_stderr) {
153 wrote_stderr = 1;
154 }
155
156 log = log->next;
157 }
143158
144159 if (!ngx_use_stderr
145160 || level > NGX_LOG_WARN
146 || log->file->fd == ngx_stderr)
161 || wrote_stderr)
147162 {
148163 return;
149164 }
347362 }
348363
349364
350 ngx_log_t *
351 ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name)
352 {
353 ngx_log_t *log;
354
355 log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t));
356 if (log == NULL) {
357 return NULL;
358 }
359
360 log->file = ngx_conf_open_file(cycle, name);
361 if (log->file == NULL) {
362 return NULL;
363 }
364
365 return log;
366 }
367
368
369 char *
365 ngx_int_t
366 ngx_log_open_default(ngx_cycle_t *cycle)
367 {
368 static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
369
370 if (cycle->new_log.file == NULL) {
371 cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);
372 if (cycle->new_log.file == NULL) {
373 return NGX_ERROR;
374 }
375
376 cycle->new_log.log_level = NGX_LOG_ERR;
377 }
378
379 return NGX_OK;
380 }
381
382
383 ngx_int_t
384 ngx_log_redirect_stderr(ngx_cycle_t *cycle)
385 {
386 ngx_fd_t fd;
387
388 if (cycle->log_use_stderr) {
389 return NGX_OK;
390 }
391
392 fd = cycle->log->file->fd;
393
394 if (fd != ngx_stderr) {
395 if (ngx_set_stderr(fd) == NGX_FILE_ERROR) {
396 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
397 ngx_set_stderr_n " failed");
398
399 return NGX_ERROR;
400 }
401 }
402
403 return NGX_OK;
404 }
405
406
407 static char *
370408 ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
371409 {
372410 ngx_uint_t i, n, d, found;
373411 ngx_str_t *value;
412
413 if (cf->args->nelts == 2) {
414 log->log_level = NGX_LOG_ERR;
415 return NGX_CONF_OK;
416 }
374417
375418 value = cf->args->elts;
376419
427470 static char *
428471 ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
429472 {
473 ngx_log_t *dummy;
474
475 dummy = &cf->cycle->new_log;
476
477 return ngx_log_set_log(cf, &dummy);
478 }
479
480
481 char *
482 ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head)
483 {
484 ngx_log_t *new_log;
430485 ngx_str_t *value, name;
431486
432 if (cf->cycle->new_log.file) {
433 return "is duplicate";
487 if (*head != NULL && (*head)->log_level == 0) {
488 new_log = *head;
489
490 } else {
491
492 new_log = ngx_pcalloc(cf->pool, sizeof(ngx_log_t));
493 if (new_log == NULL) {
494 return NGX_CONF_ERROR;
495 }
496
497 if (*head == NULL) {
498 *head = new_log;
499 }
434500 }
435501
436502 value = cf->args->elts;
437503
438504 if (ngx_strcmp(value[1].data, "stderr") == 0) {
439505 ngx_str_null(&name);
506 cf->cycle->log_use_stderr = 1;
440507
441508 } else {
442509 name = value[1];
443510 }
444511
445 cf->cycle->new_log.file = ngx_conf_open_file(cf->cycle, &name);
446 if (cf->cycle->new_log.file == NULL) {
447 return NULL;
448 }
449
450 if (cf->args->nelts == 2) {
451 cf->cycle->new_log.log_level = NGX_LOG_ERR;
452 return NGX_CONF_OK;
453 }
454
455 cf->cycle->new_log.log_level = 0;
456
457 return ngx_log_set_levels(cf, &cf->cycle->new_log);
458 }
512 new_log->file = ngx_conf_open_file(cf->cycle, &name);
513 if (new_log->file == NULL) {
514 return NGX_CONF_ERROR;
515 }
516
517 if (ngx_log_set_levels(cf, new_log) != NGX_CONF_OK) {
518 return NGX_CONF_ERROR;
519 }
520
521 if (*head != new_log) {
522 ngx_log_insert(*head, new_log);
523 }
524
525 return NGX_CONF_OK;
526 }
527
528
529 static void
530 ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log)
531 {
532 ngx_log_t tmp;
533
534 if (new_log->log_level > log->log_level) {
535
536 /*
537 * list head address is permanent, insert new log after
538 * head and swap its contents with head
539 */
540
541 tmp = *log;
542 *log = *new_log;
543 *new_log = tmp;
544
545 log->next = new_log;
546 return;
547 }
548
549 while (log->next) {
550 if (new_log->log_level > log->next->log_level) {
551 new_log->next = log->next;
552 log->next = new_log;
553 return;
554 }
555
556 log = log->next;
557 }
558
559 log->next = new_log;
560 }
6060 */
6161
6262 char *action;
63
64 ngx_log_t *next;
6365 };
6466
6567
219221 /*********************************/
220222
221223 ngx_log_t *ngx_log_init(u_char *prefix);
222 ngx_log_t *ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name);
223 char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
224224 void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
225225 void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);
226226 u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err);
227 ngx_int_t ngx_log_open_default(ngx_cycle_t *cycle);
228 ngx_int_t ngx_log_redirect_stderr(ngx_cycle_t *cycle);
229 char *ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head);
227230
228231
229232 /*
2424 #if (NGX_HAVE_OPENAT)
2525 static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
2626 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log);
27 #if (NGX_HAVE_O_PATH)
28 static ngx_int_t ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi,
29 ngx_log_t *log);
30 #endif
2731 #endif
2832 static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
2933 ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
123127
124128 if (cache->current) {
125129 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
126 "%d items still leave in open file cache",
130 "%ui items still leave in open file cache",
127131 cache->current);
128132 }
129133
516520 goto failed;
517521 }
518522
523 #if (NGX_HAVE_O_PATH)
524 if (ngx_file_o_path_info(fd, &fi, log) == NGX_ERROR) {
525 err = ngx_errno;
526 goto failed;
527 }
528 #else
519529 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
520530 err = ngx_errno;
521531 goto failed;
522532 }
533 #endif
523534
524535 if (fi.st_uid != atfi.st_uid) {
525536 err = NGX_ELOOP;
540551 return NGX_INVALID_FILE;
541552 }
542553
554
555 #if (NGX_HAVE_O_PATH)
556
557 static ngx_int_t
558 ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi, ngx_log_t *log)
559 {
560 static ngx_uint_t use_fstat = 1;
561
562 /*
563 * In Linux 2.6.39 the O_PATH flag was introduced that allows to obtain
564 * a descriptor without actually opening file or directory. It requires
565 * less permissions for path components, but till Linux 3.6 fstat() returns
566 * EBADF on such descriptors, and fstatat() with the AT_EMPTY_PATH flag
567 * should be used instead.
568 *
569 * Three scenarios are handled in this function:
570 *
571 * 1) The kernel is newer than 3.6 or fstat() with O_PATH support was
572 * backported by vendor. Then fstat() is used.
573 *
574 * 2) The kernel is newer than 2.6.39 but older than 3.6. In this case
575 * the first call of fstat() returns EBADF and we fallback to fstatat()
576 * with AT_EMPTY_PATH which was introduced at the same time as O_PATH.
577 *
578 * 3) The kernel is older than 2.6.39 but nginx was build with O_PATH
579 * support. Since descriptors are opened with O_PATH|O_RDONLY flags
580 * and O_PATH is ignored by the kernel then the O_RDONLY flag is
581 * actually used. In this case fstat() just works.
582 */
583
584 if (use_fstat) {
585 if (ngx_fd_info(fd, fi) != NGX_FILE_ERROR) {
586 return NGX_OK;
587 }
588
589 if (ngx_errno != NGX_EBADF) {
590 return NGX_ERROR;
591 }
592
593 ngx_log_error(NGX_LOG_NOTICE, log, 0,
594 "fstat(O_PATH) failed with EBADF, "
595 "switching to fstatat(AT_EMPTY_PATH)");
596
597 use_fstat = 0;
598 }
599
600 if (ngx_file_at_info(fd, "", fi, AT_EMPTY_PATH) != NGX_FILE_ERROR) {
601 return NGX_OK;
602 }
603
604 return NGX_ERROR;
605 }
606
543607 #endif
608
609 #endif /* NGX_HAVE_OPENAT */
544610
545611
546612 static ngx_fd_t
104104 }
105105 }
106106
107 pool->large = NULL;
108
109107 for (p = pool; p; p = p->d.next) {
110108 p->d.last = (u_char *) p + sizeof(ngx_pool_t);
111 }
109 p->d.failed = 0;
110 }
111
112 pool->current = pool;
113 pool->chain = NULL;
114 pool->large = NULL;
112115 }
113116
114117
0
1 /*
2 * Copyright (C) Roman Arutyunyan
3 * Copyright (C) Nginx, Inc.
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 u_char *
12 ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
13 {
14 size_t len;
15 u_char ch, *p, *addr;
16
17 p = buf;
18 len = last - buf;
19
20 if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
21 goto invalid;
22 }
23
24 p += 6;
25 len -= 6;
26
27 if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
28 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
29 "PROXY protocol unknown protocol");
30 p += 7;
31 goto skip;
32 }
33
34 if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
35 || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
36 {
37 goto invalid;
38 }
39
40 p += 5;
41 addr = p;
42
43 for ( ;; ) {
44 if (p == last) {
45 goto invalid;
46 }
47
48 ch = *p++;
49
50 if (ch == ' ') {
51 break;
52 }
53
54 if (ch != ':' && ch != '.'
55 && (ch < 'a' || ch > 'f')
56 && (ch < 'A' || ch > 'F')
57 && (ch < '0' || ch > '9'))
58 {
59 goto invalid;
60 }
61 }
62
63 len = p - addr - 1;
64 c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
65
66 if (c->proxy_protocol_addr.data == NULL) {
67 return NULL;
68 }
69
70 ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
71 c->proxy_protocol_addr.len = len;
72
73 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
74 "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr);
75
76 skip:
77
78 for ( /* void */ ; p < last - 1; p++) {
79 if (p[0] == CR && p[1] == LF) {
80 return p + 2;
81 }
82 }
83
84 invalid:
85
86 ngx_log_error(NGX_LOG_ERR, c->log, 0,
87 "broken header: \"%*s\"", (size_t) (last - buf), buf);
88
89 return NULL;
90 }
0
1 /*
2 * Copyright (C) Roman Arutyunyan
3 * Copyright (C) Nginx, Inc.
4 */
5
6
7 #ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
8 #define _NGX_PROXY_PROTOCOL_H_INCLUDED_
9
10
11 #include <ngx_config.h>
12 #include <ngx_core.h>
13
14
15 #define NGX_PROXY_PROTOCOL_MAX_HEADER 107
16
17
18 u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
19 u_char *last);
20
21
22 #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */
2525 u_char nns_lo;
2626 u_char nar_hi;
2727 u_char nar_lo;
28 } ngx_resolver_query_t;
28 } ngx_resolver_hdr_t;
2929
3030
3131 typedef struct {
6969 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
7070 size_t n);
7171 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
72 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);
72 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
73 ngx_uint_t nan, ngx_uint_t ans);
7374 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
7475 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
7576 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
8788 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
8889 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
8990 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
90 static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
91 ngx_uint_t n);
91 static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
92 ngx_resolver_node_t *rn, ngx_uint_t rotate);
9293 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
94
95 #if (NGX_HAVE_INET6)
96 static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
97 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
98 static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
99 struct in6_addr *addr, uint32_t hash);
100 #endif
93101
94102
95103 ngx_resolver_t *
133141 ngx_queue_init(&r->name_expire_queue);
134142 ngx_queue_init(&r->addr_expire_queue);
135143
144 #if (NGX_HAVE_INET6)
145 r->ipv6 = 1;
146
147 ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,
148 ngx_resolver_rbtree_insert_addr6_value);
149
150 ngx_queue_init(&r->addr6_resend_queue);
151
152 ngx_queue_init(&r->addr6_expire_queue);
153 #endif
154
136155 r->event->handler = ngx_resolver_resend_handler;
137156 r->event->data = r;
138157 r->event->log = &cf->cycle->new_log;
170189 continue;
171190 }
172191
192 #if (NGX_HAVE_INET6)
193 if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
194
195 if (ngx_strcmp(&names[i].data[5], "on") == 0) {
196 r->ipv6 = 1;
197
198 } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
199 r->ipv6 = 0;
200
201 } else {
202 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
203 "invalid parameter: %V", &names[i]);
204 return NULL;
205 }
206
207 continue;
208 }
209 #endif
210
173211 ngx_memzero(&u, sizeof(ngx_url_t));
174212
175213 u.url = names[i];
219257
220258 ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
221259
260 #if (NGX_HAVE_INET6)
261 ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
262 #endif
263
222264 if (r->event) {
223265 ngx_free(r->event);
224266 }
280322 temp->state = NGX_OK;
281323 temp->naddrs = 1;
282324 temp->addrs = &temp->addr;
283 temp->addr = addr;
325 temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
326 temp->addr.socklen = sizeof(struct sockaddr_in);
327 ngx_memzero(&temp->sin, sizeof(struct sockaddr_in));
328 temp->sin.sin_family = AF_INET;
329 temp->sin.sin_addr.s_addr = addr;
284330 temp->quick = 1;
285331
286332 return temp;
308354 ngx_resolver_t *r;
309355
310356 r = ctx->resolver;
357
358 if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
359 ctx->name.len--;
360 }
311361
312362 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
313363 "resolve: \"%V\"", &ctx->name);
410460 }
411461
412462
413 /* NGX_RESOLVE_A only */
414
415463 static ngx_int_t
416464 ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
417465 {
418466 uint32_t hash;
419 in_addr_t addr, *addrs;
420467 ngx_int_t rc;
421468 ngx_uint_t naddrs;
469 ngx_addr_t *addrs;
422470 ngx_resolver_ctx_t *next;
423471 ngx_resolver_node_t *rn;
424472
473 ngx_strlow(ctx->name.data, ctx->name.data, ctx->name.len);
474
425475 hash = ngx_crc32_short(ctx->name.data, ctx->name.len);
426476
427477 rn = ngx_resolver_lookup_name(r, &ctx->name, hash);
438488
439489 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
440490
441 naddrs = rn->naddrs;
491 naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
492 #if (NGX_HAVE_INET6)
493 naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
494 #endif
442495
443496 if (naddrs) {
444497
445 /* NGX_RESOLVE_A answer */
446
447 if (naddrs != 1) {
448 addr = 0;
449 addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
498 if (naddrs == 1 && rn->naddrs == 1) {
499 addrs = NULL;
500
501 } else {
502 addrs = ngx_resolver_export(r, rn, 1);
450503 if (addrs == NULL) {
451504 return NGX_ERROR;
452505 }
453
454 } else {
455 addr = rn->u.addr;
456 addrs = NULL;
457506 }
458507
459508 ctx->next = rn->waiting;
464513 do {
465514 ctx->state = NGX_OK;
466515 ctx->naddrs = naddrs;
467 ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
468 ctx->addr = addr;
516
517 if (addrs == NULL) {
518 ctx->addrs = &ctx->addr;
519 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
520 ctx->addr.socklen = sizeof(struct sockaddr_in);
521 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
522 ctx->sin.sin_family = AF_INET;
523 ctx->sin.sin_addr.s_addr = rn->u.addr;
524
525 } else {
526 ctx->addrs = addrs;
527 }
528
469529 next = ctx->next;
470530
471531 ctx->handler(ctx);
473533 ctx = next;
474534 } while (ctx);
475535
476 if (addrs) {
536 if (addrs != NULL) {
537 ngx_resolver_free(r, addrs->sockaddr);
477538 ngx_resolver_free(r, addrs);
478539 }
479540
523584 if (rn->query) {
524585 ngx_resolver_free_locked(r, rn->query);
525586 rn->query = NULL;
587 #if (NGX_HAVE_INET6)
588 rn->query6 = NULL;
589 #endif
526590 }
527591
528592 if (rn->cnlen) {
529593 ngx_resolver_free_locked(r, rn->u.cname);
530594 }
531595
532 if (rn->naddrs > 1) {
596 if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
533597 ngx_resolver_free_locked(r, rn->u.addrs);
534598 }
599
600 #if (NGX_HAVE_INET6)
601 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
602 ngx_resolver_free_locked(r, rn->u6.addrs6);
603 }
604 #endif
535605
536606 /* unlock alloc mutex */
537607
551621 rn->node.key = hash;
552622 rn->nlen = (u_short) ctx->name.len;
553623 rn->query = NULL;
624 #if (NGX_HAVE_INET6)
625 rn->query6 = NULL;
626 #endif
554627
555628 ngx_rbtree_insert(&r->name_rbtree, &rn->node);
556629 }
573646
574647 return NGX_OK;
575648 }
649
650 rn->naddrs = (u_short) -1;
651 #if (NGX_HAVE_INET6)
652 rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
653 #endif
576654
577655 if (ngx_resolver_send_query(r, rn) != NGX_OK) {
578656 goto failed;
600678
601679 ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
602680
681 rn->code = 0;
603682 rn->cnlen = 0;
604 rn->naddrs = 0;
605683 rn->valid = 0;
684 rn->ttl = NGX_MAX_UINT32_VALUE;
606685 rn->waiting = ctx;
607686
608687 ctx->state = NGX_AGAIN;
629708 ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
630709 {
631710 u_char *name;
711 in_addr_t addr;
712 ngx_queue_t *resend_queue, *expire_queue;
713 ngx_rbtree_t *tree;
632714 ngx_resolver_t *r;
715 struct sockaddr_in *sin;
633716 ngx_resolver_node_t *rn;
717 #if (NGX_HAVE_INET6)
718 uint32_t hash;
719 struct sockaddr_in6 *sin6;
720 #endif
721
722 #if (NGX_SUPPRESS_WARN)
723 addr = 0;
724 #if (NGX_HAVE_INET6)
725 hash = 0;
726 sin6 = NULL;
727 #endif
728 #endif
634729
635730 r = ctx->resolver;
636731
637 ctx->addr = ntohl(ctx->addr);
638
639 /* lock addr mutex */
640
641 rn = ngx_resolver_lookup_addr(r, ctx->addr);
732 switch (ctx->addr.sockaddr->sa_family) {
733
734 #if (NGX_HAVE_INET6)
735 case AF_INET6:
736 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
737 hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
738
739 /* lock addr mutex */
740
741 rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
742
743 tree = &r->addr6_rbtree;
744 resend_queue = &r->addr6_resend_queue;
745 expire_queue = &r->addr6_expire_queue;
746
747 break;
748 #endif
749
750 default: /* AF_INET */
751 sin = (struct sockaddr_in *) ctx->addr.sockaddr;
752 addr = ntohl(sin->sin_addr.s_addr);
753
754 /* lock addr mutex */
755
756 rn = ngx_resolver_lookup_addr(r, addr);
757
758 tree = &r->addr_rbtree;
759 resend_queue = &r->addr_resend_queue;
760 expire_queue = &r->addr_expire_queue;
761 }
642762
643763 if (rn) {
644764
650770
651771 rn->expire = ngx_time() + r->expire;
652772
653 ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
773 ngx_queue_insert_head(expire_queue, &rn->queue);
654774
655775 name = ngx_resolver_dup(r, rn->name, rn->nlen);
656776 if (name == NULL) {
686806
687807 ngx_resolver_free(r, rn->query);
688808 rn->query = NULL;
809 #if (NGX_HAVE_INET6)
810 rn->query6 = NULL;
811 #endif
689812
690813 } else {
691814 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
693816 goto failed;
694817 }
695818
696 rn->node.key = ctx->addr;
819 switch (ctx->addr.sockaddr->sa_family) {
820
821 #if (NGX_HAVE_INET6)
822 case AF_INET6:
823 rn->addr6 = sin6->sin6_addr;
824 rn->node.key = hash;
825 break;
826 #endif
827
828 default: /* AF_INET */
829 rn->node.key = addr;
830 }
831
697832 rn->query = NULL;
698
699 ngx_rbtree_insert(&r->addr_rbtree, &rn->node);
833 #if (NGX_HAVE_INET6)
834 rn->query6 = NULL;
835 #endif
836
837 ngx_rbtree_insert(tree, &rn->node);
700838 }
701839
702840 if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
703841 goto failed;
704842 }
843
844 rn->naddrs = (u_short) -1;
845 #if (NGX_HAVE_INET6)
846 rn->naddrs6 = (u_short) -1;
847 #endif
705848
706849 if (ngx_resolver_send_query(r, rn) != NGX_OK) {
707850 goto failed;
719862
720863 ngx_add_timer(ctx->event, ctx->timeout);
721864
722 if (ngx_queue_empty(&r->addr_resend_queue)) {
865 if (ngx_queue_empty(resend_queue)) {
723866 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
724867 }
725868
726869 rn->expire = ngx_time() + r->resend_timeout;
727870
728 ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue);
729
871 ngx_queue_insert_head(resend_queue, &rn->queue);
872
873 rn->code = 0;
730874 rn->cnlen = 0;
731 rn->naddrs = 0;
732875 rn->name = NULL;
733876 rn->nlen = 0;
734877 rn->valid = 0;
878 rn->ttl = NGX_MAX_UINT32_VALUE;
735879 rn->waiting = ctx;
736880
737881 /* unlock addr mutex */
743887 failed:
744888
745889 if (rn) {
746 ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
890 ngx_rbtree_delete(tree, &rn->node);
747891
748892 if (rn->query) {
749893 ngx_resolver_free(r, rn->query);
768912 ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
769913 {
770914 in_addr_t addr;
915 ngx_queue_t *expire_queue;
916 ngx_rbtree_t *tree;
771917 ngx_resolver_t *r;
772918 ngx_resolver_ctx_t *w, **p;
919 struct sockaddr_in *sin;
773920 ngx_resolver_node_t *rn;
921 #if (NGX_HAVE_INET6)
922 uint32_t hash;
923 struct sockaddr_in6 *sin6;
924 #endif
774925
775926 r = ctx->resolver;
927
928 switch (ctx->addr.sockaddr->sa_family) {
929
930 #if (NGX_HAVE_INET6)
931 case AF_INET6:
932 tree = &r->addr6_rbtree;
933 expire_queue = &r->addr6_expire_queue;
934 break;
935 #endif
936
937 default: /* AF_INET */
938 tree = &r->addr_rbtree;
939 expire_queue = &r->addr_expire_queue;
940 }
776941
777942 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
778943 "resolve addr done: %i", ctx->state);
785950
786951 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
787952
788 rn = ngx_resolver_lookup_addr(r, ctx->addr);
953 switch (ctx->addr.sockaddr->sa_family) {
954
955 #if (NGX_HAVE_INET6)
956 case AF_INET6:
957 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
958 hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
959 rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
960 break;
961 #endif
962
963 default: /* AF_INET */
964 sin = (struct sockaddr_in *) ctx->addr.sockaddr;
965 addr = ntohl(sin->sin_addr.s_addr);
966 rn = ngx_resolver_lookup_addr(r, addr);
967 }
789968
790969 if (rn) {
791970 p = &rn->waiting;
803982 }
804983 }
805984
806 addr = ntohl(ctx->addr);
807
808 ngx_log_error(NGX_LOG_ALERT, r->log, 0,
809 "could not cancel %ud.%ud.%ud.%ud resolving",
810 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
811 (addr >> 8) & 0xff, addr & 0xff);
985 {
986 u_char text[NGX_SOCKADDR_STRLEN];
987 ngx_str_t addrtext;
988
989 addrtext.data = text;
990 addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
991 text, NGX_SOCKADDR_STRLEN, 0);
992
993 ngx_log_error(NGX_LOG_ALERT, r->log, 0,
994 "could not cancel %V resolving", &addrtext);
995 }
812996 }
813997
814998 done:
815999
816 ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue);
1000 ngx_resolver_expire(r, tree, expire_queue);
8171001
8181002 /* unlock addr mutex */
8191003
8951079 uc->connection->read->resolver = 1;
8961080 }
8971081
898 n = ngx_send(uc->connection, rn->query, rn->qlen);
899
900 if (n == -1) {
901 return NGX_ERROR;
902 }
903
904 if ((size_t) n != (size_t) rn->qlen) {
905 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
906 return NGX_ERROR;
907 }
1082 if (rn->naddrs == (u_short) -1) {
1083 n = ngx_send(uc->connection, rn->query, rn->qlen);
1084
1085 if (n == -1) {
1086 return NGX_ERROR;
1087 }
1088
1089 if ((size_t) n != (size_t) rn->qlen) {
1090 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1091 return NGX_ERROR;
1092 }
1093 }
1094
1095 #if (NGX_HAVE_INET6)
1096 if (rn->query6 && rn->naddrs6 == (u_short) -1) {
1097 n = ngx_send(uc->connection, rn->query6, rn->qlen);
1098
1099 if (n == -1) {
1100 return NGX_ERROR;
1101 }
1102
1103 if ((size_t) n != (size_t) rn->qlen) {
1104 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1105 return NGX_ERROR;
1106 }
1107 }
1108 #endif
9081109
9091110 return NGX_OK;
9101111 }
9141115 ngx_resolver_resend_handler(ngx_event_t *ev)
9151116 {
9161117 time_t timer, atimer, ntimer;
1118 #if (NGX_HAVE_INET6)
1119 time_t a6timer;
1120 #endif
9171121 ngx_resolver_t *r;
9181122
9191123 r = ev->data;
9331137
9341138 /* unlock addr mutex */
9351139
936 if (ntimer == 0) {
1140 #if (NGX_HAVE_INET6)
1141
1142 /* lock addr6 mutex */
1143
1144 a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);
1145
1146 /* unlock addr6 mutex */
1147
1148 #endif
1149
1150 timer = ntimer;
1151
1152 if (timer == 0) {
9371153 timer = atimer;
9381154
939 } else if (atimer == 0) {
940 timer = ntimer;
941
942 } else {
943 timer = (atimer < ntimer) ? atimer : ntimer;
944 }
1155 } else if (atimer) {
1156 timer = ngx_min(timer, atimer);
1157 }
1158
1159 #if (NGX_HAVE_INET6)
1160
1161 if (timer == 0) {
1162 timer = a6timer;
1163
1164 } else if (a6timer) {
1165 timer = ngx_min(timer, a6timer);
1166 }
1167
1168 #endif
9451169
9461170 if (timer) {
9471171 ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
10201244 static void
10211245 ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
10221246 {
1023 char *err;
1024 size_t len;
1025 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1026 qtype, qclass;
1027 ngx_queue_t *q;
1028 ngx_resolver_qs_t *qs;
1029 ngx_resolver_node_t *rn;
1030 ngx_resolver_query_t *query;
1031
1032 if ((size_t) n < sizeof(ngx_resolver_query_t)) {
1247 char *err;
1248 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1249 qtype, qclass;
1250 #if (NGX_HAVE_INET6)
1251 ngx_uint_t qident6;
1252 #endif
1253 ngx_queue_t *q;
1254 ngx_resolver_qs_t *qs;
1255 ngx_resolver_hdr_t *response;
1256 ngx_resolver_node_t *rn;
1257
1258 if (n < sizeof(ngx_resolver_hdr_t)) {
10331259 goto short_response;
10341260 }
10351261
1036 query = (ngx_resolver_query_t *) buf;
1037
1038 ident = (query->ident_hi << 8) + query->ident_lo;
1039 flags = (query->flags_hi << 8) + query->flags_lo;
1040 nqs = (query->nqs_hi << 8) + query->nqs_lo;
1041 nan = (query->nan_hi << 8) + query->nan_lo;
1262 response = (ngx_resolver_hdr_t *) buf;
1263
1264 ident = (response->ident_hi << 8) + response->ident_lo;
1265 flags = (response->flags_hi << 8) + response->flags_lo;
1266 nqs = (response->nqs_hi << 8) + response->nqs_lo;
1267 nan = (response->nan_hi << 8) + response->nan_lo;
10421268
10431269 ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
10441270 "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
10451271 ident, flags, nqs, nan,
1046 (query->nns_hi << 8) + query->nns_lo,
1047 (query->nar_hi << 8) + query->nar_lo);
1048
1049 if (!(flags & 0x8000)) {
1272 (response->nns_hi << 8) + response->nns_lo,
1273 (response->nar_hi << 8) + response->nar_lo);
1274
1275 /* response to a standard query */
1276 if ((flags & 0xf870) != 0x8000) {
10501277 ngx_log_error(r->log_level, r->log, 0,
10511278 "invalid DNS response %ui fl:%04Xui", ident, flags);
10521279 return;
10531280 }
10541281
1055 code = flags & 0x7f;
1282 code = flags & 0xf;
10561283
10571284 if (code == NGX_RESOLVE_FORMERR) {
10581285
10661293 qident = (rn->query[0] << 8) + rn->query[1];
10671294
10681295 if (qident == ident) {
1069 ngx_log_error(r->log_level, r->log, 0,
1070 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1071 code, ngx_resolver_strerror(code), ident,
1072 rn->nlen, rn->name);
1073 return;
1074 }
1296 goto dns_error_name;
1297 }
1298
1299 #if (NGX_HAVE_INET6)
1300 if (rn->query6) {
1301 qident6 = (rn->query6[0] << 8) + rn->query6[1];
1302
1303 if (qident6 == ident) {
1304 goto dns_error_name;
1305 }
1306 }
1307 #endif
10751308 }
10761309
10771310 goto dns_error;
10861319 goto done;
10871320 }
10881321
1089 i = sizeof(ngx_resolver_query_t);
1322 i = sizeof(ngx_resolver_hdr_t);
10901323
10911324 while (i < (ngx_uint_t) n) {
10921325 if (buf[i] == '\0') {
10931326 goto found;
10941327 }
10951328
1096 len = buf[i];
1097 i += 1 + len;
1329 i += 1 + buf[i];
10981330 }
10991331
11001332 goto short_response;
11011333
11021334 found:
11031335
1104 if (i++ == 0) {
1336 if (i++ == sizeof(ngx_resolver_hdr_t)) {
11051337 err = "zero-length domain name in DNS response";
11061338 goto done;
11071339 }
11291361 switch (qtype) {
11301362
11311363 case NGX_RESOLVE_A:
1132
1133 ngx_resolver_process_a(r, buf, n, ident, code, nan,
1364 #if (NGX_HAVE_INET6)
1365 case NGX_RESOLVE_AAAA:
1366 #endif
1367
1368 ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
11341369 i + sizeof(ngx_resolver_qs_t));
11351370
11361371 break;
11511386
11521387 short_response:
11531388
1154 err = "short dns response";
1389 err = "short DNS response";
11551390
11561391 done:
11571392
11581393 ngx_log_error(r->log_level, r->log, 0, err);
11591394
1395 return;
1396
1397 dns_error_name:
1398
1399 ngx_log_error(r->log_level, r->log, 0,
1400 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1401 code, ngx_resolver_strerror(code), ident,
1402 rn->nlen, rn->name);
11601403 return;
11611404
11621405 dns_error:
11701413
11711414 static void
11721415 ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1173 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans)
1416 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
1417 ngx_uint_t nan, ngx_uint_t ans)
11741418 {
11751419 char *err;
11761420 u_char *cname;
11771421 size_t len;
11781422 int32_t ttl;
11791423 uint32_t hash;
1180 in_addr_t addr, *addrs;
1424 in_addr_t *addr;
11811425 ngx_str_t name;
1182 ngx_uint_t qtype, qident, naddrs, a, i, n, start;
1426 ngx_addr_t *addrs;
1427 ngx_uint_t type, class, qident, naddrs, a, i, n, start;
1428 #if (NGX_HAVE_INET6)
1429 struct in6_addr *addr6;
1430 #endif
11831431 ngx_resolver_an_t *an;
11841432 ngx_resolver_ctx_t *ctx, *next;
11851433 ngx_resolver_node_t *rn;
11861434
1187 if (ngx_resolver_copy(r, &name, buf, &buf[12], &buf[last]) != NGX_OK) {
1435 if (ngx_resolver_copy(r, &name, buf,
1436 buf + sizeof(ngx_resolver_hdr_t), buf + last)
1437 != NGX_OK)
1438 {
11881439 return;
11891440 }
11901441
11951446 /* lock name mutex */
11961447
11971448 rn = ngx_resolver_lookup_name(r, &name, hash);
1449
1450 if (rn == NULL) {
1451 ngx_log_error(r->log_level, r->log, 0,
1452 "unexpected response for %V", &name);
1453 ngx_resolver_free(r, name.data);
1454 goto failed;
1455 }
1456
1457 switch (qtype) {
1458
1459 #if (NGX_HAVE_INET6)
1460 case NGX_RESOLVE_AAAA:
1461
1462 if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
1463 ngx_log_error(r->log_level, r->log, 0,
1464 "unexpected response for %V", &name);
1465 ngx_resolver_free(r, name.data);
1466 goto failed;
1467 }
1468
1469 rn->naddrs6 = 0;
1470 qident = (rn->query6[0] << 8) + rn->query6[1];
1471
1472 break;
1473 #endif
1474
1475 default: /* NGX_RESOLVE_A */
1476
1477 if (rn->query == NULL || rn->naddrs != (u_short) -1) {
1478 ngx_log_error(r->log_level, r->log, 0,
1479 "unexpected response for %V", &name);
1480 ngx_resolver_free(r, name.data);
1481 goto failed;
1482 }
1483
1484 rn->naddrs = 0;
1485 qident = (rn->query[0] << 8) + rn->query[1];
1486 }
1487
1488 if (ident != qident) {
1489 ngx_log_error(r->log_level, r->log, 0,
1490 "wrong ident %ui response for %V, expect %ui",
1491 ident, &name, qident);
1492 ngx_resolver_free(r, name.data);
1493 goto failed;
1494 }
1495
1496 ngx_resolver_free(r, name.data);
1497
1498 if (code == 0 && rn->code) {
1499 code = rn->code;
1500 }
1501
1502 if (code == 0 && nan == 0) {
1503
1504 #if (NGX_HAVE_INET6)
1505 switch (qtype) {
1506
1507 case NGX_RESOLVE_AAAA:
1508
1509 if (rn->naddrs == (u_short) -1) {
1510 goto next;
1511 }
1512
1513 if (rn->naddrs) {
1514 goto export;
1515 }
1516
1517 break;
1518
1519 default: /* NGX_RESOLVE_A */
1520
1521 if (rn->naddrs6 == (u_short) -1) {
1522 goto next;
1523 }
1524
1525 if (rn->naddrs6) {
1526 goto export;
1527 }
1528 }
1529 #endif
1530
1531 code = NGX_RESOLVE_NXDOMAIN;
1532 }
1533
1534 if (code) {
1535
1536 #if (NGX_HAVE_INET6)
1537 switch (qtype) {
1538
1539 case NGX_RESOLVE_AAAA:
1540
1541 if (rn->naddrs == (u_short) -1) {
1542 rn->code = (u_char) code;
1543 goto next;
1544 }
1545
1546 break;
1547
1548 default: /* NGX_RESOLVE_A */
1549
1550 if (rn->naddrs6 == (u_short) -1) {
1551 rn->code = (u_char) code;
1552 goto next;
1553 }
1554 }
1555 #endif
1556
1557 next = rn->waiting;
1558 rn->waiting = NULL;
1559
1560 ngx_queue_remove(&rn->queue);
1561
1562 ngx_rbtree_delete(&r->name_rbtree, &rn->node);
1563
1564 ngx_resolver_free_node(r, rn);
1565
1566 /* unlock name mutex */
1567
1568 while (next) {
1569 ctx = next;
1570 ctx->state = code;
1571 next = ctx->next;
1572
1573 ctx->handler(ctx);
1574 }
1575
1576 return;
1577 }
1578
1579 i = ans;
1580 naddrs = 0;
1581 cname = NULL;
1582
1583 for (a = 0; a < nan; a++) {
1584
1585 start = i;
1586
1587 while (i < last) {
1588
1589 if (buf[i] & 0xc0) {
1590 i += 2;
1591 goto found;
1592 }
1593
1594 if (buf[i] == 0) {
1595 i++;
1596 goto test_length;
1597 }
1598
1599 i += 1 + buf[i];
1600 }
1601
1602 goto short_response;
1603
1604 test_length:
1605
1606 if (i - start < 2) {
1607 err = "invalid name in DNS response";
1608 goto invalid;
1609 }
1610
1611 found:
1612
1613 if (i + sizeof(ngx_resolver_an_t) >= last) {
1614 goto short_response;
1615 }
1616
1617 an = (ngx_resolver_an_t *) &buf[i];
1618
1619 type = (an->type_hi << 8) + an->type_lo;
1620 class = (an->class_hi << 8) + an->class_lo;
1621 len = (an->len_hi << 8) + an->len_lo;
1622 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
1623 + (an->ttl[2] << 8) + (an->ttl[3]);
1624
1625 if (class != 1) {
1626 ngx_log_error(r->log_level, r->log, 0,
1627 "unexpected RR class %ui", class);
1628 goto failed;
1629 }
1630
1631 if (ttl < 0) {
1632 ttl = 0;
1633 }
1634
1635 rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);
1636
1637 i += sizeof(ngx_resolver_an_t);
1638
1639 switch (type) {
1640
1641 case NGX_RESOLVE_A:
1642
1643 if (qtype != NGX_RESOLVE_A) {
1644 err = "unexpected A record in DNS response";
1645 goto invalid;
1646 }
1647
1648 if (len != 4) {
1649 err = "invalid A record in DNS response";
1650 goto invalid;
1651 }
1652
1653 if (i + 4 > last) {
1654 goto short_response;
1655 }
1656
1657 naddrs++;
1658
1659 break;
1660
1661 #if (NGX_HAVE_INET6)
1662 case NGX_RESOLVE_AAAA:
1663
1664 if (qtype != NGX_RESOLVE_AAAA) {
1665 err = "unexpected AAAA record in DNS response";
1666 goto invalid;
1667 }
1668
1669 if (len != 16) {
1670 err = "invalid AAAA record in DNS response";
1671 goto invalid;
1672 }
1673
1674 if (i + 16 > last) {
1675 goto short_response;
1676 }
1677
1678 naddrs++;
1679
1680 break;
1681 #endif
1682
1683 case NGX_RESOLVE_CNAME:
1684
1685 cname = &buf[i];
1686
1687 break;
1688
1689 case NGX_RESOLVE_DNAME:
1690
1691 break;
1692
1693 default:
1694
1695 ngx_log_error(r->log_level, r->log, 0,
1696 "unexpected RR type %ui", type);
1697 }
1698
1699 i += len;
1700 }
1701
1702 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
1703 "resolver naddrs:%ui cname:%p ttl:%uD",
1704 naddrs, cname, rn->ttl);
1705
1706 if (naddrs) {
1707
1708 switch (qtype) {
1709
1710 #if (NGX_HAVE_INET6)
1711 case NGX_RESOLVE_AAAA:
1712
1713 if (naddrs == 1) {
1714 addr6 = &rn->u6.addr6;
1715 rn->naddrs6 = 1;
1716
1717 } else {
1718 addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
1719 if (addr6 == NULL) {
1720 goto failed;
1721 }
1722
1723 rn->u6.addrs6 = addr6;
1724 rn->naddrs6 = (u_short) naddrs;
1725 }
1726
1727 #if (NGX_SUPPRESS_WARN)
1728 addr = NULL;
1729 #endif
1730
1731 break;
1732 #endif
1733
1734 default: /* NGX_RESOLVE_A */
1735
1736 if (naddrs == 1) {
1737 addr = &rn->u.addr;
1738 rn->naddrs = 1;
1739
1740 } else {
1741 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
1742 if (addr == NULL) {
1743 goto failed;
1744 }
1745
1746 rn->u.addrs = addr;
1747 rn->naddrs = (u_short) naddrs;
1748 }
1749
1750 #if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN)
1751 addr6 = NULL;
1752 #endif
1753 }
1754
1755 n = 0;
1756 i = ans;
1757
1758 for (a = 0; a < nan; a++) {
1759
1760 for ( ;; ) {
1761
1762 if (buf[i] & 0xc0) {
1763 i += 2;
1764 break;
1765 }
1766
1767 if (buf[i] == 0) {
1768 i++;
1769 break;
1770 }
1771
1772 i += 1 + buf[i];
1773 }
1774
1775 an = (ngx_resolver_an_t *) &buf[i];
1776
1777 type = (an->type_hi << 8) + an->type_lo;
1778 len = (an->len_hi << 8) + an->len_lo;
1779
1780 i += sizeof(ngx_resolver_an_t);
1781
1782 if (type == NGX_RESOLVE_A) {
1783
1784 addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1785 + (buf[i + 2] << 8) + (buf[i + 3]));
1786
1787 if (++n == naddrs) {
1788
1789 #if (NGX_HAVE_INET6)
1790 if (rn->naddrs6 == (u_short) -1) {
1791 goto next;
1792 }
1793 #endif
1794
1795 break;
1796 }
1797 }
1798
1799 #if (NGX_HAVE_INET6)
1800 else if (type == NGX_RESOLVE_AAAA) {
1801
1802 ngx_memcpy(addr6[n].s6_addr, &buf[i], 16);
1803
1804 if (++n == naddrs) {
1805
1806 if (rn->naddrs == (u_short) -1) {
1807 goto next;
1808 }
1809
1810 break;
1811 }
1812 }
1813 #endif
1814
1815 i += len;
1816 }
1817 }
1818
1819 if (rn->naddrs != (u_short) -1
1820 #if (NGX_HAVE_INET6)
1821 && rn->naddrs6 != (u_short) -1
1822 #endif
1823 && rn->naddrs
1824 #if (NGX_HAVE_INET6)
1825 + rn->naddrs6
1826 #endif
1827 > 0)
1828 {
1829
1830 #if (NGX_HAVE_INET6)
1831 export:
1832 #endif
1833
1834 naddrs = rn->naddrs;
1835 #if (NGX_HAVE_INET6)
1836 naddrs += rn->naddrs6;
1837 #endif
1838
1839 if (naddrs == 1 && rn->naddrs == 1) {
1840 addrs = NULL;
1841
1842 } else {
1843 addrs = ngx_resolver_export(r, rn, 0);
1844 if (addrs == NULL) {
1845 goto failed;
1846 }
1847 }
1848
1849 ngx_queue_remove(&rn->queue);
1850
1851 rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
1852 rn->expire = ngx_time() + r->expire;
1853
1854 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1855
1856 next = rn->waiting;
1857 rn->waiting = NULL;
1858
1859 /* unlock name mutex */
1860
1861 while (next) {
1862 ctx = next;
1863 ctx->state = NGX_OK;
1864 ctx->naddrs = naddrs;
1865
1866 if (addrs == NULL) {
1867 ctx->addrs = &ctx->addr;
1868 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
1869 ctx->addr.socklen = sizeof(struct sockaddr_in);
1870 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
1871 ctx->sin.sin_family = AF_INET;
1872 ctx->sin.sin_addr.s_addr = rn->u.addr;
1873
1874 } else {
1875 ctx->addrs = addrs;
1876 }
1877
1878 next = ctx->next;
1879
1880 ctx->handler(ctx);
1881 }
1882
1883 if (addrs != NULL) {
1884 ngx_resolver_free(r, addrs->sockaddr);
1885 ngx_resolver_free(r, addrs);
1886 }
1887
1888 ngx_resolver_free(r, rn->query);
1889 rn->query = NULL;
1890 #if (NGX_HAVE_INET6)
1891 rn->query6 = NULL;
1892 #endif
1893
1894 return;
1895 }
1896
1897 if (cname) {
1898
1899 /* CNAME only */
1900
1901 if (rn->naddrs == (u_short) -1
1902 #if (NGX_HAVE_INET6)
1903 || rn->naddrs6 == (u_short) -1
1904 #endif
1905 )
1906 {
1907 goto next;
1908 }
1909
1910 if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
1911 goto failed;
1912 }
1913
1914 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
1915 "resolver cname:\"%V\"", &name);
1916
1917 ngx_queue_remove(&rn->queue);
1918
1919 rn->cnlen = (u_short) name.len;
1920 rn->u.cname = name.data;
1921
1922 rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
1923 rn->expire = ngx_time() + r->expire;
1924
1925 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1926
1927 ctx = rn->waiting;
1928 rn->waiting = NULL;
1929
1930 if (ctx) {
1931 ctx->name = name;
1932
1933 (void) ngx_resolve_name_locked(r, ctx);
1934 }
1935
1936 ngx_resolver_free(r, rn->query);
1937 rn->query = NULL;
1938 #if (NGX_HAVE_INET6)
1939 rn->query6 = NULL;
1940 #endif
1941
1942 /* unlock name mutex */
1943
1944 return;
1945 }
1946
1947 ngx_log_error(r->log_level, r->log, 0,
1948 "no A or CNAME types in DNS response");
1949 return;
1950
1951 short_response:
1952
1953 err = "short DNS response";
1954
1955 invalid:
1956
1957 /* unlock name mutex */
1958
1959 ngx_log_error(r->log_level, r->log, 0, err);
1960
1961 return;
1962
1963 failed:
1964
1965 next:
1966
1967 /* unlock name mutex */
1968
1969 return;
1970 }
1971
1972
1973 static void
1974 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1975 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
1976 {
1977 char *err;
1978 size_t len;
1979 u_char text[NGX_SOCKADDR_STRLEN];
1980 in_addr_t addr;
1981 int32_t ttl;
1982 ngx_int_t octet;
1983 ngx_str_t name;
1984 ngx_uint_t i, mask, qident, class;
1985 ngx_queue_t *expire_queue;
1986 ngx_rbtree_t *tree;
1987 ngx_resolver_an_t *an;
1988 ngx_resolver_ctx_t *ctx, *next;
1989 ngx_resolver_node_t *rn;
1990 #if (NGX_HAVE_INET6)
1991 uint32_t hash;
1992 ngx_int_t digit;
1993 struct in6_addr addr6;
1994 #endif
1995
1996 if (ngx_resolver_copy(r, NULL, buf,
1997 buf + sizeof(ngx_resolver_hdr_t), buf + n)
1998 != NGX_OK)
1999 {
2000 return;
2001 }
2002
2003 /* AF_INET */
2004
2005 addr = 0;
2006 i = sizeof(ngx_resolver_hdr_t);
2007
2008 for (mask = 0; mask < 32; mask += 8) {
2009 len = buf[i++];
2010
2011 octet = ngx_atoi(&buf[i], len);
2012 if (octet == NGX_ERROR || octet > 255) {
2013 goto invalid_in_addr_arpa;
2014 }
2015
2016 addr += octet << mask;
2017 i += len;
2018 }
2019
2020 if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
2021 i += sizeof("\7in-addr\4arpa");
2022
2023 /* lock addr mutex */
2024
2025 rn = ngx_resolver_lookup_addr(r, addr);
2026
2027 tree = &r->addr_rbtree;
2028 expire_queue = &r->addr_expire_queue;
2029
2030 addr = htonl(addr);
2031 name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN);
2032 name.data = text;
2033
2034 goto valid;
2035 }
2036
2037 invalid_in_addr_arpa:
2038
2039 #if (NGX_HAVE_INET6)
2040
2041 i = sizeof(ngx_resolver_hdr_t);
2042
2043 for (octet = 15; octet >= 0; octet--) {
2044 if (buf[i++] != '\1') {
2045 goto invalid_ip6_arpa;
2046 }
2047
2048 digit = ngx_hextoi(&buf[i++], 1);
2049 if (digit == NGX_ERROR) {
2050 goto invalid_ip6_arpa;
2051 }
2052
2053 addr6.s6_addr[octet] = (u_char) digit;
2054
2055 if (buf[i++] != '\1') {
2056 goto invalid_ip6_arpa;
2057 }
2058
2059 digit = ngx_hextoi(&buf[i++], 1);
2060 if (digit == NGX_ERROR) {
2061 goto invalid_ip6_arpa;
2062 }
2063
2064 addr6.s6_addr[octet] += (u_char) (digit * 16);
2065 }
2066
2067 if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
2068 i += sizeof("\3ip6\4arpa");
2069
2070 /* lock addr mutex */
2071
2072 hash = ngx_crc32_short(addr6.s6_addr, 16);
2073 rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
2074
2075 tree = &r->addr6_rbtree;
2076 expire_queue = &r->addr6_expire_queue;
2077
2078 name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN);
2079 name.data = text;
2080
2081 goto valid;
2082 }
2083
2084 invalid_ip6_arpa:
2085 #endif
2086
2087 ngx_log_error(r->log_level, r->log, 0,
2088 "invalid in-addr.arpa or ip6.arpa name in DNS response");
2089 return;
2090
2091 valid:
11982092
11992093 if (rn == NULL || rn->query == NULL) {
12002094 ngx_log_error(r->log_level, r->log, 0,
12112105 goto failed;
12122106 }
12132107
1214 ngx_resolver_free(r, name.data);
1215
12162108 if (code == 0 && nan == 0) {
1217 code = 3; /* NXDOMAIN */
2109 code = NGX_RESOLVE_NXDOMAIN;
12182110 }
12192111
12202112 if (code) {
12232115
12242116 ngx_queue_remove(&rn->queue);
12252117
1226 ngx_rbtree_delete(&r->name_rbtree, &rn->node);
2118 ngx_rbtree_delete(tree, &rn->node);
12272119
12282120 ngx_resolver_free_node(r, rn);
12292121
1230 /* unlock name mutex */
2122 /* unlock addr mutex */
12312123
12322124 while (next) {
1233 ctx = next;
1234 ctx->state = code;
1235 next = ctx->next;
1236
1237 ctx->handler(ctx);
2125 ctx = next;
2126 ctx->state = code;
2127 next = ctx->next;
2128
2129 ctx->handler(ctx);
12382130 }
12392131
12402132 return;
12412133 }
12422134
1243 i = ans;
1244 naddrs = 0;
1245 addr = 0;
1246 addrs = NULL;
1247 cname = NULL;
1248 qtype = 0;
1249 ttl = 0;
1250
1251 for (a = 0; a < nan; a++) {
1252
1253 start = i;
1254
1255 while (i < last) {
1256
1257 if (buf[i] & 0xc0) {
1258 i += 2;
1259 goto found;
1260 }
1261
1262 if (buf[i] == 0) {
1263 i++;
1264 goto test_length;
1265 }
1266
1267 i += 1 + buf[i];
1268 }
1269
2135 i += sizeof(ngx_resolver_qs_t);
2136
2137 if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
12702138 goto short_response;
1271
1272 test_length:
1273
1274 if (i - start < 2) {
1275 err = "invalid name in dns response";
1276 goto invalid;
1277 }
1278
1279 found:
1280
1281 if (i + sizeof(ngx_resolver_an_t) >= last) {
1282 goto short_response;
1283 }
1284
1285 an = (ngx_resolver_an_t *) &buf[i];
1286
1287 qtype = (an->type_hi << 8) + an->type_lo;
1288 len = (an->len_hi << 8) + an->len_lo;
1289 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
1290 + (an->ttl[2] << 8) + (an->ttl[3]);
1291
1292 if (ttl < 0) {
1293 ttl = 0;
1294 }
1295
1296 if (qtype == NGX_RESOLVE_A) {
1297
1298 i += sizeof(ngx_resolver_an_t);
1299
1300 if (i + len > last) {
1301 goto short_response;
1302 }
1303
1304 addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1305 + (buf[i + 2] << 8) + (buf[i + 3]));
1306
1307 naddrs++;
1308
1309 i += len;
1310
1311 } else if (qtype == NGX_RESOLVE_CNAME) {
1312 cname = &buf[i] + sizeof(ngx_resolver_an_t);
1313 i += sizeof(ngx_resolver_an_t) + len;
1314
1315 } else if (qtype == NGX_RESOLVE_DNAME) {
1316 i += sizeof(ngx_resolver_an_t) + len;
1317
1318 } else {
1319 ngx_log_error(r->log_level, r->log, 0,
1320 "unexpected qtype %ui", qtype);
1321 }
1322 }
1323
1324 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
1325 "resolver naddrs:%ui cname:%p ttl:%d",
1326 naddrs, cname, ttl);
1327
1328 if (naddrs) {
1329
1330 if (naddrs == 1) {
1331 rn->u.addr = addr;
1332
1333 } else {
1334
1335 addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
1336 if (addrs == NULL) {
1337 return;
1338 }
1339
1340 n = 0;
1341 i = ans;
1342
1343 for (a = 0; a < nan; a++) {
1344
1345 for ( ;; ) {
1346
1347 if (buf[i] & 0xc0) {
1348 i += 2;
1349 goto ok;
1350 }
1351
1352 if (buf[i] == 0) {
1353 i++;
1354 goto ok;
1355 }
1356
1357 i += 1 + buf[i];
1358 }
1359
1360 ok:
1361
1362 an = (ngx_resolver_an_t *) &buf[i];
1363
1364 qtype = (an->type_hi << 8) + an->type_lo;
1365 len = (an->len_hi << 8) + an->len_lo;
1366
1367 i += sizeof(ngx_resolver_an_t);
1368
1369 if (qtype == NGX_RESOLVE_A) {
1370
1371 addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1372 + (buf[i + 2] << 8) + (buf[i + 3]));
1373
1374 if (n == naddrs) {
1375 break;
1376 }
1377 }
1378
1379 i += len;
1380 }
1381
1382 rn->u.addrs = addrs;
1383
1384 addrs = ngx_resolver_dup(r, rn->u.addrs,
1385 naddrs * sizeof(in_addr_t));
1386 if (addrs == NULL) {
1387 return;
1388 }
1389 }
1390
1391 rn->naddrs = (u_short) naddrs;
1392
1393 ngx_queue_remove(&rn->queue);
1394
1395 rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
1396 rn->expire = ngx_time() + r->expire;
1397
1398 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1399
1400 next = rn->waiting;
1401 rn->waiting = NULL;
1402
1403 /* unlock name mutex */
1404
1405 while (next) {
1406 ctx = next;
1407 ctx->state = NGX_OK;
1408 ctx->naddrs = naddrs;
1409 ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
1410 ctx->addr = addr;
1411 next = ctx->next;
1412
1413 ctx->handler(ctx);
1414 }
1415
1416 if (naddrs > 1) {
1417 ngx_resolver_free(r, addrs);
1418 }
1419
1420 ngx_resolver_free(r, rn->query);
1421 rn->query = NULL;
1422
1423 return;
1424
1425 } else if (cname) {
1426
1427 /* CNAME only */
1428
1429 if (ngx_resolver_copy(r, &name, buf, cname, &buf[last]) != NGX_OK) {
1430 return;
1431 }
1432
1433 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
1434 "resolver cname:\"%V\"", &name);
1435
1436 ngx_queue_remove(&rn->queue);
1437
1438 rn->cnlen = (u_short) name.len;
1439 rn->u.cname = name.data;
1440
1441 rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
1442 rn->expire = ngx_time() + r->expire;
1443
1444 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1445
1446 ctx = rn->waiting;
1447 rn->waiting = NULL;
1448
1449 if (ctx) {
1450 ctx->name = name;
1451
1452 (void) ngx_resolve_name_locked(r, ctx);
1453 }
1454
1455 ngx_resolver_free(r, rn->query);
1456 rn->query = NULL;
1457
1458 return;
1459 }
1460
1461 ngx_log_error(r->log_level, r->log, 0,
1462 "no A or CNAME types in DNS responses, unknown query type: %ui",
1463 qtype);
1464 return;
1465
1466 short_response:
1467
1468 err = "short dns response";
1469
1470 invalid:
1471
1472 /* unlock name mutex */
1473
1474 ngx_log_error(r->log_level, r->log, 0, err);
1475
1476 return;
1477
1478 failed:
1479
1480 /* unlock name mutex */
1481
1482 ngx_resolver_free(r, name.data);
1483
1484 return;
1485 }
1486
1487
1488 static void
1489 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
1490 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
1491 {
1492 char *err;
1493 size_t len;
1494 in_addr_t addr;
1495 int32_t ttl;
1496 ngx_int_t digit;
1497 ngx_str_t name;
1498 ngx_uint_t i, mask, qident;
1499 ngx_resolver_an_t *an;
1500 ngx_resolver_ctx_t *ctx, *next;
1501 ngx_resolver_node_t *rn;
1502
1503 if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) != NGX_OK) {
1504 goto invalid_in_addr_arpa;
1505 }
1506
1507 addr = 0;
1508 i = 12;
1509
1510 for (mask = 0; mask < 32; mask += 8) {
1511 len = buf[i++];
1512
1513 digit = ngx_atoi(&buf[i], len);
1514 if (digit == NGX_ERROR || digit > 255) {
1515 goto invalid_in_addr_arpa;
1516 }
1517
1518 addr += digit << mask;
1519 i += len;
1520 }
1521
1522 if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) {
1523 goto invalid_in_addr_arpa;
1524 }
1525
1526 /* lock addr mutex */
1527
1528 rn = ngx_resolver_lookup_addr(r, addr);
1529
1530 if (rn == NULL || rn->query == NULL) {
1531 ngx_log_error(r->log_level, r->log, 0,
1532 "unexpected response for %ud.%ud.%ud.%ud",
1533 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
1534 (addr >> 8) & 0xff, addr & 0xff);
1535 goto failed;
1536 }
1537
1538 qident = (rn->query[0] << 8) + rn->query[1];
1539
1540 if (ident != qident) {
1541 ngx_log_error(r->log_level, r->log, 0,
1542 "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",
1543 ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff,
1544 (addr >> 8) & 0xff, addr & 0xff, qident);
1545 goto failed;
1546 }
1547
1548 if (code == 0 && nan == 0) {
1549 code = 3; /* NXDOMAIN */
1550 }
1551
1552 if (code) {
1553 next = rn->waiting;
1554 rn->waiting = NULL;
1555
1556 ngx_queue_remove(&rn->queue);
1557
1558 ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
1559
1560 ngx_resolver_free_node(r, rn);
1561
1562 /* unlock addr mutex */
1563
1564 while (next) {
1565 ctx = next;
1566 ctx->state = code;
1567 next = ctx->next;
1568
1569 ctx->handler(ctx);
1570 }
1571
1572 return;
1573 }
1574
1575 i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);
1576
1577 if (i + 2 + sizeof(ngx_resolver_an_t) > (ngx_uint_t) n) {
1578 goto short_response;
1579 }
1580
1581 /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */
1582
1583 if (buf[i] != 0xc0 || buf[i + 1] != 0x0c) {
1584 err = "invalid in-addr.arpa name in DNS response";
2139 }
2140
2141 /* compression pointer to *.arpa */
2142
2143 if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
2144 err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
15852145 goto invalid;
15862146 }
15872147
15882148 an = (ngx_resolver_an_t *) &buf[i + 2];
15892149
2150 class = (an->class_hi << 8) + an->class_lo;
15902151 len = (an->len_hi << 8) + an->len_lo;
15912152 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
15922153 + (an->ttl[2] << 8) + (an->ttl[3]);
15932154
2155 if (class != 1) {
2156 ngx_log_error(r->log_level, r->log, 0,
2157 "unexpected RR class %ui", class);
2158 goto failed;
2159 }
2160
15942161 if (ttl < 0) {
15952162 ttl = 0;
15962163 }
15982165 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
15992166 "resolver qt:%ui cl:%ui len:%uz",
16002167 (an->type_hi << 8) + an->type_lo,
1601 (an->class_hi << 8) + an->class_lo, len);
2168 class, len);
16022169
16032170 i += 2 + sizeof(ngx_resolver_an_t);
16042171
1605 if (i + len > (ngx_uint_t) n) {
2172 if (i + len > n) {
16062173 goto short_response;
16072174 }
16082175
1609 if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) != NGX_OK) {
1610 return;
2176 if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
2177 goto failed;
16112178 }
16122179
16132180 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);
16332200 rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
16342201 rn->expire = ngx_time() + r->expire;
16352202
1636 ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
2203 ngx_queue_insert_head(expire_queue, &rn->queue);
16372204
16382205 next = rn->waiting;
16392206 rn->waiting = NULL;
16412208 /* unlock addr mutex */
16422209
16432210 while (next) {
1644 ctx = next;
1645 ctx->state = NGX_OK;
1646 ctx->name = name;
1647 next = ctx->next;
1648
1649 ctx->handler(ctx);
2211 ctx = next;
2212 ctx->state = NGX_OK;
2213 ctx->name = name;
2214 next = ctx->next;
2215
2216 ctx->handler(ctx);
16502217 }
16512218
16522219 ngx_resolver_free(r, name.data);
16532220
1654 return;
1655
1656 invalid_in_addr_arpa:
1657
1658 ngx_log_error(r->log_level, r->log, 0,
1659 "invalid in-addr.arpa name in DNS response");
16602221 return;
16612222
16622223 short_response:
17492310
17502311 return NULL;
17512312 }
2313
2314
2315 #if (NGX_HAVE_INET6)
2316
2317 static ngx_resolver_node_t *
2318 ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
2319 uint32_t hash)
2320 {
2321 ngx_int_t rc;
2322 ngx_rbtree_node_t *node, *sentinel;
2323 ngx_resolver_node_t *rn;
2324
2325 node = r->addr6_rbtree.root;
2326 sentinel = r->addr6_rbtree.sentinel;
2327
2328 while (node != sentinel) {
2329
2330 if (hash < node->key) {
2331 node = node->left;
2332 continue;
2333 }
2334
2335 if (hash > node->key) {
2336 node = node->right;
2337 continue;
2338 }
2339
2340 /* hash == node->key */
2341
2342 rn = (ngx_resolver_node_t *) node;
2343
2344 rc = ngx_memcmp(addr, &rn->addr6, 16);
2345
2346 if (rc == 0) {
2347 return rn;
2348 }
2349
2350 node = (rc < 0) ? node->left : node->right;
2351 }
2352
2353 /* not found */
2354
2355 return NULL;
2356 }
2357
2358 #endif
17522359
17532360
17542361 static void
17922399 }
17932400
17942401
2402 #if (NGX_HAVE_INET6)
2403
2404 static void
2405 ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
2406 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
2407 {
2408 ngx_rbtree_node_t **p;
2409 ngx_resolver_node_t *rn, *rn_temp;
2410
2411 for ( ;; ) {
2412
2413 if (node->key < temp->key) {
2414
2415 p = &temp->left;
2416
2417 } else if (node->key > temp->key) {
2418
2419 p = &temp->right;
2420
2421 } else { /* node->key == temp->key */
2422
2423 rn = (ngx_resolver_node_t *) node;
2424 rn_temp = (ngx_resolver_node_t *) temp;
2425
2426 p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
2427 < 0) ? &temp->left : &temp->right;
2428 }
2429
2430 if (*p == sentinel) {
2431 break;
2432 }
2433
2434 temp = *p;
2435 }
2436
2437 *p = node;
2438 node->parent = temp;
2439 node->left = sentinel;
2440 node->right = sentinel;
2441 ngx_rbt_red(node);
2442 }
2443
2444 #endif
2445
2446
17952447 static ngx_int_t
17962448 ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
17972449 {
1798 u_char *p, *s;
1799 size_t len, nlen;
1800 ngx_uint_t ident;
1801 ngx_resolver_qs_t *qs;
1802 ngx_resolver_query_t *query;
2450 u_char *p, *s;
2451 size_t len, nlen;
2452 ngx_uint_t ident;
2453 #if (NGX_HAVE_INET6)
2454 ngx_resolver_t *r;
2455 #endif
2456 ngx_resolver_qs_t *qs;
2457 ngx_resolver_hdr_t *query;
18032458
18042459 nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;
18052460
1806 len = sizeof(ngx_resolver_query_t) + nlen + sizeof(ngx_resolver_qs_t);
1807
2461 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
2462
2463 #if (NGX_HAVE_INET6)
2464 r = ctx->resolver;
2465
2466 p = ngx_resolver_alloc(ctx->resolver, r->ipv6 ? len * 2 : len);
2467 #else
18082468 p = ngx_resolver_alloc(ctx->resolver, len);
2469 #endif
18092470 if (p == NULL) {
18102471 return NGX_ERROR;
18112472 }
18132474 rn->qlen = (u_short) len;
18142475 rn->query = p;
18152476
1816 query = (ngx_resolver_query_t *) p;
2477 #if (NGX_HAVE_INET6)
2478 if (r->ipv6) {
2479 rn->query6 = p + len;
2480 }
2481 #endif
2482
2483 query = (ngx_resolver_hdr_t *) p;
18172484
18182485 ident = ngx_random();
18192486
18202487 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
1821 "resolve: \"%V\" %i", &ctx->name, ident & 0xffff);
2488 "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff);
18222489
18232490 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
18242491 query->ident_lo = (u_char) (ident & 0xff);
18322499 query->nns_hi = 0; query->nns_lo = 0;
18332500 query->nar_hi = 0; query->nar_lo = 0;
18342501
1835 p += sizeof(ngx_resolver_query_t) + nlen;
2502 p += sizeof(ngx_resolver_hdr_t) + nlen;
18362503
18372504 qs = (ngx_resolver_qs_t *) p;
18382505
18392506 /* query type */
1840 qs->type_hi = 0; qs->type_lo = (u_char) ctx->type;
1841
1842 /* IP query class */
2507 qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A;
2508
2509 /* IN query class */
18432510 qs->class_hi = 0; qs->class_lo = 1;
18442511
18452512 /* convert "www.example.com" to "\3www\7example\3com\0" */
18752542
18762543 *p = (u_char) len;
18772544
2545 #if (NGX_HAVE_INET6)
2546 if (!r->ipv6) {
2547 return NGX_OK;
2548 }
2549
2550 p = rn->query6;
2551
2552 ngx_memcpy(p, rn->query, rn->qlen);
2553
2554 query = (ngx_resolver_hdr_t *) p;
2555
2556 ident = ngx_random();
2557
2558 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
2559 "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff);
2560
2561 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
2562 query->ident_lo = (u_char) (ident & 0xff);
2563
2564 p += sizeof(ngx_resolver_hdr_t) + nlen;
2565
2566 qs = (ngx_resolver_qs_t *) p;
2567
2568 qs->type_lo = NGX_RESOLVE_AAAA;
2569 #endif
2570
18782571 return NGX_OK;
18792572 }
18802573
1881
1882 /* AF_INET only */
18832574
18842575 static ngx_int_t
18852576 ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
18862577 {
1887 u_char *p, *d;
1888 size_t len;
1889 ngx_int_t n;
1890 ngx_uint_t ident;
1891 ngx_resolver_query_t *query;
1892
1893 len = sizeof(ngx_resolver_query_t)
1894 + sizeof(".255.255.255.255.in-addr.arpa.") - 1
1895 + sizeof(ngx_resolver_qs_t);
2578 u_char *p, *d;
2579 size_t len;
2580 in_addr_t addr;
2581 ngx_int_t n;
2582 ngx_uint_t ident;
2583 ngx_resolver_hdr_t *query;
2584 struct sockaddr_in *sin;
2585 #if (NGX_HAVE_INET6)
2586 struct sockaddr_in6 *sin6;
2587 #endif
2588
2589 switch (ctx->addr.sockaddr->sa_family) {
2590
2591 #if (NGX_HAVE_INET6)
2592 case AF_INET6:
2593 len = sizeof(ngx_resolver_hdr_t)
2594 + 64 + sizeof(".ip6.arpa.") - 1
2595 + sizeof(ngx_resolver_qs_t);
2596
2597 break;
2598 #endif
2599
2600 default: /* AF_INET */
2601 len = sizeof(ngx_resolver_hdr_t)
2602 + sizeof(".255.255.255.255.in-addr.arpa.") - 1
2603 + sizeof(ngx_resolver_qs_t);
2604 }
18962605
18972606 p = ngx_resolver_alloc(ctx->resolver, len);
18982607 if (p == NULL) {
19002609 }
19012610
19022611 rn->query = p;
1903 query = (ngx_resolver_query_t *) p;
2612 query = (ngx_resolver_hdr_t *) p;
19042613
19052614 ident = ngx_random();
19062615
19162625 query->nns_hi = 0; query->nns_lo = 0;
19172626 query->nar_hi = 0; query->nar_lo = 0;
19182627
1919 p += sizeof(ngx_resolver_query_t);
1920
1921 for (n = 0; n < 32; n += 8) {
1922 d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
1923 *p = (u_char) (d - &p[1]);
1924 p = d;
1925 }
1926
1927 /* query type "PTR", IP query class */
1928 ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);
1929
1930 rn->qlen = (u_short)
1931 (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t)
1932 - rn->query);
2628 p += sizeof(ngx_resolver_hdr_t);
2629
2630 switch (ctx->addr.sockaddr->sa_family) {
2631
2632 #if (NGX_HAVE_INET6)
2633 case AF_INET6:
2634 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
2635
2636 for (n = 15; n >= 0; n--) {
2637 p = ngx_sprintf(p, "\1%xd\1%xd",
2638 sin6->sin6_addr.s6_addr[n] & 0xf,
2639 (sin6->sin6_addr.s6_addr[n] >> 4) & 0xf);
2640 }
2641
2642 p = ngx_cpymem(p, "\3ip6\4arpa\0", 10);
2643
2644 break;
2645 #endif
2646
2647 default: /* AF_INET */
2648
2649 sin = (struct sockaddr_in *) ctx->addr.sockaddr;
2650 addr = ntohl(sin->sin_addr.s_addr);
2651
2652 for (n = 0; n < 32; n += 8) {
2653 d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff);
2654 *p = (u_char) (d - &p[1]);
2655 p = d;
2656 }
2657
2658 p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14);
2659 }
2660
2661 /* query type "PTR", IN query class */
2662 p = ngx_cpymem(p, "\0\14\0\1", 4);
2663
2664 rn->qlen = (u_short) (p - rn->query);
19332665
19342666 return NGX_OK;
19352667 }
20112743 n = *src++;
20122744
20132745 } else {
2014 ngx_memcpy(dst, src, n);
2746 ngx_strlow(dst, src, n);
20152747 dst += n;
20162748 src += n;
20172749
20602792 ngx_resolver_free_locked(r, rn->u.cname);
20612793 }
20622794
2063 if (rn->naddrs > 1) {
2795 if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
20642796 ngx_resolver_free_locked(r, rn->u.addrs);
20652797 }
2798
2799 #if (NGX_HAVE_INET6)
2800 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
2801 ngx_resolver_free_locked(r, rn->u6.addrs6);
2802 }
2803 #endif
20662804
20672805 ngx_resolver_free_locked(r, rn);
20682806
21352873 }
21362874
21372875
2138 static in_addr_t *
2139 ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
2140 {
2141 void *dst, *p;
2142 ngx_uint_t j;
2143
2144 dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
2145
2876 static ngx_addr_t *
2877 ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2878 ngx_uint_t rotate)
2879 {
2880 ngx_addr_t *dst;
2881 ngx_uint_t d, i, j, n;
2882 u_char (*sockaddr)[NGX_SOCKADDRLEN];
2883 in_addr_t *addr;
2884 struct sockaddr_in *sin;
2885 #if (NGX_HAVE_INET6)
2886 struct in6_addr *addr6;
2887 struct sockaddr_in6 *sin6;
2888 #endif
2889
2890 n = rn->naddrs;
2891 #if (NGX_HAVE_INET6)
2892 n += rn->naddrs6;
2893 #endif
2894
2895 dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
21462896 if (dst == NULL) {
2147 return dst;
2148 }
2149
2150 j = ngx_random() % n;
2151
2152 if (j == 0) {
2153 ngx_memcpy(dst, src, n * sizeof(in_addr_t));
2154 return dst;
2155 }
2156
2157 p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
2158 ngx_memcpy(p, src, j * sizeof(in_addr_t));
2897 return NULL;
2898 }
2899
2900 sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN);
2901 if (sockaddr == NULL) {
2902 ngx_resolver_free(r, dst);
2903 return NULL;
2904 }
2905
2906 i = 0;
2907 d = rotate ? ngx_random() % n : 0;
2908
2909 if (rn->naddrs) {
2910 j = rotate ? ngx_random() % rn->naddrs : 0;
2911
2912 addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;
2913
2914 do {
2915 sin = (struct sockaddr_in *) sockaddr[d];
2916 sin->sin_family = AF_INET;
2917 sin->sin_addr.s_addr = addr[j++];
2918 dst[d].sockaddr = (struct sockaddr *) sin;
2919 dst[d++].socklen = sizeof(struct sockaddr_in);
2920
2921 if (d == n) {
2922 d = 0;
2923 }
2924
2925 if (j == rn->naddrs) {
2926 j = 0;
2927 }
2928 } while (++i < rn->naddrs);
2929 }
2930
2931 #if (NGX_HAVE_INET6)
2932 if (rn->naddrs6) {
2933 j = rotate ? ngx_random() % rn->naddrs6 : 0;
2934
2935 addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;
2936
2937 do {
2938 sin6 = (struct sockaddr_in6 *) sockaddr[d];
2939 sin6->sin6_family = AF_INET6;
2940 ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16);
2941 dst[d].sockaddr = (struct sockaddr *) sin6;
2942 dst[d++].socklen = sizeof(struct sockaddr_in6);
2943
2944 if (d == n) {
2945 d = 0;
2946 }
2947
2948 if (j == rn->naddrs6) {
2949 j = 0;
2950 }
2951 } while (++i < n);
2952 }
2953 #endif
21592954
21602955 return dst;
21612956 }
22203015
22213016 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);
22223017
2223 if (s == -1) {
3018 if (s == (ngx_socket_t) -1) {
22243019 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
22253020 ngx_socket_n " failed");
22263021 return NGX_ERROR;
22413036 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
22423037 ngx_nonblocking_n " failed");
22433038
2244 ngx_free_connection(c);
2245
2246 if (ngx_close_socket(s) == -1) {
2247 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
2248 ngx_close_socket_n " failed");
2249 }
2250
2251 return NGX_ERROR;
3039 goto failed;
22523040 }
22533041
22543042 rev = c->read;
22733061 #endif
22743062
22753063 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
2276 "connect to %V, fd:%d #%d", &uc->server, s, c->number);
3064 "connect to %V, fd:%d #%uA", &uc->server, s, c->number);
22773065
22783066 rc = connect(s, uc->sockaddr, uc->socklen);
22793067
22833071 ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
22843072 "connect() failed");
22853073
2286 return NGX_ERROR;
3074 goto failed;
22873075 }
22883076
22893077 /* UDP sockets are always ready to write */
22973085 /* eventport event type has no meaning: oneshot only */
22983086
22993087 if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
2300 return NGX_ERROR;
3088 goto failed;
23013089 }
23023090
23033091 } else {
23043092 /* rtsig */
23053093
23063094 if (ngx_add_conn(c) == NGX_ERROR) {
2307 return NGX_ERROR;
3095 goto failed;
23083096 }
23093097 }
23103098
23113099 return NGX_OK;
2312 }
3100
3101 failed:
3102
3103 ngx_close_connection(c);
3104 uc->connection = NULL;
3105
3106 return NGX_ERROR;
3107 }
1717 #define NGX_RESOLVE_PTR 12
1818 #define NGX_RESOLVE_MX 15
1919 #define NGX_RESOLVE_TXT 16
20 #if (NGX_HAVE_INET6)
21 #define NGX_RESOLVE_AAAA 28
22 #endif
2023 #define NGX_RESOLVE_DNAME 39
2124
2225 #define NGX_RESOLVE_FORMERR 1
5356 /* PTR: resolved name, A: name to resolve */
5457 u_char *name;
5558
59 #if (NGX_HAVE_INET6)
60 /* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */
61 struct in6_addr addr6;
62 #endif
63
5664 u_short nlen;
5765 u_short qlen;
5866
5967 u_char *query;
68 #if (NGX_HAVE_INET6)
69 u_char *query6;
70 #endif
6071
6172 union {
6273 in_addr_t addr;
6475 u_char *cname;
6576 } u;
6677
78 u_char code;
6779 u_short naddrs;
6880 u_short cnlen;
6981
82 #if (NGX_HAVE_INET6)
83 union {
84 struct in6_addr addr6;
85 struct in6_addr *addrs6;
86 } u6;
87
88 u_short naddrs6;
89 #endif
90
7091 time_t expire;
7192 time_t valid;
93 uint32_t ttl;
7294
7395 ngx_resolver_ctx_t *waiting;
7496 } ngx_resolver_node_t;
99121 ngx_queue_t name_expire_queue;
100122 ngx_queue_t addr_expire_queue;
101123
124 #if (NGX_HAVE_INET6)
125 ngx_uint_t ipv6; /* unsigned ipv6:1; */
126 ngx_rbtree_t addr6_rbtree;
127 ngx_rbtree_node_t addr6_sentinel;
128 ngx_queue_t addr6_resend_queue;
129 ngx_queue_t addr6_expire_queue;
130 #endif
131
102132 time_t resend_timeout;
103133 time_t expire;
104134 time_t valid;
116146 ngx_int_t ident;
117147
118148 ngx_int_t state;
119 ngx_int_t type;
120149 ngx_str_t name;
121150
122151 ngx_uint_t naddrs;
123 in_addr_t *addrs;
124 in_addr_t addr;
152 ngx_addr_t *addrs;
153 ngx_addr_t addr;
154 struct sockaddr_in sin;
125155
126156 ngx_resolver_handler_pt handler;
127157 void *data;
128128 pool->pages->slab = pages;
129129 }
130130
131 pool->log_nomem = 1;
131132 pool->log_ctx = &pool->zero;
132133 pool->zero = '\0';
133134 }
439440 n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift;
440441 m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1));
441442 n /= (sizeof(uintptr_t) * 8);
442 bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1));
443 bitmap = (uintptr_t *)
444 ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1));
443445
444446 if (bitmap[n] & m) {
445447
656658 }
657659 }
658660
659 ngx_slab_error(pool, NGX_LOG_CRIT, "ngx_slab_alloc() failed: no memory");
661 if (pool->log_nomem) {
662 ngx_slab_error(pool, NGX_LOG_CRIT,
663 "ngx_slab_alloc() failed: no memory");
664 }
660665
661666 return NULL;
662667 }
3838 u_char *log_ctx;
3939 u_char zero;
4040
41 unsigned log_nomem:1;
42
4143 void *data;
4244 void *addr;
4345 } ngx_slab_pool_t;
1010
1111 static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
1212 u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
13 static void ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
14 const u_char *basis, ngx_uint_t padding);
1315 static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
1416 const u_char *basis);
1517
485487
486488 if (hexadecimal == 0) {
487489
488 if (ui64 <= NGX_MAX_UINT32_VALUE) {
490 if (ui64 <= (uint64_t) NGX_MAX_UINT32_VALUE) {
489491
490492 /*
491493 * To divide 64-bit numbers and to find remainders
852854
853855
854856 ngx_int_t
857 ngx_filename_cmp(u_char *s1, u_char *s2, size_t n)
858 {
859 ngx_uint_t c1, c2;
860
861 while (n) {
862 c1 = (ngx_uint_t) *s1++;
863 c2 = (ngx_uint_t) *s2++;
864
865 #if (NGX_HAVE_CASELESS_FILESYSTEM)
866 c1 = tolower(c1);
867 c2 = tolower(c2);
868 #endif
869
870 if (c1 == c2) {
871
872 if (c1) {
873 n--;
874 continue;
875 }
876
877 return 0;
878 }
879
880 /* we need '/' to be the lowest character */
881
882 if (c1 == 0 || c2 == 0) {
883 return c1 - c2;
884 }
885
886 c1 = (c1 == '/') ? 0 : c1;
887 c2 = (c2 == '/') ? 0 : c2;
888
889 return c1 - c2;
890 }
891
892 return 0;
893 }
894
895
896 ngx_int_t
855897 ngx_atoi(u_char *line, size_t n)
856898 {
857899 ngx_int_t value;
10591101 void
10601102 ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src)
10611103 {
1104 static u_char basis64[] =
1105 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1106
1107 ngx_encode_base64_internal(dst, src, basis64, 1);
1108 }
1109
1110
1111 void
1112 ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src)
1113 {
1114 static u_char basis64[] =
1115 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
1116
1117 ngx_encode_base64_internal(dst, src, basis64, 0);
1118 }
1119
1120
1121 static void
1122 ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src, const u_char *basis,
1123 ngx_uint_t padding)
1124 {
10621125 u_char *d, *s;
10631126 size_t len;
1064 static u_char basis64[] =
1065 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10661127
10671128 len = src->len;
10681129 s = src->data;
10691130 d = dst->data;
10701131
10711132 while (len > 2) {
1072 *d++ = basis64[(s[0] >> 2) & 0x3f];
1073 *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
1074 *d++ = basis64[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
1075 *d++ = basis64[s[2] & 0x3f];
1133 *d++ = basis[(s[0] >> 2) & 0x3f];
1134 *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
1135 *d++ = basis[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
1136 *d++ = basis[s[2] & 0x3f];
10761137
10771138 s += 3;
10781139 len -= 3;
10791140 }
10801141
10811142 if (len) {
1082 *d++ = basis64[(s[0] >> 2) & 0x3f];
1143 *d++ = basis[(s[0] >> 2) & 0x3f];
10831144
10841145 if (len == 1) {
1085 *d++ = basis64[(s[0] & 3) << 4];
1146 *d++ = basis[(s[0] & 3) << 4];
1147 if (padding) {
1148 *d++ = '=';
1149 }
1150
1151 } else {
1152 *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
1153 *d++ = basis[(s[1] & 0x0f) << 2];
1154 }
1155
1156 if (padding) {
10861157 *d++ = '=';
1087
1088 } else {
1089 *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
1090 *d++ = basis64[(s[1] & 0x0f) << 2];
1091 }
1092
1093 *d++ = '=';
1158 }
10941159 }
10951160
10961161 dst->len = d - dst->data;
166166 ngx_int_t ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n);
167167 ngx_int_t ngx_memn2cmp(u_char *s1, u_char *s2, size_t n1, size_t n2);
168168 ngx_int_t ngx_dns_strcmp(u_char *s1, u_char *s2);
169 ngx_int_t ngx_filename_cmp(u_char *s1, u_char *s2, size_t n);
169170
170171 ngx_int_t ngx_atoi(u_char *line, size_t n);
171172 ngx_int_t ngx_atofp(u_char *line, size_t n, size_t point);
181182 #define ngx_base64_decoded_length(len) (((len + 3) / 4) * 3)
182183
183184 void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
185 void ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src);
184186 ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
185187 ngx_int_t ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src);
186188
424424
425425 case -1:
426426 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
427 "ioctl(DP_ISPOLLED) failed for socket %d, event",
427 "ioctl(DP_ISPOLLED) failed for socket %d, event %04Xd",
428428 fd, revents);
429429 break;
430430
448448 != (ssize_t) sizeof(struct pollfd))
449449 {
450450 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
451 "write(/dev/poll) for %d failed, fd");
451 "write(/dev/poll) for %d failed", fd);
452452 }
453453
454454 if (close(fd) == -1) {
2323 #define EPOLLMSG 0x400
2424 #define EPOLLERR 0x008
2525 #define EPOLLHUP 0x010
26
27 #define EPOLLRDHUP 0x2000
2628
2729 #define EPOLLET 0x80000000
2830 #define EPOLLONESHOT 0x40000000
395397 if (event == NGX_READ_EVENT) {
396398 e = c->write;
397399 prev = EPOLLOUT;
398 #if (NGX_READ_EVENT != EPOLLIN)
399 events = EPOLLIN;
400 #if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
401 events = EPOLLIN|EPOLLRDHUP;
400402 #endif
401403
402404 } else {
403405 e = c->read;
404 prev = EPOLLIN;
406 prev = EPOLLIN|EPOLLRDHUP;
405407 #if (NGX_WRITE_EVENT != EPOLLOUT)
406408 events = EPOLLOUT;
407409 #endif
465467
466468 } else {
467469 e = c->read;
468 prev = EPOLLIN;
470 prev = EPOLLIN|EPOLLRDHUP;
469471 }
470472
471473 if (e->active) {
500502 {
501503 struct epoll_event ee;
502504
503 ee.events = EPOLLIN|EPOLLOUT|EPOLLET;
505 ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP;
504506 ee.data.ptr = (void *) ((uintptr_t) c | c->read->instance);
505507
506508 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
665667
666668 if ((revents & EPOLLIN) && rev->active) {
667669
670 #if (NGX_HAVE_EPOLLRDHUP)
671 if (revents & EPOLLRDHUP) {
672 rev->pending_eof = 1;
673 }
674 #endif
675
668676 if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
669677 rev->posted_ready = 1;
670678
287287
288288 ngx_log_error(level, cycle->log, err, "select() failed");
289289
290 if (err == EBADF) {
290 if (err == NGX_EBADF) {
291291 ngx_select_repair_fd_sets(cycle);
292292 }
293293
147147 return NGX_ERROR;
148148 }
149149
150 if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE)
151 || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE))
150 if ((event == NGX_READ_EVENT && max_read >= FD_SETSIZE)
151 || (event == NGX_WRITE_EVENT && max_write >= FD_SETSIZE))
152152 {
153153 ngx_log_error(NGX_LOG_ERR, ev->log, 0,
154154 "maximum number of descriptors "
5555 ngx_uint_t ngx_accept_mutex_held;
5656 ngx_msec_t ngx_accept_mutex_delay;
5757 ngx_int_t ngx_accept_disabled;
58 ngx_file_t ngx_accept_mutex_lock_file;
5958
6059
6160 #if (NGX_STAT_STUB)
6868
6969 unsigned delayed:1;
7070
71 unsigned read_discarded:1;
72
73 unsigned unexpected_eof:1;
74
7571 unsigned deferred_accept:1;
7672
77 /* the pending eof reported by kqueue or in aio chain operation */
73 /* the pending eof reported by kqueue, epoll or in aio chain operation */
7874 unsigned pending_eof:1;
7975
8076 #if !(NGX_THREADS)
352348 #define NGX_VNODE_EVENT 0
353349
354350
351 #if (NGX_HAVE_EPOLL) && !(NGX_HAVE_EPOLLRDHUP)
352 #define EPOLLRDHUP 0
353 #endif
354
355
355356 #if (NGX_HAVE_KQUEUE)
356357
357358 #define NGX_READ_EVENT EVFILT_READ
395396
396397 #elif (NGX_HAVE_EPOLL)
397398
398 #define NGX_READ_EVENT EPOLLIN
399 #define NGX_READ_EVENT (EPOLLIN|EPOLLRDHUP)
399400 #define NGX_WRITE_EVENT EPOLLOUT
400401
401402 #define NGX_LEVEL_EVENT 0
6969 s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
7070 #endif
7171
72 if (s == -1) {
72 if (s == (ngx_socket_t) -1) {
7373 err = ngx_socket_errno;
7474
7575 if (err == NGX_EAGAIN) {
211211 c->socklen = socklen;
212212 c->listening = ls;
213213 c->local_sockaddr = ls->sockaddr;
214 c->local_socklen = ls->socklen;
214215
215216 c->unexpected_eof = 1;
216217
274275 return;
275276 }
276277
277 c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->addr_text.data,
278 c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen,
279 c->addr_text.data,
278280 ls->addr_text_max_len, 0);
279281 if (c->addr_text.len == 0) {
280282 ngx_close_accepted_connection(c);
295297
296298 cidr = ecf->debug_connection.elts;
297299 for (i = 0; i < ecf->debug_connection.nelts; i++) {
298 if (cidr[i].family != c->sockaddr->sa_family) {
300 if (cidr[i].family != (ngx_uint_t) c->sockaddr->sa_family) {
299301 goto next;
300302 }
301303
341343 #endif
342344
343345 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
344 "*%d accept: %V fd:%d", c->number, &c->addr_text, s);
346 "*%uA accept: %V fd:%d", c->number, &c->addr_text, s);
345347
346348 if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
347349 if (ngx_add_conn(c) == NGX_ERROR) {
3030
3131 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0, "socket %d", s);
3232
33 if (s == -1) {
33 if (s == (ngx_socket_t) -1) {
3434 ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
3535 ngx_socket_n " failed");
3636 return NGX_ERROR;
121121 }
122122
123123 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
124 "connect to %V, fd:%d #%d", pc->name, s, c->number);
124 "connect to %V, fd:%d #%uA", pc->name, s, c->number);
125125
126126 rc = connect(s, pc->sockaddr, pc->socklen);
127127
1414 } ngx_openssl_conf_t;
1515
1616
17 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
17 static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
1818 static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
1919 int ret);
2020 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
3636 ngx_slab_pool_t *shpool, ngx_uint_t n);
3737 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
3838 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
39
40 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
41 static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
42 unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
43 HMAC_CTX *hctx, int enc);
44 #endif
3945
4046 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
4147 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
8187 int ngx_ssl_connection_index;
8288 int ngx_ssl_server_conf_index;
8389 int ngx_ssl_session_cache_index;
90 int ngx_ssl_session_ticket_keys_index;
8491 int ngx_ssl_certificate_index;
8592 int ngx_ssl_stapling_index;
8693
138145 return NGX_ERROR;
139146 }
140147
148 ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
149 NULL, NULL);
150 if (ngx_ssl_session_ticket_keys_index == -1) {
151 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
152 "SSL_CTX_get_ex_new_index() failed");
153 return NGX_ERROR;
154 }
155
141156 ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
142157 NULL);
143158 if (ngx_ssl_certificate_index == -1) {
174189 return NGX_ERROR;
175190 }
176191
192 ssl->buffer_size = NGX_SSL_BUFSIZE;
193
177194 /* client side options */
178195
179196 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
184201 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
185202 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
186203
204 #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
187205 /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
188206 SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
207 #endif
189208
190209 SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
191210 SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
277296 {
278297 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
279298 "SSL_CTX_set_ex_data() failed");
299 X509_free(x509);
300 BIO_free(bio);
280301 return NGX_ERROR;
281302 }
282303
341362 {
342363 STACK_OF(X509_NAME) *list;
343364
344 SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
365 SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_ssl_verify_callback);
345366
346367 SSL_CTX_set_verify_depth(ssl->ctx, depth);
347368
362383 return NGX_ERROR;
363384 }
364385
386 /*
387 * SSL_CTX_load_verify_locations() may leave errors in the error queue
388 * while returning success
389 */
390
391 ERR_clear_error();
392
365393 list = SSL_load_client_CA_file((char *) cert->data);
366394
367395 if (list == NULL) {
406434 return NGX_ERROR;
407435 }
408436
437 /*
438 * SSL_CTX_load_verify_locations() may leave errors in the error queue
439 * while returning success
440 */
441
442 ERR_clear_error();
443
409444 return NGX_OK;
410445 }
411446
456491
457492
458493 static int
459 ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
494 ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)
460495 {
461496 #if (NGX_DEBUG)
462497 char *subject, *issuer;
502537 static void
503538 ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
504539 {
540 BIO *rbio, *wbio;
505541 ngx_connection_t *c;
506542
507543 if (where & SSL_CB_HANDSHAKE_START) {
512548 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
513549 }
514550 }
551
552 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
553 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
554
555 if (!c->ssl->handshake_buffer_set) {
556 /*
557 * By default OpenSSL uses 4k buffer during a handshake,
558 * which is too low for long certificate chains and might
559 * result in extra round-trips.
560 *
561 * To adjust a buffer size we detect that buffering was added
562 * to write side of the connection by comparing rbio and wbio.
563 * If they are different, we assume that it's due to buffering
564 * added to wbio, and set buffer size.
565 */
566
567 rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn);
568 wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn);
569
570 if (rbio != wbio) {
571 (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE);
572 c->ssl->handshake_buffer_set = 1;
573 }
574 }
575 }
515576 }
516577
517578
518579 RSA *
519 ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length)
580 ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
581 int key_length)
520582 {
521583 static RSA *key;
522584
665727 }
666728
667729 sc->buffer = ((flags & NGX_SSL_BUFFER) != 0);
730 sc->buffer_size = ssl->buffer_size;
668731
669732 sc->connection = SSL_new(ssl->ctx);
670733
11611224 buf = c->ssl->buf;
11621225
11631226 if (buf == NULL) {
1164 buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
1227 buf = ngx_create_temp_buf(c->pool, c->ssl->buffer_size);
11651228 if (buf == NULL) {
11661229 return NGX_CHAIN_ERROR;
11671230 }
11701233 }
11711234
11721235 if (buf->start == NULL) {
1173 buf->start = ngx_palloc(c->pool, NGX_SSL_BUFSIZE);
1236 buf->start = ngx_palloc(c->pool, c->ssl->buffer_size);
11741237 if (buf->start == NULL) {
11751238 return NGX_CHAIN_ERROR;
11761239 }
11771240
11781241 buf->pos = buf->start;
11791242 buf->last = buf->start;
1180 buf->end = buf->start + NGX_SSL_BUFSIZE;
1243 buf->end = buf->start + c->ssl->buffer_size;
11811244 }
11821245
11831246 send = buf->last - buf->pos;
16631726 {
16641727 long cache_mode;
16651728
1729 SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
1730
16661731 if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
16671732 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
16681733 return NGX_OK;
17081773 }
17091774 }
17101775
1711 SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
1712
17131776 if (shm_zone) {
17141777 SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session);
17151778 SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session);
17401803 return NGX_OK;
17411804 }
17421805
1806 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
1807
17431808 if (shm_zone->shm.exists) {
1744 shm_zone->data = data;
1809 shm_zone->data = shpool->data;
17451810 return NGX_OK;
17461811 }
1747
1748 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
17491812
17501813 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
17511814 if (cache == NULL) {
17691832
17701833 ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
17711834 &shm_zone->shm.name);
1835
1836 shpool->log_nomem = 0;
17721837
17731838 return NGX_OK;
17741839 }
19221987 ngx_shmtx_unlock(&shpool->mutex);
19231988
19241989 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1925 "could not add new SSL session to the session cache");
1990 "could not allocate new session%s", shpool->log_ctx);
19261991
19271992 return 0;
19281993 }
21992264 }
22002265
22012266
2267 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
2268
2269 ngx_int_t
2270 ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
2271 {
2272 u_char buf[48];
2273 ssize_t n;
2274 ngx_str_t *path;
2275 ngx_file_t file;
2276 ngx_uint_t i;
2277 ngx_array_t *keys;
2278 ngx_file_info_t fi;
2279 ngx_ssl_session_ticket_key_t *key;
2280
2281 if (paths == NULL) {
2282 return NGX_OK;
2283 }
2284
2285 keys = ngx_array_create(cf->pool, paths->nelts,
2286 sizeof(ngx_ssl_session_ticket_key_t));
2287 if (keys == NULL) {
2288 return NGX_ERROR;
2289 }
2290
2291 path = paths->elts;
2292 for (i = 0; i < paths->nelts; i++) {
2293
2294 if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) {
2295 return NGX_ERROR;
2296 }
2297
2298 ngx_memzero(&file, sizeof(ngx_file_t));
2299 file.name = path[i];
2300 file.log = cf->log;
2301
2302 file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0);
2303 if (file.fd == NGX_INVALID_FILE) {
2304 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
2305 ngx_open_file_n " \"%V\" failed", &file.name);
2306 return NGX_ERROR;
2307 }
2308
2309 if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
2310 ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
2311 ngx_fd_info_n " \"%V\" failed", &file.name);
2312 goto failed;
2313 }
2314
2315 if (ngx_file_size(&fi) != 48) {
2316 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2317 "\"%V\" must be 48 bytes", &file.name);
2318 goto failed;
2319 }
2320
2321 n = ngx_read_file(&file, buf, 48, 0);
2322
2323 if (n == NGX_ERROR) {
2324 ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
2325 ngx_read_file_n " \"%V\" failed", &file.name);
2326 goto failed;
2327 }
2328
2329 if (n != 48) {
2330 ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
2331 ngx_read_file_n " \"%V\" returned only "
2332 "%z bytes instead of 48", &file.name, n);
2333 goto failed;
2334 }
2335
2336 key = ngx_array_push(keys);
2337 if (key == NULL) {
2338 goto failed;
2339 }
2340
2341 ngx_memcpy(key->name, buf, 16);
2342 ngx_memcpy(key->aes_key, buf + 16, 16);
2343 ngx_memcpy(key->hmac_key, buf + 32, 16);
2344
2345 if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
2346 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
2347 ngx_close_file_n " \"%V\" failed", &file.name);
2348 }
2349 }
2350
2351 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys)
2352 == 0)
2353 {
2354 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2355 "SSL_CTX_set_ex_data() failed");
2356 return NGX_ERROR;
2357 }
2358
2359 if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx,
2360 ngx_ssl_session_ticket_key_callback)
2361 == 0)
2362 {
2363 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
2364 "nginx was built with Session Tickets support, however, "
2365 "now it is linked dynamically to an OpenSSL library "
2366 "which has no tlsext support, therefore Session Tickets "
2367 "are not available");
2368 }
2369
2370 return NGX_OK;
2371
2372 failed:
2373
2374 if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
2375 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
2376 ngx_close_file_n " \"%V\" failed", &file.name);
2377 }
2378
2379 return NGX_ERROR;
2380 }
2381
2382
2383 #ifdef OPENSSL_NO_SHA256
2384 #define ngx_ssl_session_ticket_md EVP_sha1
2385 #else
2386 #define ngx_ssl_session_ticket_md EVP_sha256
2387 #endif
2388
2389
2390 static int
2391 ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn,
2392 unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx,
2393 HMAC_CTX *hctx, int enc)
2394 {
2395 SSL_CTX *ssl_ctx;
2396 ngx_uint_t i;
2397 ngx_array_t *keys;
2398 ngx_ssl_session_ticket_key_t *key;
2399 #if (NGX_DEBUG)
2400 u_char buf[32];
2401 ngx_connection_t *c;
2402 #endif
2403
2404 ssl_ctx = SSL_get_SSL_CTX(ssl_conn);
2405
2406 keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index);
2407 if (keys == NULL) {
2408 return -1;
2409 }
2410
2411 key = keys->elts;
2412
2413 #if (NGX_DEBUG)
2414 c = ngx_ssl_get_connection(ssl_conn);
2415 #endif
2416
2417 if (enc == 1) {
2418 /* encrypt session ticket */
2419
2420 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2421 "ssl session ticket encrypt, key: \"%*s\" (%s session)",
2422 ngx_hex_dump(buf, key[0].name, 16) - buf, buf,
2423 SSL_session_reused(ssl_conn) ? "reused" : "new");
2424
2425 RAND_pseudo_bytes(iv, 16);
2426 EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv);
2427 HMAC_Init_ex(hctx, key[0].hmac_key, 16,
2428 ngx_ssl_session_ticket_md(), NULL);
2429 memcpy(name, key[0].name, 16);
2430
2431 return 0;
2432
2433 } else {
2434 /* decrypt session ticket */
2435
2436 for (i = 0; i < keys->nelts; i++) {
2437 if (ngx_memcmp(name, key[i].name, 16) == 0) {
2438 goto found;
2439 }
2440 }
2441
2442 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2443 "ssl session ticket decrypt, key: \"%*s\" not found",
2444 ngx_hex_dump(buf, name, 16) - buf, buf);
2445
2446 return 0;
2447
2448 found:
2449
2450 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2451 "ssl session ticket decrypt, key: \"%*s\"%s",
2452 ngx_hex_dump(buf, key[i].name, 16) - buf, buf,
2453 (i == 0) ? " (default)" : "");
2454
2455 HMAC_Init_ex(hctx, key[i].hmac_key, 16,
2456 ngx_ssl_session_ticket_md(), NULL);
2457 EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv);
2458
2459 return (i == 0) ? 1 : 2 /* renew */;
2460 }
2461 }
2462
2463 #else
2464
2465 ngx_int_t
2466 ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths)
2467 {
2468 if (paths) {
2469 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
2470 "\"ssl_session_ticket_keys\" ignored, not supported");
2471 }
2472
2473 return NGX_OK;
2474 }
2475
2476 #endif
2477
2478
22022479 void
22032480 ngx_ssl_cleanup_ctx(void *data)
22042481 {
22472524 }
22482525
22492526 ngx_hex_dump(s->data, buf, len);
2527
2528 return NGX_OK;
2529 }
2530
2531
2532 ngx_int_t
2533 ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
2534 {
2535 if (SSL_session_reused(c->ssl->connection)) {
2536 ngx_str_set(s, "r");
2537
2538 } else {
2539 ngx_str_set(s, ".");
2540 }
22502541
22512542 return NGX_OK;
22522543 }
2828 typedef struct {
2929 SSL_CTX *ctx;
3030 ngx_log_t *log;
31 size_t buffer_size;
3132 } ngx_ssl_t;
3233
3334
3637
3738 ngx_int_t last;
3839 ngx_buf_t *buf;
40 size_t buffer_size;
3941
4042 ngx_connection_handler_pt handler;
4143
4749 unsigned buffer:1;
4850 unsigned no_wait_shutdown:1;
4951 unsigned no_send_shutdown:1;
52 unsigned handshake_buffer_set:1;
5053 } ngx_ssl_connection_t;
5154
5255
8184 } ngx_ssl_session_cache_t;
8285
8386
87 #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
88
89 typedef struct {
90 u_char name[16];
91 u_char aes_key[16];
92 u_char hmac_key[16];
93 } ngx_ssl_session_ticket_key_t;
94
95 #endif
96
8497
8598 #define NGX_SSL_SSLv2 0x0002
8699 #define NGX_SSL_SSLv3 0x0004
108121 ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
109122 ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
110123 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
111 RSA *ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length);
124 RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
125 int key_length);
112126 ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
113127 ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
114128 ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
115129 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout);
130 ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl,
131 ngx_array_t *paths);
116132 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
117133 ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
118134 ngx_uint_t flags);
139155 ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
140156 ngx_str_t *s);
141157 ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
158 ngx_str_t *s);
159 ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool,
142160 ngx_str_t *s);
143161 ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool,
144162 ngx_str_t *s);
170188 extern int ngx_ssl_connection_index;
171189 extern int ngx_ssl_server_conf_index;
172190 extern int ngx_ssl_session_cache_index;
191 extern int ngx_ssl_session_ticket_keys_index;
173192 extern int ngx_ssl_certificate_index;
174193 extern int ngx_ssl_stapling_index;
175194
791791 }
792792
793793 resolve->name = ctx->host;
794 resolve->type = NGX_RESOLVE_A;
795794 resolve->handler = ngx_ssl_ocsp_resolve_handler;
796795 resolve->data = ctx;
797796 resolve->timeout = ctx->resolver_timeout;
815814 {
816815 ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
817816
818 u_char *p;
819 size_t len;
820 in_port_t port;
821 ngx_uint_t i;
822 struct sockaddr_in *sin;
823
824 ngx_log_debug0(NGX_LOG_ALERT, ctx->log, 0,
817 u_char *p;
818 size_t len;
819 in_port_t port;
820 socklen_t socklen;
821 ngx_uint_t i;
822 struct sockaddr *sockaddr;
823
824 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
825825 "ssl ocsp resolve handler");
826826
827827 if (resolve->state) {
834834
835835 #if (NGX_DEBUG)
836836 {
837 in_addr_t addr;
837 u_char text[NGX_SOCKADDR_STRLEN];
838 ngx_str_t addr;
839
840 addr.data = text;
838841
839842 for (i = 0; i < resolve->naddrs; i++) {
840 addr = ntohl(resolve->addrs[i]);
841
842 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
843 "name was resolved to %ud.%ud.%ud.%ud",
844 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
845 (addr >> 8) & 0xff, addr & 0xff);
843 addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
844 resolve->addrs[i].socklen,
845 text, NGX_SOCKADDR_STRLEN, 0);
846
847 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
848 "name was resolved to %V", &addr);
849
846850 }
847851 }
848852 #endif
858862
859863 for (i = 0; i < resolve->naddrs; i++) {
860864
861 sin = ngx_pcalloc(ctx->pool, sizeof(struct sockaddr_in));
862 if (sin == NULL) {
865 socklen = resolve->addrs[i].socklen;
866
867 sockaddr = ngx_palloc(ctx->pool, socklen);
868 if (sockaddr == NULL) {
863869 goto failed;
864870 }
865871
866 sin->sin_family = AF_INET;
867 sin->sin_port = port;
868 sin->sin_addr.s_addr = resolve->addrs[i];
869
870 ctx->addrs[i].sockaddr = (struct sockaddr *) sin;
871 ctx->addrs[i].socklen = sizeof(struct sockaddr_in);
872
873 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
874
875 p = ngx_pnalloc(ctx->pool, len);
872 ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
873
874 switch (sockaddr->sa_family) {
875 #if (NGX_HAVE_INET6)
876 case AF_INET6:
877 ((struct sockaddr_in6 *) sockaddr)->sin6_port = port;
878 break;
879 #endif
880 default: /* AF_INET */
881 ((struct sockaddr_in *) sockaddr)->sin_port = port;
882 }
883
884 ctx->addrs[i].sockaddr = sockaddr;
885 ctx->addrs[i].socklen = socklen;
886
887 p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
876888 if (p == NULL) {
877889 goto failed;
878890 }
879891
880 len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
892 len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
881893
882894 ctx->addrs[i].name.len = len;
883895 ctx->addrs[i].name.data = p;
5656 do_write = 1;
5757 }
5858
59 if (p->upstream->fd != -1) {
59 if (p->upstream->fd != (ngx_socket_t) -1) {
6060 rev = p->upstream->read;
6161
6262 flags = (rev->eof || rev->error) ? NGX_CLOSE_EVENT : 0;
7373 }
7474 }
7575
76 if (p->downstream->fd != -1 && p->downstream->data == p->output_ctx) {
76 if (p->downstream->fd != (ngx_socket_t) -1
77 && p->downstream->data == p->output_ctx)
78 {
7779 wev = p->downstream->write;
7880 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
7981 return NGX_ABORT;
219221 {
220222
221223 /*
222 * if it is allowed, then save some bufs from r->in
223 * to a temporary file, and add them to a r->out chain
224 * if it is allowed, then save some bufs from p->in
225 * to a temporary file, and add them to a p->out chain
224226 */
225227
226228 rc = ngx_event_pipe_write_chain_to_temp_file(p);
453455 size_t bsize;
454456 ngx_int_t rc;
455457 ngx_uint_t flush, flushed, prev_last_shadow;
456 ngx_chain_t *out, **ll, *cl, file;
458 ngx_chain_t *out, **ll, *cl;
457459 ngx_connection_t *downstream;
458460
459461 downstream = p->downstream;
513515 }
514516
515517 if (p->cacheable && p->buf_to_file) {
516
517 file.buf = p->buf_to_file;
518 file.next = NULL;
519
520 if (ngx_write_chain_to_temp_file(p->temp_file, &file)
521 == NGX_ERROR)
522 {
518 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
519 "pipe write chain");
520
521 if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) {
523522 return NGX_ABORT;
524523 }
525524 }
857856 return NGX_OK;
858857 }
859858
860 if (p->free) {
861 cl = p->free;
862 b = cl->buf;
863 p->free = cl->next;
864 ngx_free_chain(p->pool, cl);
865
866 } else {
867 b = ngx_alloc_buf(p->pool);
868 if (b == NULL) {
869 return NGX_ERROR;
870 }
871 }
859 cl = ngx_chain_get_free_buf(p->pool, &p->free);
860 if (cl == NULL) {
861 return NGX_ERROR;
862 }
863
864 b = cl->buf;
872865
873866 ngx_memcpy(b, buf, sizeof(ngx_buf_t));
874867 b->shadow = buf;
877870 b->recycled = 1;
878871 buf->shadow = b;
879872
880 cl = ngx_alloc_chain_link(p->pool);
881 if (cl == NULL) {
882 return NGX_ERROR;
883 }
884
885 cl->buf = b;
886 cl->next = NULL;
887
888873 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
889874
890875 if (p->in) {
2525
2626 #endif
2727
28 #if (NGX_HAVE_UNIX_DOMAIN)
29
30 typedef struct {
31 ngx_uint_t deny; /* unsigned deny:1; */
32 } ngx_http_access_rule_un_t;
33
34 #endif
35
2836 typedef struct {
2937 ngx_array_t *rules; /* array of ngx_http_access_rule_t */
3038 #if (NGX_HAVE_INET6)
3139 ngx_array_t *rules6; /* array of ngx_http_access_rule6_t */
40 #endif
41 #if (NGX_HAVE_UNIX_DOMAIN)
42 ngx_array_t *rules_un; /* array of ngx_http_access_rule_un_t */
3243 #endif
3344 } ngx_http_access_loc_conf_t;
3445
3950 #if (NGX_HAVE_INET6)
4051 static ngx_int_t ngx_http_access_inet6(ngx_http_request_t *r,
4152 ngx_http_access_loc_conf_t *alcf, u_char *p);
53 #endif
54 #if (NGX_HAVE_UNIX_DOMAIN)
55 static ngx_int_t ngx_http_access_unix(ngx_http_request_t *r,
56 ngx_http_access_loc_conf_t *alcf);
4257 #endif
4358 static ngx_int_t ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny);
4459 static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
143158 return ngx_http_access_inet6(r, alcf, p);
144159 }
145160
161 break;
162
163 #endif
164
165 #if (NGX_HAVE_UNIX_DOMAIN)
166
167 case AF_UNIX:
168 if (alcf->rules_un) {
169 return ngx_http_access_unix(r, alcf);
170 }
171
172 break;
173
146174 #endif
147175 }
148176
220248 #endif
221249
222250
251 #if (NGX_HAVE_UNIX_DOMAIN)
252
253 static ngx_int_t
254 ngx_http_access_unix(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf)
255 {
256 ngx_uint_t i;
257 ngx_http_access_rule_un_t *rule_un;
258
259 rule_un = alcf->rules_un->elts;
260 for (i = 0; i < alcf->rules_un->nelts; i++) {
261
262 /* TODO: check path */
263 if (1) {
264 return ngx_http_access_found(r, rule_un[i].deny);
265 }
266 }
267
268 return NGX_DECLINED;
269 }
270
271 #endif
272
273
223274 static ngx_int_t
224275 ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny)
225276 {
245296 {
246297 ngx_http_access_loc_conf_t *alcf = conf;
247298
248 ngx_int_t rc;
249 ngx_uint_t all;
250 ngx_str_t *value;
251 ngx_cidr_t cidr;
252 ngx_http_access_rule_t *rule;
253 #if (NGX_HAVE_INET6)
254 ngx_http_access_rule6_t *rule6;
299 ngx_int_t rc;
300 ngx_uint_t all;
301 ngx_str_t *value;
302 ngx_cidr_t cidr;
303 ngx_http_access_rule_t *rule;
304 #if (NGX_HAVE_INET6)
305 ngx_http_access_rule6_t *rule6;
306 #endif
307 #if (NGX_HAVE_UNIX_DOMAIN)
308 ngx_http_access_rule_un_t *rule_un;
255309 #endif
256310
257311 ngx_memzero(&cidr, sizeof(ngx_cidr_t));
262316
263317 if (!all) {
264318
319 #if (NGX_HAVE_UNIX_DOMAIN)
320
321 if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) {
322 cidr.family = AF_UNIX;
323 rc = NGX_OK;
324
325 } else {
326 rc = ngx_ptocidr(&value[1], &cidr);
327 }
328
329 #else
265330 rc = ngx_ptocidr(&value[1], &cidr);
331 #endif
266332
267333 if (rc == NGX_ERROR) {
268334 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
276342 }
277343 }
278344
279 switch (cidr.family) {
280
281 #if (NGX_HAVE_INET6)
282 case AF_INET6:
283 case 0: /* all */
345 if (cidr.family == AF_INET || all) {
346
347 if (alcf->rules == NULL) {
348 alcf->rules = ngx_array_create(cf->pool, 4,
349 sizeof(ngx_http_access_rule_t));
350 if (alcf->rules == NULL) {
351 return NGX_CONF_ERROR;
352 }
353 }
354
355 rule = ngx_array_push(alcf->rules);
356 if (rule == NULL) {
357 return NGX_CONF_ERROR;
358 }
359
360 rule->mask = cidr.u.in.mask;
361 rule->addr = cidr.u.in.addr;
362 rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
363 }
364
365 #if (NGX_HAVE_INET6)
366 if (cidr.family == AF_INET6 || all) {
284367
285368 if (alcf->rules6 == NULL) {
286369 alcf->rules6 = ngx_array_create(cf->pool, 4,
298381 rule6->mask = cidr.u.in6.mask;
299382 rule6->addr = cidr.u.in6.addr;
300383 rule6->deny = (value[0].data[0] == 'd') ? 1 : 0;
301
302 if (!all) {
303 break;
304 }
305
306 /* "all" passes through */
307 #endif
308
309 default: /* AF_INET */
310
311 if (alcf->rules == NULL) {
312 alcf->rules = ngx_array_create(cf->pool, 4,
313 sizeof(ngx_http_access_rule_t));
314 if (alcf->rules == NULL) {
384 }
385 #endif
386
387 #if (NGX_HAVE_UNIX_DOMAIN)
388 if (cidr.family == AF_UNIX || all) {
389
390 if (alcf->rules_un == NULL) {
391 alcf->rules_un = ngx_array_create(cf->pool, 1,
392 sizeof(ngx_http_access_rule_un_t));
393 if (alcf->rules_un == NULL) {
315394 return NGX_CONF_ERROR;
316395 }
317396 }
318397
319 rule = ngx_array_push(alcf->rules);
320 if (rule == NULL) {
398 rule_un = ngx_array_push(alcf->rules_un);
399 if (rule_un == NULL) {
321400 return NGX_CONF_ERROR;
322401 }
323402
324 rule->mask = cidr.u.in.mask;
325 rule->addr = cidr.u.in.addr;
326 rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
327 }
403 rule_un->deny = (value[0].data[0] == 'd') ? 1 : 0;
404 }
405 #endif
328406
329407 return NGX_CONF_OK;
330408 }
350428 ngx_http_access_loc_conf_t *prev = parent;
351429 ngx_http_access_loc_conf_t *conf = child;
352430
353 #if (NGX_HAVE_INET6)
354
355 if (conf->rules == NULL && conf->rules6 == NULL) {
431 if (conf->rules == NULL
432 #if (NGX_HAVE_INET6)
433 && conf->rules6 == NULL
434 #endif
435 #if (NGX_HAVE_UNIX_DOMAIN)
436 && conf->rules_un == NULL
437 #endif
438 ) {
356439 conf->rules = prev->rules;
440 #if (NGX_HAVE_INET6)
357441 conf->rules6 = prev->rules6;
358 }
359
360 #else
361
362 if (conf->rules == NULL) {
363 conf->rules = prev->rules;
364 }
365
366 #endif
442 #endif
443 #if (NGX_HAVE_UNIX_DOMAIN)
444 conf->rules_un = prev->rules_un;
445 #endif
446 }
367447
368448 return NGX_CONF_OK;
369449 }
136136
137137 if (rc == NGX_DECLINED) {
138138
139 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
139 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
140140 "no user/password was provided for basic authentication");
141141
142142 return ngx_http_auth_basic_set_realm(r, &realm);
0
1 /*
2 * Copyright (C) Maxim Dounin
3 * Copyright (C) Nginx, Inc.
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12 typedef struct {
13 ngx_str_t uri;
14 ngx_array_t *vars;
15 } ngx_http_auth_request_conf_t;
16
17
18 typedef struct {
19 ngx_uint_t done;
20 ngx_uint_t status;
21 ngx_http_request_t *subrequest;
22 } ngx_http_auth_request_ctx_t;
23
24
25 typedef struct {
26 ngx_int_t index;
27 ngx_http_complex_value_t value;
28 ngx_http_set_variable_pt set_handler;
29 } ngx_http_auth_request_variable_t;
30
31
32 static ngx_int_t ngx_http_auth_request_handler(ngx_http_request_t *r);
33 static ngx_int_t ngx_http_auth_request_done(ngx_http_request_t *r,
34 void *data, ngx_int_t rc);
35 static ngx_int_t ngx_http_auth_request_set_variables(ngx_http_request_t *r,
36 ngx_http_auth_request_conf_t *arcf, ngx_http_auth_request_ctx_t *ctx);
37 static ngx_int_t ngx_http_auth_request_variable(ngx_http_request_t *r,
38 ngx_http_variable_value_t *v, uintptr_t data);
39 static void *ngx_http_auth_request_create_conf(ngx_conf_t *cf);
40 static char *ngx_http_auth_request_merge_conf(ngx_conf_t *cf,
41 void *parent, void *child);
42 static ngx_int_t ngx_http_auth_request_init(ngx_conf_t *cf);
43 static char *ngx_http_auth_request(ngx_conf_t *cf, ngx_command_t *cmd,
44 void *conf);
45 static char *ngx_http_auth_request_set(ngx_conf_t *cf, ngx_command_t *cmd,
46 void *conf);
47
48
49 static ngx_command_t ngx_http_auth_request_commands[] = {
50
51 { ngx_string("auth_request"),
52 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
53 ngx_http_auth_request,
54 NGX_HTTP_LOC_CONF_OFFSET,
55 0,
56 NULL },
57
58 { ngx_string("auth_request_set"),
59 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
60 ngx_http_auth_request_set,
61 NGX_HTTP_LOC_CONF_OFFSET,
62 0,
63 NULL },
64
65 ngx_null_command
66 };
67
68
69 static ngx_http_module_t ngx_http_auth_request_module_ctx = {
70 NULL, /* preconfiguration */
71 ngx_http_auth_request_init, /* postconfiguration */
72
73 NULL, /* create main configuration */
74 NULL, /* init main configuration */
75
76 NULL, /* create server configuration */
77 NULL, /* merge server configuration */
78
79 ngx_http_auth_request_create_conf, /* create location configuration */
80 ngx_http_auth_request_merge_conf /* merge location configuration */
81 };
82
83
84 ngx_module_t ngx_http_auth_request_module = {
85 NGX_MODULE_V1,
86 &ngx_http_auth_request_module_ctx, /* module context */
87 ngx_http_auth_request_commands, /* module directives */
88 NGX_HTTP_MODULE, /* module type */
89 NULL, /* init master */
90 NULL, /* init module */
91 NULL, /* init process */
92 NULL, /* init thread */
93 NULL, /* exit thread */
94 NULL, /* exit process */
95 NULL, /* exit master */
96 NGX_MODULE_V1_PADDING
97 };
98
99
100 static ngx_int_t
101 ngx_http_auth_request_handler(ngx_http_request_t *r)
102 {
103 ngx_table_elt_t *h, *ho;
104 ngx_http_request_t *sr;
105 ngx_http_post_subrequest_t *ps;
106 ngx_http_auth_request_ctx_t *ctx;
107 ngx_http_auth_request_conf_t *arcf;
108
109 arcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_request_module);
110
111 if (arcf->uri.len == 0) {
112 return NGX_DECLINED;
113 }
114
115 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
116 "auth request handler");
117
118 ctx = ngx_http_get_module_ctx(r, ngx_http_auth_request_module);
119
120 if (ctx != NULL) {
121 if (!ctx->done) {
122 return NGX_AGAIN;
123 }
124
125 /*
126 * as soon as we are done - explicitly set variables to make
127 * sure they will be available after internal redirects
128 */
129
130 if (ngx_http_auth_request_set_variables(r, arcf, ctx) != NGX_OK) {
131 return NGX_ERROR;
132 }
133
134 /* return appropriate status */
135
136 if (ctx->status == NGX_HTTP_FORBIDDEN) {
137 return ctx->status;
138 }
139
140 if (ctx->status == NGX_HTTP_UNAUTHORIZED) {
141 sr = ctx->subrequest;
142
143 h = sr->headers_out.www_authenticate;
144
145 if (!h && sr->upstream) {
146 h = sr->upstream->headers_in.www_authenticate;
147 }
148
149 if (h) {
150 ho = ngx_list_push(&r->headers_out.headers);
151 if (ho == NULL) {
152 return NGX_ERROR;
153 }
154
155 *ho = *h;
156
157 r->headers_out.www_authenticate = ho;
158 }
159
160 return ctx->status;
161 }
162
163 if (ctx->status >= NGX_HTTP_OK
164 && ctx->status < NGX_HTTP_SPECIAL_RESPONSE)
165 {
166 return NGX_OK;
167 }
168
169 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
170 "auth request unexpected status: %d", ctx->status);
171
172 return NGX_HTTP_INTERNAL_SERVER_ERROR;
173 }
174
175 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_auth_request_ctx_t));
176 if (ctx == NULL) {
177 return NGX_ERROR;
178 }
179
180 ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
181 if (ps == NULL) {
182 return NGX_ERROR;
183 }
184
185 ps->handler = ngx_http_auth_request_done;
186 ps->data = ctx;
187
188 if (ngx_http_subrequest(r, &arcf->uri, NULL, &sr, ps,
189 NGX_HTTP_SUBREQUEST_WAITED)
190 != NGX_OK)
191 {
192 return NGX_ERROR;
193 }
194
195 /*
196 * allocate fake request body to avoid attempts to read it and to make
197 * sure real body file (if already read) won't be closed by upstream
198 */
199
200 sr->request_body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
201 if (sr->request_body == NULL) {
202 return NGX_ERROR;
203 }
204
205 sr->header_only = 1;
206
207 ctx->subrequest = sr;
208
209 ngx_http_set_ctx(r, ctx, ngx_http_auth_request_module);
210
211 return NGX_AGAIN;
212 }
213
214
215 static ngx_int_t
216 ngx_http_auth_request_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
217 {
218 ngx_http_auth_request_ctx_t *ctx = data;
219
220 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
221 "auth request done s:%d", r->headers_out.status);
222
223 ctx->done = 1;
224 ctx->status = r->headers_out.status;
225
226 return rc;
227 }
228
229
230 static ngx_int_t
231 ngx_http_auth_request_set_variables(ngx_http_request_t *r,
232 ngx_http_auth_request_conf_t *arcf, ngx_http_auth_request_ctx_t *ctx)
233 {
234 ngx_str_t val;
235 ngx_http_variable_t *v;
236 ngx_http_variable_value_t *vv;
237 ngx_http_auth_request_variable_t *av, *last;
238 ngx_http_core_main_conf_t *cmcf;
239
240 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
241 "auth request set variables");
242
243 if (arcf->vars == NULL) {
244 return NGX_OK;
245 }
246
247 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
248 v = cmcf->variables.elts;
249
250 av = arcf->vars->elts;
251 last = av + arcf->vars->nelts;
252
253 while (av < last) {
254 /*
255 * explicitly set new value to make sure it will be available after
256 * internal redirects
257 */
258
259 vv = &r->variables[av->index];
260
261 if (ngx_http_complex_value(ctx->subrequest, &av->value, &val)
262 != NGX_OK)
263 {
264 return NGX_ERROR;
265 }
266
267 vv->valid = 1;
268 vv->not_found = 0;
269 vv->data = val.data;
270 vv->len = val.len;
271
272 if (av->set_handler) {
273 /*
274 * set_handler only available in cmcf->variables_keys, so we store
275 * it explicitly
276 */
277
278 av->set_handler(r, vv, v[av->index].data);
279 }
280
281 av++;
282 }
283
284 return NGX_OK;
285 }
286
287
288 static ngx_int_t
289 ngx_http_auth_request_variable(ngx_http_request_t *r,
290 ngx_http_variable_value_t *v, uintptr_t data)
291 {
292 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
293 "auth request variable");
294
295 v->not_found = 1;
296
297 return NGX_OK;
298 }
299
300
301 static void *
302 ngx_http_auth_request_create_conf(ngx_conf_t *cf)
303 {
304 ngx_http_auth_request_conf_t *conf;
305
306 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_request_conf_t));
307 if (conf == NULL) {
308 return NULL;
309 }
310
311 /*
312 * set by ngx_pcalloc():
313 *
314 * conf->uri = { 0, NULL };
315 */
316
317 conf->vars = NGX_CONF_UNSET_PTR;
318
319 return conf;
320 }
321
322
323 static char *
324 ngx_http_auth_request_merge_conf(ngx_conf_t *cf, void *parent, void *child)
325 {
326 ngx_http_auth_request_conf_t *prev = parent;
327 ngx_http_auth_request_conf_t *conf = child;
328
329 ngx_conf_merge_str_value(conf->uri, prev->uri, "");
330 ngx_conf_merge_ptr_value(conf->vars, prev->vars, NULL);
331
332 return NGX_CONF_OK;
333 }
334
335
336 static ngx_int_t
337 ngx_http_auth_request_init(ngx_conf_t *cf)
338 {
339 ngx_http_handler_pt *h;
340 ngx_http_core_main_conf_t *cmcf;
341
342 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
343
344 h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
345 if (h == NULL) {
346 return NGX_ERROR;
347 }
348
349 *h = ngx_http_auth_request_handler;
350
351 return NGX_OK;
352 }
353
354
355 static char *
356 ngx_http_auth_request(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
357 {
358 ngx_http_auth_request_conf_t *arcf = conf;
359
360 ngx_str_t *value;
361
362 if (arcf->uri.data != NULL) {
363 return "is duplicate";
364 }
365
366 value = cf->args->elts;
367
368 if (ngx_strcmp(value[1].data, "off") == 0) {
369 arcf->uri.len = 0;
370 arcf->uri.data = (u_char *) "";
371
372 return NGX_CONF_OK;
373 }
374
375 arcf->uri = value[1];
376
377 return NGX_CONF_OK;
378 }
379
380
381 static char *
382 ngx_http_auth_request_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
383 {
384 ngx_http_auth_request_conf_t *arcf = conf;
385
386 ngx_str_t *value;
387 ngx_http_variable_t *v;
388 ngx_http_auth_request_variable_t *av;
389 ngx_http_compile_complex_value_t ccv;
390
391 value = cf->args->elts;
392
393 if (value[1].data[0] != '$') {
394 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
395 "invalid variable name \"%V\"", &value[1]);
396 return NGX_CONF_ERROR;
397 }
398
399 value[1].len--;
400 value[1].data++;
401
402 if (arcf->vars == NGX_CONF_UNSET_PTR) {
403 arcf->vars = ngx_array_create(cf->pool, 1,
404 sizeof(ngx_http_auth_request_variable_t));
405 if (arcf->vars == NULL) {
406 return NGX_CONF_ERROR;
407 }
408 }
409
410 av = ngx_array_push(arcf->vars);
411 if (av == NULL) {
412 return NGX_CONF_ERROR;
413 }
414
415 v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
416 if (v == NULL) {
417 return NGX_CONF_ERROR;
418 }
419
420 av->index = ngx_http_get_variable_index(cf, &value[1]);
421 if (av->index == NGX_ERROR) {
422 return NGX_CONF_ERROR;
423 }
424
425 if (v->get_handler == NULL) {
426 v->get_handler = ngx_http_auth_request_variable;
427 v->data = (uintptr_t) av;
428 }
429
430 av->set_handler = v->set_handler;
431
432 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
433
434 ccv.cf = cf;
435 ccv.value = &value[2];
436 ccv.complex_value = &av->value;
437
438 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
439 return NGX_CONF_ERROR;
440 }
441
442 return NGX_CONF_OK;
443 }
232232 r->headers_out.status = NGX_HTTP_OK;
233233 r->headers_out.content_type_len = sizeof("text/html") - 1;
234234 ngx_str_set(&r->headers_out.content_type, "text/html");
235 r->headers_out.content_type_lowcase = NULL;
235236
236237 rc = ngx_http_send_header(r);
237238
356357
357358 if (ngx_close_dir(&dir) == NGX_ERROR) {
358359 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
359 ngx_close_dir_n " \"%s\" failed", &path);
360 ngx_close_dir_n " \"%V\" failed", &path);
360361 }
361362
362363 escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len);
127127 ngx_string("text/xml"),
128128 ngx_string("text/plain"),
129129 ngx_string("text/vnd.wap.wml"),
130 ngx_string("application/x-javascript"),
130 ngx_string("application/javascript"),
131131 ngx_string("application/rss+xml"),
132132 ngx_null_string
133133 };
88 #include <ngx_core.h>
99 #include <ngx_http.h>
1010
11
12 #define NGX_HTTP_DAV_COPY_BLOCK 65536
1311
1412 #define NGX_HTTP_DAV_OFF 2
1513
605603
606604 duri.len = last - p;
607605 duri.data = p;
608 flags = 0;
606 flags = NGX_HTTP_LOG_UNSAFE;
609607
610608 if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) {
611609 goto invalid_destination;
137137 static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data);
138138 static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
139139 ngx_buf_t *buf);
140 static ngx_int_t ngx_http_fastcgi_non_buffered_filter(void *data,
141 ssize_t bytes);
140142 static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
141143 ngx_http_fastcgi_ctx_t *f);
142144 static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
184186 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
185187 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
186188 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
189 { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
187190 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
188191 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
189192 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
229232 ngx_conf_set_access_slot,
230233 NGX_HTTP_LOC_CONF_OFFSET,
231234 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store_access),
235 NULL },
236
237 { ngx_string("fastcgi_buffering"),
238 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
239 ngx_conf_set_flag_slot,
240 NGX_HTTP_LOC_CONF_OFFSET,
241 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffering),
232242 NULL },
233243
234244 { ngx_string("fastcgi_ignore_client_abort"),
392402 ngx_conf_set_msec_slot,
393403 NGX_HTTP_LOC_CONF_OFFSET,
394404 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
405 NULL },
406
407 { ngx_string("fastcgi_cache_revalidate"),
408 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
409 ngx_conf_set_flag_slot,
410 NGX_HTTP_LOC_CONF_OFFSET,
411 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_revalidate),
395412 NULL },
396413
397414 #endif
552569 #if (NGX_HTTP_CACHE)
553570
554571 static ngx_keyval_t ngx_http_fastcgi_cache_headers[] = {
555 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
572 { ngx_string("HTTP_IF_MODIFIED_SINCE"),
573 ngx_string("$upstream_cache_last_modified") },
556574 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
557575 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
558576 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
576594 ngx_http_upstream_t *u;
577595 ngx_http_fastcgi_ctx_t *f;
578596 ngx_http_fastcgi_loc_conf_t *flcf;
579
580 if (r->subrequest_in_memory) {
581 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
582 "ngx_http_fastcgi_module does not support "
583 "subrequest in memory");
584 return NGX_HTTP_INTERNAL_SERVER_ERROR;
585 }
586597
587598 if (ngx_http_upstream_create(r) != NGX_OK) {
588599 return NGX_HTTP_INTERNAL_SERVER_ERROR;
620631 u->finalize_request = ngx_http_fastcgi_finalize_request;
621632 r->state = 0;
622633
623 u->buffering = 1;
634 u->buffering = flcf->upstream.buffering;
624635
625636 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
626637 if (u->pipe == NULL) {
631642 u->pipe->input_ctx = r;
632643
633644 u->input_filter_init = ngx_http_fastcgi_input_filter_init;
645 u->input_filter = ngx_http_fastcgi_non_buffered_filter;
646 u->input_filter_ctx = r;
634647
635648 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
636649
15811594 ngx_str_set(&u->headers_in.status_line, "200 OK");
15821595 }
15831596
1584 if (u->state) {
1597 if (u->state && u->state->status == 0) {
15851598 u->state->status = u->headers_in.status_n;
15861599 }
15871600
18241837 break;
18251838 }
18261839
1827 if (p->free) {
1828 cl = p->free;
1829 b = cl->buf;
1830 p->free = cl->next;
1831 ngx_free_chain(p->pool, cl);
1832
1833 } else {
1834 b = ngx_alloc_buf(p->pool);
1835 if (b == NULL) {
1836 return NGX_ERROR;
1837 }
1838 }
1840 cl = ngx_chain_get_free_buf(p->pool, &p->free);
1841 if (cl == NULL) {
1842 return NGX_ERROR;
1843 }
1844
1845 b = cl->buf;
18391846
18401847 ngx_memzero(b, sizeof(ngx_buf_t));
18411848
18491856 *prev = b;
18501857 prev = &b->shadow;
18511858
1852 cl = ngx_alloc_chain_link(p->pool);
1853 if (cl == NULL) {
1854 return NGX_ERROR;
1855 }
1856
1857 cl->buf = b;
1858 cl->next = NULL;
1859
18601859 if (p->in) {
18611860 *p->last_in = cl;
18621861 } else {
19171916
19181917 if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
19191918 return NGX_ERROR;
1919 }
1920
1921 return NGX_OK;
1922 }
1923
1924
1925 static ngx_int_t
1926 ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
1927 {
1928 u_char *m, *msg;
1929 ngx_int_t rc;
1930 ngx_buf_t *b, *buf;
1931 ngx_chain_t *cl, **ll;
1932 ngx_http_request_t *r;
1933 ngx_http_upstream_t *u;
1934 ngx_http_fastcgi_ctx_t *f;
1935
1936 r = data;
1937 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1938
1939 u = r->upstream;
1940 buf = &u->buffer;
1941
1942 buf->pos = buf->last;
1943 buf->last += bytes;
1944
1945 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
1946 ll = &cl->next;
1947 }
1948
1949 f->pos = buf->pos;
1950 f->last = buf->last;
1951
1952 for ( ;; ) {
1953 if (f->state < ngx_http_fastcgi_st_data) {
1954
1955 rc = ngx_http_fastcgi_process_record(r, f);
1956
1957 if (rc == NGX_AGAIN) {
1958 break;
1959 }
1960
1961 if (rc == NGX_ERROR) {
1962 return NGX_ERROR;
1963 }
1964
1965 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1966 f->state = ngx_http_fastcgi_st_padding;
1967
1968 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1969 "http fastcgi closed stdout");
1970
1971 continue;
1972 }
1973 }
1974
1975 if (f->state == ngx_http_fastcgi_st_padding) {
1976
1977 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1978
1979 if (f->pos + f->padding < f->last) {
1980 u->length = 0;
1981 break;
1982 }
1983
1984 if (f->pos + f->padding == f->last) {
1985 u->length = 0;
1986 u->keepalive = 1;
1987 break;
1988 }
1989
1990 f->padding -= f->last - f->pos;
1991
1992 break;
1993 }
1994
1995 if (f->pos + f->padding < f->last) {
1996 f->state = ngx_http_fastcgi_st_version;
1997 f->pos += f->padding;
1998
1999 continue;
2000 }
2001
2002 if (f->pos + f->padding == f->last) {
2003 f->state = ngx_http_fastcgi_st_version;
2004
2005 break;
2006 }
2007
2008 f->padding -= f->last - f->pos;
2009
2010 break;
2011 }
2012
2013
2014 /* f->state == ngx_http_fastcgi_st_data */
2015
2016 if (f->type == NGX_HTTP_FASTCGI_STDERR) {
2017
2018 if (f->length) {
2019
2020 if (f->pos == f->last) {
2021 break;
2022 }
2023
2024 msg = f->pos;
2025
2026 if (f->pos + f->length <= f->last) {
2027 f->pos += f->length;
2028 f->length = 0;
2029 f->state = ngx_http_fastcgi_st_padding;
2030
2031 } else {
2032 f->length -= f->last - f->pos;
2033 f->pos = f->last;
2034 }
2035
2036 for (m = f->pos - 1; msg < m; m--) {
2037 if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
2038 break;
2039 }
2040 }
2041
2042 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2043 "FastCGI sent in stderr: \"%*s\"",
2044 m + 1 - msg, msg);
2045
2046 } else {
2047 f->state = ngx_http_fastcgi_st_padding;
2048 }
2049
2050 continue;
2051 }
2052
2053 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
2054
2055 if (f->pos + f->length <= f->last) {
2056 f->state = ngx_http_fastcgi_st_padding;
2057 f->pos += f->length;
2058
2059 continue;
2060 }
2061
2062 f->length -= f->last - f->pos;
2063
2064 break;
2065 }
2066
2067
2068 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
2069
2070 if (f->pos == f->last) {
2071 break;
2072 }
2073
2074 cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2075 if (cl == NULL) {
2076 return NGX_ERROR;
2077 }
2078
2079 *ll = cl;
2080 ll = &cl->next;
2081
2082 b = cl->buf;
2083
2084 b->flush = 1;
2085 b->memory = 1;
2086
2087 b->pos = f->pos;
2088 b->tag = u->output.tag;
2089
2090 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2091 "http fastcgi output buf %p", b->pos);
2092
2093 if (f->pos + f->length <= f->last) {
2094 f->state = ngx_http_fastcgi_st_padding;
2095 f->pos += f->length;
2096 b->last = f->pos;
2097
2098 continue;
2099 }
2100
2101 f->length -= f->last - f->pos;
2102 b->last = f->last;
2103
2104 break;
2105 }
2106
2107 /* provide continuous buffer for subrequests in memory */
2108
2109 if (r->subrequest_in_memory) {
2110
2111 cl = u->out_bufs;
2112
2113 if (cl) {
2114 buf->pos = cl->buf->pos;
2115 }
2116
2117 buf->last = buf->pos;
2118
2119 for (cl = u->out_bufs; cl; cl = cl->next) {
2120 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2121 "http fastcgi in memory %p-%p %uz",
2122 cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf));
2123
2124 if (buf->last == cl->buf->pos) {
2125 buf->last = cl->buf->last;
2126 continue;
2127 }
2128
2129 buf->last = ngx_movemem(buf->last, cl->buf->pos,
2130 cl->buf->last - cl->buf->pos);
2131
2132 cl->buf->pos = buf->last - (cl->buf->last - cl->buf->pos);
2133 cl->buf->last = buf->last;
2134 }
19202135 }
19212136
19222137 return NGX_OK;
21252340 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
21262341 conf->upstream.cache_lock = NGX_CONF_UNSET;
21272342 conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
2343 conf->upstream.cache_revalidate = NGX_CONF_UNSET;
21282344 #endif
21292345
21302346 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
21342350
21352351 /* "fastcgi_cyclic_temp_file" is disabled */
21362352 conf->upstream.cyclic_temp_file = 0;
2353
2354 conf->upstream.change_buffering = 1;
21372355
21382356 conf->catch_stderr = NGX_CONF_UNSET_PTR;
21392357
23562574 ngx_conf_merge_ptr_value(conf->upstream.no_cache,
23572575 prev->upstream.no_cache, NULL);
23582576
2359 if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
2360 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
2361 "\"fastcgi_no_cache\" functionality has been changed in 0.8.46, "
2362 "now it should be used together with \"fastcgi_cache_bypass\"");
2363 }
2364
23652577 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
23662578 prev->upstream.cache_valid, NULL);
23672579
23742586
23752587 ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
23762588 prev->upstream.cache_lock_timeout, 5000);
2589
2590 ngx_conf_merge_value(conf->upstream.cache_revalidate,
2591 prev->upstream.cache_revalidate, 0);
23772592
23782593 #endif
23792594
25502765
25512766 s->key = h->key;
25522767 s->value = h->value;
2553 s->skip_empty = 0;
2768 s->skip_empty = 1;
25542769
25552770 next:
25562771
198198 }
199199 }
200200
201 if (ctx->nomem) {
201 if (ctx->nomem || in == NULL) {
202202
203203 /* flush busy buffers */
204204
421421 rc = inflate(&ctx->zstream, ctx->flush);
422422
423423 if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
424 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
424 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
425425 "inflate() failed: %d, %d", ctx->flush, rc);
426426 return NGX_ERROR;
427427 }
499499 return NGX_OK;
500500 }
501501
502 if (rc == Z_STREAM_END && ctx->flush == Z_FINISH
503 && ctx->zstream.avail_in == 0)
504 {
502 if (ctx->flush == Z_FINISH && ctx->zstream.avail_in == 0) {
503
504 if (rc != Z_STREAM_END) {
505 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
506 "inflate() returned %d on response end", rc);
507 return NGX_ERROR;
508 }
505509
506510 if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) {
507511 return NGX_ERROR;
367367 if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
368368 goto failed;
369369 }
370 }
371
372 if (ctx->nomem) {
370
371 r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
372 }
373
374 if (ctx->nomem || in == NULL) {
373375
374376 /* flush busy buffers */
375377
619621 return NGX_ERROR;
620622 }
621623
622 r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
623
624624 ctx->last_out = &ctx->out;
625625 ctx->crc32 = crc32(0L, Z_NULL, 0);
626626 ctx->flush = Z_NO_FLUSH;
852852 cl->next = NULL;
853853 *ctx->last_out = cl;
854854 ctx->last_out = &cl->next;
855
856 r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED;
855857
856858 return NGX_OK;
857859 }
3737 static ngx_command_t ngx_http_gzip_static_commands[] = {
3838
3939 { ngx_string("gzip_static"),
40 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
40 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
4141 ngx_conf_set_enum_slot,
4242 NGX_HTTP_LOC_CONF_OFFSET,
4343 offsetof(ngx_http_gzip_static_conf_t, enable),
338338 {
339339 ngx_table_elt_t *cc, **ccp;
340340
341 if (value->len == 0) {
342 return NGX_OK;
343 }
344
341345 ccp = r->headers_out.cache_control.elts;
342346
343347 if (ccp == NULL) {
477477 "image buf: %uz", size);
478478
479479 rest = ctx->image + ctx->length - p;
480 size = (rest < size) ? rest : size;
480
481 if (size > rest) {
482 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
483 "image filter: too big response");
484 return NGX_ERROR;
485 }
481486
482487 p = ngx_cpymem(p, b->pos, size);
483488 b->pos += size;
566571 ngx_http_clean_header(r);
567572
568573 r->headers_out.status = NGX_HTTP_OK;
569 ngx_str_set(&r->headers_out.content_type, "text/plain");
574 r->headers_out.content_type_len = sizeof("application/json") - 1;
575 ngx_str_set(&r->headers_out.content_type, "application/json");
570576 r->headers_out.content_type_lowcase = NULL;
571577
572578 if (ctx == NULL) {
450450
451451 node = ngx_slab_alloc_locked(ctx->shpool, size);
452452 if (node == NULL) {
453 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
454 "could not allocate node%s", ctx->shpool->log_ctx);
453455 return NGX_ERROR;
454456 }
455457 }
672674
673675 ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z",
674676 &shm_zone->shm.name);
677
678 ctx->shpool->log_nomem = 0;
675679
676680 return NGX_OK;
677681 }
911915 continue;
912916 }
913917
914 if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) {
918 if (ngx_strcmp(value[i].data, "nodelay") == 0) {
915919 nodelay = 1;
916920 continue;
917921 }
130130 }
131131
132132 if (!value->valid) {
133 value = ngx_http_get_flushed_variable(r, (ngx_uint_t) value->data);
133 value = ngx_http_get_flushed_variable(r, (uintptr_t) value->data);
134134
135135 if (value == NULL || value->not_found) {
136136 value = &ngx_http_variable_null_value;
413413 var = ctx->var_values.elts;
414414
415415 for (i = 0; i < ctx->var_values.nelts; i++) {
416 if (index == (ngx_int_t) var[i].data) {
416 if (index == (intptr_t) var[i].data) {
417417 var = &var[i];
418418 goto found;
419419 }
428428 var->no_cacheable = 0;
429429 var->not_found = 0;
430430 var->len = 0;
431 var->data = (u_char *) index;
431 var->data = (u_char *) (intptr_t) index;
432432
433433 goto found;
434434 }
196196 return NGX_HTTP_INTERNAL_SERVER_ERROR;
197197 }
198198
199 ctx->rest = NGX_HTTP_MEMCACHED_END;
200199 ctx->request = r;
201200
202201 ngx_http_set_ctx(r, ctx, ngx_http_memcached_module);
308307
309308 found:
310309
310 line.data = u->buffer.pos;
311 line.len = p - u->buffer.pos;
312
313 if (line.len == 0 || *(p - 1) != CR) {
314 goto no_valid;
315 }
316
311317 *p = '\0';
312
313 line.len = p - u->buffer.pos - 1;
314 line.data = u->buffer.pos;
318 line.len--;
315319
316320 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
317321 "memcached: \"%V\"", &line);
386390 length:
387391
388392 start = p;
389
390 while (*p && *p++ != CR) { /* void */ }
391
392 u->headers_in.content_length_n = ngx_atoof(start, p - start - 1);
393 p = line.data + line.len;
394
395 u->headers_in.content_length_n = ngx_atoof(start, p - start);
393396 if (u->headers_in.content_length_n == -1) {
394397 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
395398 "memcached sent invalid length in response \"%V\" "
400403
401404 u->headers_in.status_n = 200;
402405 u->state->status = 200;
403 u->buffer.pos = p + 1;
406 u->buffer.pos = p + sizeof(CRLF) - 1;
404407
405408 return NGX_OK;
406409 }
409412 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
410413 "key: \"%V\" was not found by memcached", &ctx->key);
411414
415 u->headers_in.content_length_n = 0;
412416 u->headers_in.status_n = 404;
413417 u->state->status = 404;
418 u->buffer.pos = p + sizeof("END" CRLF) - 1;
414419 u->keepalive = 1;
415420
416421 return NGX_OK;
434439
435440 u = ctx->request->upstream;
436441
437 u->length += NGX_HTTP_MEMCACHED_END;
442 if (u->headers_in.status_n != 404) {
443 u->length = u->headers_in.content_length_n + NGX_HTTP_MEMCACHED_END;
444 ctx->rest = NGX_HTTP_MEMCACHED_END;
445
446 } else {
447 u->length = 0;
448 }
438449
439450 return NGX_OK;
440451 }
508519 return NGX_OK;
509520 }
510521
511 last += u->length - NGX_HTTP_MEMCACHED_END;
522 last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
512523
513524 if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
514525 ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
2626 #define NGX_HTTP_MP4_CTTS_ATOM 15
2727 #define NGX_HTTP_MP4_CTTS_DATA 16
2828 #define NGX_HTTP_MP4_STSC_ATOM 17
29 #define NGX_HTTP_MP4_STSC_CHUNK 18
29 #define NGX_HTTP_MP4_STSC_START 18
3030 #define NGX_HTTP_MP4_STSC_DATA 19
31 #define NGX_HTTP_MP4_STSZ_ATOM 20
32 #define NGX_HTTP_MP4_STSZ_DATA 21
33 #define NGX_HTTP_MP4_STCO_ATOM 22
34 #define NGX_HTTP_MP4_STCO_DATA 23
35 #define NGX_HTTP_MP4_CO64_ATOM 24
36 #define NGX_HTTP_MP4_CO64_DATA 25
31 #define NGX_HTTP_MP4_STSC_END 20
32 #define NGX_HTTP_MP4_STSZ_ATOM 21
33 #define NGX_HTTP_MP4_STSZ_DATA 22
34 #define NGX_HTTP_MP4_STCO_ATOM 23
35 #define NGX_HTTP_MP4_STCO_DATA 24
36 #define NGX_HTTP_MP4_CO64_ATOM 25
37 #define NGX_HTTP_MP4_CO64_DATA 26
3738
3839 #define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
3940
6162 uint32_t chunks;
6263
6364 ngx_uint_t start_sample;
65 ngx_uint_t end_sample;
6466 ngx_uint_t start_chunk;
65 ngx_uint_t chunk_samples;
66 uint64_t chunk_samples_size;
67 ngx_uint_t end_chunk;
68 ngx_uint_t start_chunk_samples;
69 ngx_uint_t end_chunk_samples;
70 uint64_t start_chunk_samples_size;
71 uint64_t end_chunk_samples_size;
6772 off_t start_offset;
73 off_t end_offset;
6874
6975 size_t tkhd_size;
7076 size_t mdhd_size;
94100 ngx_buf_t ctts_atom_buf;
95101 ngx_buf_t ctts_data_buf;
96102 ngx_buf_t stsc_atom_buf;
97 ngx_buf_t stsc_chunk_buf;
103 ngx_buf_t stsc_start_chunk_buf;
104 ngx_buf_t stsc_end_chunk_buf;
98105 ngx_buf_t stsc_data_buf;
99106 ngx_buf_t stsz_atom_buf;
100107 ngx_buf_t stsz_data_buf;
103110 ngx_buf_t co64_atom_buf;
104111 ngx_buf_t co64_data_buf;
105112
106 ngx_mp4_stsc_entry_t stsc_chunk_entry;
113 ngx_mp4_stsc_entry_t stsc_start_chunk_entry;
114 ngx_mp4_stsc_entry_t stsc_end_chunk_entry;
107115 } ngx_http_mp4_trak_t;
108116
109117
120128 off_t end;
121129 off_t content_length;
122130 ngx_uint_t start;
131 ngx_uint_t length;
123132 uint32_t timescale;
124133 ngx_http_request_t *request;
125134 ngx_array_t trak;
156165 #define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8)
157166 #define ngx_mp4_atom_data(mp4) mp4->buffer_pos
158167 #define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8)
159 #define ngx_mp4_atom_next(mp4, n) mp4->buffer_pos += n; mp4->offset += n
168
169
170 #define ngx_mp4_atom_next(mp4, n) \
171 mp4->buffer_pos += (size_t) n; \
172 mp4->offset += n
160173
161174
162175 #define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \
200213 #define ngx_mp4_last_trak(mp4) \
201214 &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1]
202215
216
217 static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r);
203218
204219 static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
205220 static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
212227 static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
213228 uint64_t atom_data_size);
214229 static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
215 off_t start_offset);
230 off_t start_offset, off_t end_offset);
216231 static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
217232 uint64_t atom_data_size);
218233 static ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4,
251266 uint64_t atom_data_size);
252267 static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
253268 ngx_http_mp4_trak_t *trak);
269 static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
270 ngx_http_mp4_trak_t *trak, ngx_uint_t start);
254271 static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
255272 uint64_t atom_data_size);
256273 static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
257274 ngx_http_mp4_trak_t *trak);
275 static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
276 ngx_http_mp4_trak_t *trak, ngx_uint_t start);
258277 static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
259278 uint64_t atom_data_size);
260279 static void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
261280 ngx_http_mp4_trak_t *trak);
281 static void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
282 ngx_http_mp4_trak_t *trak, ngx_uint_t start);
262283 static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
263284 uint64_t atom_data_size);
264285 static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
265286 ngx_http_mp4_trak_t *trak);
287 static ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
288 ngx_http_mp4_trak_t *trak, ngx_uint_t start);
266289 static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
267290 uint64_t atom_data_size);
268291 static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
279302 ngx_http_mp4_trak_t *trak);
280303 static void ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4,
281304 ngx_http_mp4_trak_t *trak, off_t adjustment);
305
282306 static char *ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
283307 static void *ngx_http_mp4_create_conf(ngx_conf_t *cf);
284308 static char *ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child);
309
285310
286311 static ngx_command_t ngx_http_mp4_commands[] = {
287312
394419 {
395420 u_char *last;
396421 size_t root;
397 ngx_int_t rc, start;
398 ngx_uint_t level;
422 ngx_int_t rc, start, end;
423 ngx_uint_t level, length;
399424 ngx_str_t path, value;
400425 ngx_log_t *log;
401426 ngx_buf_t *b;
500525 r->allow_ranges = 1;
501526
502527 start = -1;
528 length = 0;
503529 r->headers_out.content_length_n = of.size;
504530 mp4 = NULL;
505531 b = NULL;
517543 ngx_set_errno(0);
518544 start = (int) (strtod((char *) value.data, NULL) * 1000);
519545
520 if (ngx_errno == 0 && start >= 0) {
521 r->allow_ranges = 0;
522
523 mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t));
524 if (mp4 == NULL) {
525 return NGX_HTTP_INTERNAL_SERVER_ERROR;
546 if (ngx_errno != 0) {
547 start = -1;
548 }
549 }
550
551 if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) {
552
553 ngx_set_errno(0);
554 end = (int) (strtod((char *) value.data, NULL) * 1000);
555
556 if (ngx_errno != 0) {
557 end = -1;
558 }
559
560 if (end > 0) {
561 if (start < 0) {
562 start = 0;
526563 }
527564
528 mp4->file.fd = of.fd;
529 mp4->file.name = path;
530 mp4->file.log = r->connection->log;;
531 mp4->end = of.size;
532 mp4->start = (ngx_uint_t) start;
533 mp4->request = r;
534
535 switch (ngx_http_mp4_process(mp4)) {
536
537 case NGX_DECLINED:
538 if (mp4->buffer) {
539 ngx_pfree(r->pool, mp4->buffer);
540 }
541
542 ngx_pfree(r->pool, mp4);
543 mp4 = NULL;
544
545 break;
546
547 case NGX_OK:
548 r->headers_out.content_length_n = mp4->content_length;
549 break;
550
551 default: /* NGX_ERROR */
552 if (mp4->buffer) {
553 ngx_pfree(r->pool, mp4->buffer);
554 }
555
556 ngx_pfree(r->pool, mp4);
557
558 return NGX_HTTP_INTERNAL_SERVER_ERROR;
565 if (end > start) {
566 length = end - start;
559567 }
560568 }
569 }
570 }
571
572 if (start >= 0) {
573 r->single_range = 1;
574
575 mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t));
576 if (mp4 == NULL) {
577 return NGX_HTTP_INTERNAL_SERVER_ERROR;
578 }
579
580 mp4->file.fd = of.fd;
581 mp4->file.name = path;
582 mp4->file.log = r->connection->log;
583 mp4->end = of.size;
584 mp4->start = (ngx_uint_t) start;
585 mp4->length = length;
586 mp4->request = r;
587
588 switch (ngx_http_mp4_process(mp4)) {
589
590 case NGX_DECLINED:
591 if (mp4->buffer) {
592 ngx_pfree(r->pool, mp4->buffer);
593 }
594
595 ngx_pfree(r->pool, mp4);
596 mp4 = NULL;
597
598 break;
599
600 case NGX_OK:
601 r->headers_out.content_length_n = mp4->content_length;
602 break;
603
604 default: /* NGX_ERROR */
605 if (mp4->buffer) {
606 ngx_pfree(r->pool, mp4->buffer);
607 }
608
609 ngx_pfree(r->pool, mp4);
610
611 return NGX_HTTP_INTERNAL_SERVER_ERROR;
561612 }
562613 }
563614
637688 static ngx_int_t
638689 ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
639690 {
640 off_t start_offset, adjustment;
691 off_t start_offset, end_offset, adjustment;
641692 ngx_int_t rc;
642693 ngx_uint_t i, j;
643694 ngx_chain_t **prev;
644695 ngx_http_mp4_trak_t *trak;
645696 ngx_http_mp4_conf_t *conf;
646697
647 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
648 "mp4 start:%ui", mp4->start);
698 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
699 "mp4 start:%ui, length:%ui", mp4->start, mp4->length);
649700
650701 conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
651702
687738 }
688739
689740 start_offset = mp4->end;
741 end_offset = 0;
690742 trak = mp4->trak.elts;
691743
692744 for (i = 0; i < mp4->trak.nelts; i++) {
734786 start_offset = trak[i].start_offset;
735787 }
736788
789 if (end_offset < trak[i].end_offset) {
790 end_offset = trak[i].end_offset;
791 }
792
737793 *prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM];
738794 prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next;
739795
745801 }
746802 }
747803
804 if (end_offset < start_offset) {
805 end_offset = start_offset;
806 }
807
748808 mp4->moov_size += 8;
749809
750810 ngx_mp4_set_32value(mp4->moov_atom_header, mp4->moov_size);
761821 }
762822
763823 adjustment = mp4->ftyp_size + mp4->moov_size
764 + ngx_http_mp4_update_mdat_atom(mp4, start_offset)
824 + ngx_http_mp4_update_mdat_atom(mp4, start_offset, end_offset)
765825 - start_offset;
766826
767827 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
9471007 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom");
9481008
9491009 if (atom_data_size > 1024
950 || ngx_mp4_atom_data(mp4) + atom_data_size > mp4->buffer_end)
1010 || ngx_mp4_atom_data(mp4) + (size_t) atom_data_size > mp4->buffer_end)
9511011 {
9521012 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
9531013 "\"%s\" mp4 ftyp atom is too large:%uL",
10051065
10061066 no_mdat = (mp4->mdat_atom.buf == NULL);
10071067
1008 if (no_mdat && mp4->start == 0) {
1068 if (no_mdat && mp4->start == 0 && mp4->length == 0) {
10091069 /*
10101070 * send original file if moov atom resides before
10111071 * mdat atom and client requests integral file
11041164
11051165
11061166 static size_t
1107 ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset)
1167 ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset,
1168 off_t end_offset)
11081169 {
11091170 off_t atom_data_size;
11101171 u_char *atom_header;
11121173 uint64_t atom_size;
11131174 ngx_buf_t *atom;
11141175
1115 atom_data_size = mp4->mdat_data.buf->file_last - start_offset;
1176 atom_data_size = end_offset - start_offset;
11161177 mp4->mdat_data.buf->file_pos = start_offset;
1178 mp4->mdat_data.buf->file_last = end_offset;
11171179
11181180 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
11191181 "mdat new offset @%O:%O", start_offset, atom_data_size);
11201182
11211183 atom_header = mp4->mdat_atom_header;
11221184
1123 if ((uint64_t) atom_data_size > 0xffffffff) {
1185 if ((uint64_t) atom_data_size > (uint64_t) 0xffffffff) {
11241186 atom_size = 1;
11251187 atom_header_size = sizeof(ngx_mp4_atom_header64_t);
11261188 ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t),
11951257 u_char *atom_header;
11961258 size_t atom_size;
11971259 uint32_t timescale;
1198 uint64_t duration;
1260 uint64_t duration, start_time, length_time;
11991261 ngx_buf_t *atom;
12001262 ngx_mp4_mvhd_atom_t *mvhd_atom;
12011263 ngx_mp4_mvhd64_atom_t *mvhd64_atom;
12381300 "mvhd timescale:%uD, duration:%uL, time:%.3fs",
12391301 timescale, duration, (double) duration / timescale);
12401302
1241 duration -= (uint64_t) mp4->start * timescale / 1000;
1303 start_time = (uint64_t) mp4->start * timescale / 1000;
1304
1305 if (duration < start_time) {
1306 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
1307 "\"%s\" mp4 start time exceeds file duration",
1308 mp4->file.name.data);
1309 return NGX_ERROR;
1310 }
1311
1312 duration -= start_time;
1313
1314 if (mp4->length) {
1315 length_time = (uint64_t) mp4->length * timescale / 1000;
1316
1317 if (duration > length_time) {
1318 duration = length_time;
1319 }
1320 }
12421321
12431322 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
12441323 "mvhd new duration:%uL, time:%.3fs",
12951374
12961375 trak->out[NGX_HTTP_MP4_TRAK_ATOM].buf = atom;
12971376
1298 atom_end = mp4->buffer_pos + atom_data_size;
1377 atom_end = mp4->buffer_pos + (size_t) atom_data_size;
12991378 atom_file_end = mp4->offset + atom_data_size;
13001379
13011380 rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_trak_atoms, atom_data_size);
13851464 {
13861465 u_char *atom_header;
13871466 size_t atom_size;
1388 uint64_t duration;
1467 uint64_t duration, start_time, length_time;
13891468 ngx_buf_t *atom;
13901469 ngx_http_mp4_trak_t *trak;
13911470 ngx_mp4_tkhd_atom_t *tkhd_atom;
14251504 "tkhd duration:%uL, time:%.3fs",
14261505 duration, (double) duration / mp4->timescale);
14271506
1428 duration -= (uint64_t) mp4->start * mp4->timescale / 1000;
1507 start_time = (uint64_t) mp4->start * mp4->timescale / 1000;
1508
1509 if (duration <= start_time) {
1510 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1511 "tkhd duration is less than start time");
1512 return NGX_DECLINED;
1513 }
1514
1515 duration -= start_time;
1516
1517 if (mp4->length) {
1518 length_time = (uint64_t) mp4->length * mp4->timescale / 1000;
1519
1520 if (duration > length_time) {
1521 duration = length_time;
1522 }
1523 }
14291524
14301525 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
14311526 "tkhd new duration:%uL, time:%.3fs",
15281623 u_char *atom_header;
15291624 size_t atom_size;
15301625 uint32_t timescale;
1531 uint64_t duration;
1626 uint64_t duration, start_time, length_time;
15321627 ngx_buf_t *atom;
15331628 ngx_http_mp4_trak_t *trak;
15341629 ngx_mp4_mdhd_atom_t *mdhd_atom;
15701665 "mdhd timescale:%uD, duration:%uL, time:%.3fs",
15711666 timescale, duration, (double) duration / timescale);
15721667
1573 duration -= (uint64_t) mp4->start * timescale / 1000;
1668 start_time = (uint64_t) mp4->start * timescale / 1000;
1669
1670 if (duration <= start_time) {
1671 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1672 "mdhd duration is less than start time");
1673 return NGX_DECLINED;
1674 }
1675
1676 duration -= start_time;
1677
1678 if (mp4->length) {
1679 length_time = (uint64_t) mp4->length * timescale / 1000;
1680
1681 if (duration > length_time) {
1682 duration = length_time;
1683 }
1684 }
15741685
15751686 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
15761687 "mdhd new duration:%uL, time:%.3fs",
19432054 ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
19442055 ngx_http_mp4_trak_t *trak)
19452056 {
1946 size_t atom_size;
1947 uint32_t entries, count, duration;
1948 uint64_t start_time;
1949 ngx_buf_t *atom, *data;
1950 ngx_uint_t start_sample;
1951 ngx_mp4_stts_atom_t *stts_atom;
1952 ngx_mp4_stts_entry_t *entry, *end;
2057 size_t atom_size;
2058 ngx_buf_t *atom, *data;
2059 ngx_mp4_stts_atom_t *stts_atom;
19532060
19542061 /*
19552062 * mdia.minf.stbl.stts updating requires trak->timescale
19682075 return NGX_ERROR;
19692076 }
19702077
2078 if (ngx_http_mp4_crop_stts_data(mp4, trak, 1) != NGX_OK) {
2079 return NGX_ERROR;
2080 }
2081
2082 if (ngx_http_mp4_crop_stts_data(mp4, trak, 0) != NGX_OK) {
2083 return NGX_ERROR;
2084 }
2085
2086 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2087 "time-to-sample entries:%uD", trak->time_to_sample_entries);
2088
2089 atom_size = sizeof(ngx_mp4_stts_atom_t) + (data->last - data->pos);
2090 trak->size += atom_size;
2091
2092 atom = trak->out[NGX_HTTP_MP4_STTS_ATOM].buf;
2093 stts_atom = (ngx_mp4_stts_atom_t *) atom->pos;
2094 ngx_mp4_set_32value(stts_atom->size, atom_size);
2095 ngx_mp4_set_32value(stts_atom->entries, trak->time_to_sample_entries);
2096
2097 return NGX_OK;
2098 }
2099
2100
2101 static ngx_int_t
2102 ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
2103 ngx_http_mp4_trak_t *trak, ngx_uint_t start)
2104 {
2105 uint32_t count, duration, rest;
2106 uint64_t start_time;
2107 ngx_buf_t *data;
2108 ngx_uint_t start_sample, entries, start_sec;
2109 ngx_mp4_stts_entry_t *entry, *end;
2110
2111 if (start) {
2112 start_sec = mp4->start;
2113
2114 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2115 "mp4 stts crop start_time:%ui", start_sec);
2116
2117 } else if (mp4->length) {
2118 start_sec = mp4->length;
2119
2120 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2121 "mp4 stts crop end_time:%ui", start_sec);
2122
2123 } else {
2124 return NGX_OK;
2125 }
2126
2127 data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
2128
2129 start_time = (uint64_t) start_sec * trak->timescale / 1000;
2130
19712131 entries = trak->time_to_sample_entries;
1972 start_time = (uint64_t) mp4->start * trak->timescale / 1000;
1973
1974 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1975 "time-to-sample start_time:%uL", start_time);
1976
19772132 start_sample = 0;
19782133 entry = (ngx_mp4_stts_entry_t *) data->pos;
19792134 end = (ngx_mp4_stts_entry_t *) data->last;
19822137 count = ngx_mp4_get_32value(entry->count);
19832138 duration = ngx_mp4_get_32value(entry->duration);
19842139
1985 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
1986 "count:%uD, duration:%uD", count, duration);
2140 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2141 "time:%uL, count:%uD, duration:%uD",
2142 start_time, count, duration);
19872143
19882144 if (start_time < (uint64_t) count * duration) {
19892145 start_sample += (ngx_uint_t) (start_time / duration);
1990 count -= (uint32_t) (start_time / duration);
1991 ngx_mp4_set_32value(entry->count, count);
2146 rest = (uint32_t) (start_time / duration);
19922147 goto found;
19932148 }
19942149
19982153 entry++;
19992154 }
20002155
2001 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2002 "start time is out mp4 stts samples in \"%s\"",
2003 mp4->file.name.data);
2004
2005 return NGX_ERROR;
2156 if (start) {
2157 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2158 "start time is out mp4 stts samples in \"%s\"",
2159 mp4->file.name.data);
2160
2161 return NGX_ERROR;
2162
2163 } else {
2164 trak->end_sample = trak->start_sample + start_sample;
2165
2166 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2167 "end_sample:%ui", trak->end_sample);
2168
2169 return NGX_OK;
2170 }
20062171
20072172 found:
20082173
2009 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2010 "start_sample:%ui, new count:%uD", start_sample, count);
2011
2012 trak->start_sample = start_sample;
2013
2014 data->pos = (u_char *) entry;
2015 atom_size = sizeof(ngx_mp4_stts_atom_t) + (data->last - data->pos);
2016 trak->size += atom_size;
2017
2018 atom = trak->out[NGX_HTTP_MP4_STTS_ATOM].buf;
2019 stts_atom = (ngx_mp4_stts_atom_t *) atom->pos;
2020 ngx_mp4_set_32value(stts_atom->size, atom_size);
2021 ngx_mp4_set_32value(stts_atom->entries, entries);
2174 if (start) {
2175 ngx_mp4_set_32value(entry->count, count - rest);
2176 data->pos = (u_char *) entry;
2177 trak->time_to_sample_entries = entries;
2178 trak->start_sample = start_sample;
2179
2180 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2181 "start_sample:%ui, new count:%uD",
2182 trak->start_sample, count - rest);
2183
2184 } else {
2185 ngx_mp4_set_32value(entry->count, rest);
2186 data->last = (u_char *) (entry + 1);
2187 trak->time_to_sample_entries -= entries - 1;
2188 trak->end_sample = trak->start_sample + start_sample;
2189
2190 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2191 "end_sample:%ui, new count:%uD",
2192 trak->end_sample, rest);
2193 }
20222194
20232195 return NGX_OK;
20242196 }
21002272 ngx_http_mp4_trak_t *trak)
21012273 {
21022274 size_t atom_size;
2103 uint32_t entries, sample, start_sample, *entry, *end;
2275 uint32_t sample, start_sample, *entry, *end;
21042276 ngx_buf_t *atom, *data;
21052277 ngx_http_mp4_stss_atom_t *stss_atom;
21062278
21192291 return NGX_OK;
21202292 }
21212293
2294 ngx_http_mp4_crop_stss_data(mp4, trak, 1);
2295 ngx_http_mp4_crop_stss_data(mp4, trak, 0);
2296
2297 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2298 "sync sample entries:%uD", trak->sync_samples_entries);
2299
2300 if (trak->sync_samples_entries) {
2301 entry = (uint32_t *) data->pos;
2302 end = (uint32_t *) data->last;
2303
2304 start_sample = trak->start_sample;
2305
2306 while (entry < end) {
2307 sample = ngx_mp4_get_32value(entry);
2308 sample -= start_sample;
2309 ngx_mp4_set_32value(entry, sample);
2310 entry++;
2311 }
2312
2313 } else {
2314 trak->out[NGX_HTTP_MP4_STSS_DATA].buf = NULL;
2315 }
2316
2317 atom_size = sizeof(ngx_http_mp4_stss_atom_t) + (data->last - data->pos);
2318 trak->size += atom_size;
2319
2320 atom = trak->out[NGX_HTTP_MP4_STSS_ATOM].buf;
2321 stss_atom = (ngx_http_mp4_stss_atom_t *) atom->pos;
2322
2323 ngx_mp4_set_32value(stss_atom->size, atom_size);
2324 ngx_mp4_set_32value(stss_atom->entries, trak->sync_samples_entries);
2325
2326 return NGX_OK;
2327 }
2328
2329
2330 static void
2331 ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
2332 ngx_http_mp4_trak_t *trak, ngx_uint_t start)
2333 {
2334 uint32_t sample, start_sample, *entry, *end;
2335 ngx_buf_t *data;
2336 ngx_uint_t entries;
2337
21222338 /* sync samples starts from 1 */
2123 start_sample = trak->start_sample + 1;
2339
2340 if (start) {
2341 start_sample = trak->start_sample + 1;
2342
2343 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2344 "mp4 stss crop start_sample:%uD", start_sample);
2345
2346 } else if (mp4->length) {
2347 start_sample = trak->end_sample + 1;
2348
2349 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2350 "mp4 stss crop end_sample:%uD", start_sample);
2351
2352 } else {
2353 return;
2354 }
2355
2356 data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
2357
21242358 entries = trak->sync_samples_entries;
2125
21262359 entry = (uint32_t *) data->pos;
21272360 end = (uint32_t *) data->last;
21282361
21292362 while (entry < end) {
21302363 sample = ngx_mp4_get_32value(entry);
21312364
2132 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2133 "start:%uD, sync:%uD", start_sample, sample);
2365 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2366 "sync:%uD", sample);
21342367
21352368 if (sample >= start_sample) {
21362369 goto found;
21402373 entry++;
21412374 }
21422375
2143 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2144 "start sample is out of mp4 stss atom in \"%s\"",
2145 mp4->file.name.data);
2146
2147 return NGX_ERROR;
2376 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2377 "sample is out of mp4 stss atom");
21482378
21492379 found:
21502380
2151 data->pos = (u_char *) entry;
2152
2153 start_sample = trak->start_sample;
2154
2155 while (entry < end) {
2156 sample = ngx_mp4_get_32value(entry);
2157 sample -= start_sample;
2158 ngx_mp4_set_32value(entry, sample);
2159 entry++;
2160 }
2161
2162 atom_size = sizeof(ngx_http_mp4_stss_atom_t) + (data->last - data->pos);
2163 trak->size += atom_size;
2164
2165 atom = trak->out[NGX_HTTP_MP4_STSS_ATOM].buf;
2166 stss_atom = (ngx_http_mp4_stss_atom_t *) atom->pos;
2167
2168 ngx_mp4_set_32value(stss_atom->size, atom_size);
2169 ngx_mp4_set_32value(stss_atom->entries, entries);
2170
2171 return NGX_OK;
2381 if (start) {
2382 data->pos = (u_char *) entry;
2383 trak->sync_samples_entries = entries;
2384
2385 } else {
2386 data->last = (u_char *) entry;
2387 trak->sync_samples_entries -= entries;
2388 }
21722389 }
21732390
21742391
22522469 ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
22532470 ngx_http_mp4_trak_t *trak)
22542471 {
2255 size_t atom_size;
2256 uint32_t entries, count, start_sample;
2257 ngx_buf_t *atom, *data;
2258 ngx_mp4_ctts_atom_t *ctts_atom;
2259 ngx_mp4_ctts_entry_t *entry, *end;
2472 size_t atom_size;
2473 ngx_buf_t *atom, *data;
2474 ngx_mp4_ctts_atom_t *ctts_atom;
22602475
22612476 /*
22622477 * mdia.minf.stbl.ctts updating requires trak->start_sample
22732488 return;
22742489 }
22752490
2491 ngx_http_mp4_crop_ctts_data(mp4, trak, 1);
2492 ngx_http_mp4_crop_ctts_data(mp4, trak, 0);
2493
2494 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2495 "composition offset entries:%uD",
2496 trak->composition_offset_entries);
2497
2498 if (trak->composition_offset_entries == 0) {
2499 trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL;
2500 trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = NULL;
2501 return;
2502 }
2503
2504 atom_size = sizeof(ngx_mp4_ctts_atom_t) + (data->last - data->pos);
2505 trak->size += atom_size;
2506
2507 atom = trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf;
2508 ctts_atom = (ngx_mp4_ctts_atom_t *) atom->pos;
2509
2510 ngx_mp4_set_32value(ctts_atom->size, atom_size);
2511 ngx_mp4_set_32value(ctts_atom->entries, trak->composition_offset_entries);
2512
2513 return;
2514 }
2515
2516
2517 static void
2518 ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
2519 ngx_http_mp4_trak_t *trak, ngx_uint_t start)
2520 {
2521 uint32_t count, start_sample, rest;
2522 ngx_buf_t *data;
2523 ngx_uint_t entries;
2524 ngx_mp4_ctts_entry_t *entry, *end;
2525
22762526 /* sync samples starts from 1 */
2277 start_sample = trak->start_sample + 1;
2527
2528 if (start) {
2529 start_sample = trak->start_sample + 1;
2530
2531 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2532 "mp4 ctts crop start_sample:%uD", start_sample);
2533
2534 } else if (mp4->length) {
2535 start_sample = trak->end_sample - trak->start_sample + 1;
2536
2537 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2538 "mp4 ctts crop end_sample:%uD", start_sample);
2539
2540 } else {
2541 return;
2542 }
2543
2544 data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
2545
22782546 entries = trak->composition_offset_entries;
22792547 entry = (ngx_mp4_ctts_entry_t *) data->pos;
22802548 end = (ngx_mp4_ctts_entry_t *) data->last;
22832551 count = ngx_mp4_get_32value(entry->count);
22842552
22852553 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2286 "start:%uD, count:%uD, offset:%uD",
2554 "sample:%uD, count:%uD, offset:%uD",
22872555 start_sample, count, ngx_mp4_get_32value(entry->offset));
22882556
22892557 if (start_sample <= count) {
2290 count -= (start_sample - 1);
2291 ngx_mp4_set_32value(entry->count, count);
2558 rest = start_sample - 1;
22922559 goto found;
22932560 }
22942561
22972564 entry++;
22982565 }
22992566
2300 trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL;
2301 trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = NULL;
2567 if (start) {
2568 data->pos = (u_char *) end;
2569 trak->composition_offset_entries = 0;
2570 }
23022571
23032572 return;
23042573
23052574 found:
23062575
2307 data->pos = (u_char *) entry;
2308 atom_size = sizeof(ngx_mp4_ctts_atom_t) + (data->last - data->pos);
2309 trak->size += atom_size;
2310
2311 atom = trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf;
2312 ctts_atom = (ngx_mp4_ctts_atom_t *) atom->pos;
2313
2314 ngx_mp4_set_32value(ctts_atom->size, atom_size);
2315 ngx_mp4_set_32value(ctts_atom->entries, entries);
2316
2317 return;
2576 if (start) {
2577 ngx_mp4_set_32value(entry->count, count - rest);
2578 data->pos = (u_char *) entry;
2579 trak->composition_offset_entries = entries;
2580
2581 } else {
2582 ngx_mp4_set_32value(entry->count, rest);
2583 data->last = (u_char *) (entry + 1);
2584 trak->composition_offset_entries -= entries - 1;
2585 }
23182586 }
23192587
23202588
23932661 ngx_http_mp4_trak_t *trak)
23942662 {
23952663 size_t atom_size;
2396 uint32_t start_sample, entries, chunk, samples, id,
2397 next_chunk, n;
2398 ngx_buf_t *atom, *data, *buf;
2664 uint32_t chunk;
2665 ngx_buf_t *atom, *data;
23992666 ngx_mp4_stsc_atom_t *stsc_atom;
2400 ngx_mp4_stsc_entry_t *entry, *first, *end;
2667 ngx_mp4_stsc_entry_t *entry, *end;
24012668
24022669 /*
24032670 * mdia.minf.stbl.stsc updating requires trak->start_sample
24242691 return NGX_ERROR;
24252692 }
24262693
2427 start_sample = (uint32_t) trak->start_sample;
2694 if (ngx_http_mp4_crop_stsc_data(mp4, trak, 1) != NGX_OK) {
2695 return NGX_ERROR;
2696 }
2697
2698 if (ngx_http_mp4_crop_stsc_data(mp4, trak, 0) != NGX_OK) {
2699 return NGX_ERROR;
2700 }
2701
2702 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2703 "sample-to-chunk entries:%uD",
2704 trak->sample_to_chunk_entries);
2705
2706 entry = (ngx_mp4_stsc_entry_t *) data->pos;
2707 end = (ngx_mp4_stsc_entry_t *) data->last;
2708
2709 while (entry < end) {
2710 chunk = ngx_mp4_get_32value(entry->chunk);
2711 chunk -= trak->start_chunk;
2712 ngx_mp4_set_32value(entry->chunk, chunk);
2713 entry++;
2714 }
2715
2716 atom_size = sizeof(ngx_mp4_stsc_atom_t)
2717 + trak->sample_to_chunk_entries * sizeof(ngx_mp4_stsc_entry_t);
2718
2719 trak->size += atom_size;
2720
2721 atom = trak->out[NGX_HTTP_MP4_STSC_ATOM].buf;
2722 stsc_atom = (ngx_mp4_stsc_atom_t *) atom->pos;
2723
2724 ngx_mp4_set_32value(stsc_atom->size, atom_size);
2725 ngx_mp4_set_32value(stsc_atom->entries, trak->sample_to_chunk_entries);
2726
2727 return NGX_OK;
2728 }
2729
2730
2731 static ngx_int_t
2732 ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
2733 ngx_http_mp4_trak_t *trak, ngx_uint_t start)
2734 {
2735 uint32_t start_sample, chunk, samples, id, next_chunk, n,
2736 prev_samples;
2737 ngx_buf_t *data, *buf;
2738 ngx_uint_t entries, target_chunk, chunk_samples;
2739 ngx_mp4_stsc_entry_t *entry, *end, *first;
2740
24282741 entries = trak->sample_to_chunk_entries - 1;
2742
2743 if (start) {
2744 start_sample = (uint32_t) trak->start_sample;
2745
2746 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2747 "mp4 stsc crop start_sample:%uD", start_sample);
2748
2749 } else if (mp4->length) {
2750 start_sample = (uint32_t) (trak->end_sample - trak->start_sample);
2751 samples = 0;
2752
2753 data = trak->out[NGX_HTTP_MP4_STSC_START].buf;
2754
2755 if (data) {
2756 entry = (ngx_mp4_stsc_entry_t *) data->pos;
2757 samples = ngx_mp4_get_32value(entry->samples);
2758 entries--;
2759
2760 if (samples > start_sample) {
2761 samples = start_sample;
2762 ngx_mp4_set_32value(entry->samples, samples);
2763 }
2764
2765 start_sample -= samples;
2766 }
2767
2768 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2769 "mp4 stsc crop end_sample:%uD, ext_samples:%uD",
2770 start_sample, samples);
2771
2772 } else {
2773 return NGX_OK;
2774 }
2775
2776 data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
24292777
24302778 entry = (ngx_mp4_stsc_entry_t *) data->pos;
24312779 end = (ngx_mp4_stsc_entry_t *) data->last;
24332781 chunk = ngx_mp4_get_32value(entry->chunk);
24342782 samples = ngx_mp4_get_32value(entry->samples);
24352783 id = ngx_mp4_get_32value(entry->id);
2784 prev_samples = 0;
24362785 entry++;
24372786
24382787 while (entry < end) {
24402789 next_chunk = ngx_mp4_get_32value(entry->chunk);
24412790
24422791 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2443 "start_sample:%uD, chunk:%uD, chunks:%uD, "
2792 "sample:%uD, chunk:%uD, chunks:%uD, "
24442793 "samples:%uD, id:%uD",
24452794 start_sample, chunk, next_chunk - chunk, samples, id);
24462795
24472796 n = (next_chunk - chunk) * samples;
24482797
2449 if (start_sample <= n) {
2798 if (start_sample < n) {
24502799 goto found;
24512800 }
24522801
24532802 start_sample -= n;
24542803
2804 prev_samples = samples;
24552805 chunk = next_chunk;
24562806 samples = ngx_mp4_get_32value(entry->samples);
24572807 id = ngx_mp4_get_32value(entry->id);
24592809 entry++;
24602810 }
24612811
2462 next_chunk = trak->chunks;
2812 next_chunk = trak->chunks + 1;
24632813
24642814 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2465 "start_sample:%uD, chunk:%uD, chunks:%uD, samples:%uD",
2815 "sample:%uD, chunk:%uD, chunks:%uD, samples:%uD",
24662816 start_sample, chunk, next_chunk - chunk, samples);
24672817
24682818 n = (next_chunk - chunk) * samples;
24692819
24702820 if (start_sample > n) {
24712821 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
2472 "start time is out mp4 stsc chunks in \"%s\"",
2473 mp4->file.name.data);
2822 "%s time is out mp4 stsc chunks in \"%s\"",
2823 start ? "start" : "end", mp4->file.name.data);
24742824 return NGX_ERROR;
24752825 }
24762826
24862836 return NGX_ERROR;
24872837 }
24882838
2489 trak->start_chunk = chunk - 1;
2490
2491 trak->start_chunk += start_sample / samples;
2492 trak->chunk_samples = start_sample % samples;
2493
2494 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2495 "start chunk:%ui, samples:%uD",
2496 trak->start_chunk, trak->chunk_samples);
2497
2498 data->pos = (u_char *) entry;
2499 atom_size = sizeof(ngx_mp4_stsc_atom_t) + (data->last - data->pos);
2500
2501 ngx_mp4_set_32value(entry->chunk, 1);
2502
2503 if (trak->chunk_samples && next_chunk - trak->start_chunk == 2) {
2504
2505 /* last chunk in the entry */
2506
2507 ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples);
2508
2509 } else if (trak->chunk_samples) {
2510
2511 first = &trak->stsc_chunk_entry;
2839 target_chunk = chunk - 1;
2840 target_chunk += start_sample / samples;
2841 chunk_samples = start_sample % samples;
2842
2843 if (start) {
2844 data->pos = (u_char *) entry;
2845
2846 trak->sample_to_chunk_entries = entries;
2847 trak->start_chunk = target_chunk;
2848 trak->start_chunk_samples = chunk_samples;
2849
2850 ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
2851
2852 samples -= chunk_samples;
2853
2854 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2855 "start_chunk:%ui, start_chunk_samples:%ui",
2856 trak->start_chunk, trak->start_chunk_samples);
2857
2858 } else {
2859 if (start_sample) {
2860 data->last = (u_char *) (entry + 1);
2861 trak->sample_to_chunk_entries -= entries - 1;
2862 trak->end_chunk_samples = samples;
2863
2864 } else {
2865 data->last = (u_char *) entry;
2866 trak->sample_to_chunk_entries -= entries;
2867 trak->end_chunk_samples = prev_samples;
2868 }
2869
2870 if (chunk_samples) {
2871 trak->end_chunk = target_chunk + 1;
2872 trak->end_chunk_samples = chunk_samples;
2873
2874 } else {
2875 trak->end_chunk = target_chunk;
2876 }
2877
2878 samples = chunk_samples;
2879 next_chunk = chunk + 1;
2880
2881 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2882 "end_chunk:%ui, end_chunk_samples:%ui",
2883 trak->end_chunk, trak->end_chunk_samples);
2884 }
2885
2886 if (chunk_samples && next_chunk - target_chunk == 2) {
2887
2888 ngx_mp4_set_32value(entry->samples, samples);
2889
2890 } else if (chunk_samples && start) {
2891
2892 first = &trak->stsc_start_chunk_entry;
25122893 ngx_mp4_set_32value(first->chunk, 1);
2513 ngx_mp4_set_32value(first->samples, samples - trak->chunk_samples);
2894 ngx_mp4_set_32value(first->samples, samples);
25142895 ngx_mp4_set_32value(first->id, id);
25152896
2516 buf = &trak->stsc_chunk_buf;
2897 buf = &trak->stsc_start_chunk_buf;
25172898 buf->temporary = 1;
25182899 buf->pos = (u_char *) first;
25192900 buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
25202901
2521 trak->out[NGX_HTTP_MP4_STSC_CHUNK].buf = buf;
2522
2523 ngx_mp4_set_32value(entry->chunk, 2);
2524
2525 entries++;
2526 atom_size += sizeof(ngx_mp4_stsc_entry_t);
2527 }
2528
2529 while (++entry < end) {
2530 chunk = ngx_mp4_get_32value(entry->chunk);
2531 chunk -= trak->start_chunk;
2532 ngx_mp4_set_32value(entry->chunk, chunk);
2533 }
2534
2535 trak->size += atom_size;
2536
2537 atom = trak->out[NGX_HTTP_MP4_STSC_ATOM].buf;
2538 stsc_atom = (ngx_mp4_stsc_atom_t *) atom->pos;
2539
2540 ngx_mp4_set_32value(stsc_atom->size, atom_size);
2541 ngx_mp4_set_32value(stsc_atom->entries, entries);
2902 trak->out[NGX_HTTP_MP4_STSC_START].buf = buf;
2903
2904 ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 2);
2905
2906 trak->sample_to_chunk_entries++;
2907
2908 } else if (chunk_samples) {
2909
2910 first = &trak->stsc_end_chunk_entry;
2911 ngx_mp4_set_32value(first->chunk, trak->end_chunk - trak->start_chunk);
2912 ngx_mp4_set_32value(first->samples, samples);
2913 ngx_mp4_set_32value(first->id, id);
2914
2915 buf = &trak->stsc_end_chunk_buf;
2916 buf->temporary = 1;
2917 buf->pos = (u_char *) first;
2918 buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
2919
2920 trak->out[NGX_HTTP_MP4_STSC_END].buf = buf;
2921
2922 trak->sample_to_chunk_entries++;
2923 }
25422924
25432925 return NGX_OK;
25442926 }
26343016 ngx_http_mp4_trak_t *trak)
26353017 {
26363018 size_t atom_size;
2637 uint32_t *pos, *end;
3019 uint32_t *pos, *end, entries;
26383020 ngx_buf_t *atom, *data;
26393021 ngx_mp4_stsz_atom_t *stsz_atom;
26403022
26503032 data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
26513033
26523034 if (data) {
2653 if (trak->start_sample > trak->sample_sizes_entries) {
3035 entries = trak->sample_sizes_entries;
3036
3037 if (trak->start_sample > entries) {
26543038 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
26553039 "start time is out mp4 stsz samples in \"%s\"",
26563040 mp4->file.name.data);
26573041 return NGX_ERROR;
26583042 }
26593043
3044 entries -= trak->start_sample;
26603045 data->pos += trak->start_sample * sizeof(uint32_t);
26613046 end = (uint32_t *) data->pos;
26623047
2663 for (pos = end - trak->chunk_samples; pos < end; pos++) {
2664 trak->chunk_samples_size += ngx_mp4_get_32value(pos);
3048 for (pos = end - trak->start_chunk_samples; pos < end; pos++) {
3049 trak->start_chunk_samples_size += ngx_mp4_get_32value(pos);
26653050 }
26663051
26673052 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2668 "chunk samples sizes:%uL", trak->chunk_samples_size);
3053 "chunk samples sizes:%uL",
3054 trak->start_chunk_samples_size);
3055
3056 if (mp4->length) {
3057 if (trak->end_sample - trak->start_sample > entries) {
3058 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
3059 "end time is out mp4 stsz samples in \"%s\"",
3060 mp4->file.name.data);
3061 return NGX_ERROR;
3062 }
3063
3064 entries = trak->end_sample - trak->start_sample;
3065 data->last = data->pos + entries * sizeof(uint32_t);
3066 end = (uint32_t *) data->last;
3067
3068 for (pos = end - trak->end_chunk_samples; pos < end; pos++) {
3069 trak->end_chunk_samples_size += ngx_mp4_get_32value(pos);
3070 }
3071
3072 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
3073 "mp4 stsz end_chunk_samples_size:%uL",
3074 trak->end_chunk_samples_size);
3075 }
26693076
26703077 atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
26713078 trak->size += atom_size;
26743081 stsz_atom = (ngx_mp4_stsz_atom_t *) atom->pos;
26753082
26763083 ngx_mp4_set_32value(stsz_atom->size, atom_size);
2677 ngx_mp4_set_32value(stsz_atom->entries,
2678 trak->sample_sizes_entries - trak->start_sample);
3084 ngx_mp4_set_32value(stsz_atom->entries, entries);
26793085 }
26803086
26813087 return NGX_OK;
27563162 ngx_http_mp4_trak_t *trak)
27573163 {
27583164 size_t atom_size;
3165 uint32_t entries;
27593166 ngx_buf_t *atom, *data;
27603167 ngx_mp4_stco_atom_t *stco_atom;
27613168
27853192 }
27863193
27873194 data->pos += trak->start_chunk * sizeof(uint32_t);
3195
3196 trak->start_offset = ngx_mp4_get_32value(data->pos);
3197 trak->start_offset += trak->start_chunk_samples_size;
3198 ngx_mp4_set_32value(data->pos, trak->start_offset);
3199
3200 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
3201 "start chunk offset:%O", trak->start_offset);
3202
3203 if (mp4->length) {
3204
3205 if (trak->end_chunk > trak->chunks) {
3206 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
3207 "end time is out mp4 stco chunks in \"%s\"",
3208 mp4->file.name.data);
3209 return NGX_ERROR;
3210 }
3211
3212 entries = trak->end_chunk - trak->start_chunk;
3213 data->last = data->pos + entries * sizeof(uint32_t);
3214
3215 if (entries) {
3216 trak->end_offset =
3217 ngx_mp4_get_32value(data->last - sizeof(uint32_t));
3218 trak->end_offset += trak->end_chunk_samples_size;
3219
3220 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
3221 "end chunk offset:%O", trak->end_offset);
3222 }
3223
3224 } else {
3225 entries = trak->chunks - trak->start_chunk;
3226 trak->end_offset = mp4->mdat_data.buf->file_last;
3227 }
3228
3229 if (entries == 0) {
3230 trak->start_offset = mp4->end;
3231 trak->end_offset = 0;
3232 }
3233
27883234 atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
27893235 trak->size += atom_size;
27903236
2791 trak->start_offset = ngx_mp4_get_32value(data->pos);
2792 trak->start_offset += trak->chunk_samples_size;
2793 ngx_mp4_set_32value(data->pos, trak->start_offset);
2794
2795 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2796 "start chunk offset:%uD", trak->start_offset);
2797
27983237 atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf;
27993238 stco_atom = (ngx_mp4_stco_atom_t *) atom->pos;
28003239
28013240 ngx_mp4_set_32value(stco_atom->size, atom_size);
2802 ngx_mp4_set_32value(stco_atom->entries, trak->chunks - trak->start_chunk);
3241 ngx_mp4_set_32value(stco_atom->entries, entries);
28033242
28043243 return NGX_OK;
28053244 }
29073346 ngx_http_mp4_trak_t *trak)
29083347 {
29093348 size_t atom_size;
3349 uint64_t entries;
29103350 ngx_buf_t *atom, *data;
29113351 ngx_mp4_co64_atom_t *co64_atom;
29123352
29363376 }
29373377
29383378 data->pos += trak->start_chunk * sizeof(uint64_t);
3379
3380 trak->start_offset = ngx_mp4_get_64value(data->pos);
3381 trak->start_offset += trak->start_chunk_samples_size;
3382 ngx_mp4_set_64value(data->pos, trak->start_offset);
3383
3384 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
3385 "start chunk offset:%O", trak->start_offset);
3386
3387 if (mp4->length) {
3388
3389 if (trak->end_chunk > trak->chunks) {
3390 ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
3391 "end time is out mp4 co64 chunks in \"%s\"",
3392 mp4->file.name.data);
3393 return NGX_ERROR;
3394 }
3395
3396 entries = trak->end_chunk - trak->start_chunk;
3397 data->last = data->pos + entries * sizeof(uint64_t);
3398
3399 if (entries) {
3400 trak->end_offset =
3401 ngx_mp4_get_64value(data->last - sizeof(uint64_t));
3402 trak->end_offset += trak->end_chunk_samples_size;
3403
3404 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
3405 "end chunk offset:%O", trak->end_offset);
3406 }
3407
3408 } else {
3409 entries = trak->chunks - trak->start_chunk;
3410 trak->end_offset = mp4->mdat_data.buf->file_last;
3411 }
3412
3413 if (entries == 0) {
3414 trak->start_offset = mp4->end;
3415 trak->end_offset = 0;
3416 }
3417
29393418 atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
29403419 trak->size += atom_size;
29413420
2942 trak->start_offset = ngx_mp4_get_64value(data->pos);
2943 trak->start_offset += trak->chunk_samples_size;
2944 ngx_mp4_set_64value(data->pos, trak->start_offset);
2945
2946 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
2947 "start chunk offset:%uL", trak->start_offset);
2948
29493421 atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf;
29503422 co64_atom = (ngx_mp4_co64_atom_t *) atom->pos;
29513423
29523424 ngx_mp4_set_32value(co64_atom->size, atom_size);
2953 ngx_mp4_set_32value(co64_atom->entries, trak->chunks - trak->start_chunk);
3425 ngx_mp4_set_32value(co64_atom->entries, entries);
29543426
29553427 return NGX_OK;
29563428 }
7575
7676 ngx_uint_t headers_hash_max_size;
7777 ngx_uint_t headers_hash_bucket_size;
78
79 #if (NGX_HTTP_SSL)
80 ngx_uint_t ssl;
81 ngx_uint_t ssl_protocols;
82 ngx_str_t ssl_ciphers;
83 #endif
7884 } ngx_http_proxy_loc_conf_t;
7985
8086
177183 { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
178184 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
179185 { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
186 { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
180187 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
181188 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
182189 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
183190 { ngx_null_string, 0 }
184191 };
192
193
194 #if (NGX_HTTP_SSL)
195
196 static ngx_conf_bitmask_t ngx_http_proxy_ssl_protocols[] = {
197 { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
198 { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
199 { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
200 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
201 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
202 { ngx_null_string, 0 }
203 };
204
205 #endif
185206
186207
187208 static ngx_conf_enum_t ngx_http_proxy_http_version[] = {
443464 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
444465 NULL },
445466
467 { ngx_string("proxy_cache_revalidate"),
468 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
469 ngx_conf_set_flag_slot,
470 NGX_HTTP_LOC_CONF_OFFSET,
471 offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_revalidate),
472 NULL },
473
446474 #endif
447475
448476 { ngx_string("proxy_temp_path"),
508536 ngx_conf_set_flag_slot,
509537 NGX_HTTP_LOC_CONF_OFFSET,
510538 offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
539 NULL },
540
541 { ngx_string("proxy_ssl_protocols"),
542 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
543 ngx_conf_set_bitmask_slot,
544 NGX_HTTP_LOC_CONF_OFFSET,
545 offsetof(ngx_http_proxy_loc_conf_t, ssl_protocols),
546 &ngx_http_proxy_ssl_protocols },
547
548 { ngx_string("proxy_ssl_ciphers"),
549 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
550 ngx_conf_set_str_slot,
551 NGX_HTTP_LOC_CONF_OFFSET,
552 offsetof(ngx_http_proxy_loc_conf_t, ssl_ciphers),
511553 NULL },
512554
513555 #endif
586628 { ngx_string("Keep-Alive"), ngx_string("") },
587629 { ngx_string("Expect"), ngx_string("") },
588630 { ngx_string("Upgrade"), ngx_string("") },
589 { ngx_string("If-Modified-Since"), ngx_string("") },
631 { ngx_string("If-Modified-Since"),
632 ngx_string("$upstream_cache_last_modified") },
590633 { ngx_string("If-Unmodified-Since"), ngx_string("") },
591634 { ngx_string("If-None-Match"), ngx_string("") },
592635 { ngx_string("If-Match"), ngx_string("") },
9921035
9931036 len += uri_len;
9941037
1038 ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
1039
9951040 ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
9961041
9971042 if (plcf->body_set_len) {
13161361 return NGX_OK;
13171362 }
13181363
1319 if (u->state) {
1364 if (u->state && u->state->status == 0) {
13201365 u->state->status = ctx->status.code;
13211366 }
13221367
15381583 u->pipe->length = 3; /* "0" LF LF */
15391584
15401585 u->input_filter = ngx_http_proxy_non_buffered_chunked_filter;
1541 u->length = -1;
1586 u->length = 1;
15421587
15431588 } else if (u->headers_in.content_length_n == 0) {
15441589 /* empty body: special case as filter won't be called */
15691614 return NGX_OK;
15701615 }
15711616
1572 if (p->free) {
1573 cl = p->free;
1574 b = cl->buf;
1575 p->free = cl->next;
1576 ngx_free_chain(p->pool, cl);
1577
1578 } else {
1579 b = ngx_alloc_buf(p->pool);
1580 if (b == NULL) {
1581 return NGX_ERROR;
1582 }
1583 }
1617 cl = ngx_chain_get_free_buf(p->pool, &p->free);
1618 if (cl == NULL) {
1619 return NGX_ERROR;
1620 }
1621
1622 b = cl->buf;
15841623
15851624 ngx_memcpy(b, buf, sizeof(ngx_buf_t));
15861625 b->shadow = buf;
15891628 b->recycled = 1;
15901629 buf->shadow = b;
15911630
1592 cl = ngx_alloc_chain_link(p->pool);
1593 if (cl == NULL) {
1594 return NGX_ERROR;
1595 }
1596
1597 cl->buf = b;
1598 cl->next = NULL;
1599
16001631 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
16011632
16021633 if (p->in) {
16611692
16621693 /* a chunk has been parsed successfully */
16631694
1664 if (p->free) {
1665 cl = p->free;
1666 b = cl->buf;
1667 p->free = cl->next;
1668 ngx_free_chain(p->pool, cl);
1669
1670 } else {
1671 b = ngx_alloc_buf(p->pool);
1672 if (b == NULL) {
1673 return NGX_ERROR;
1674 }
1675 }
1695 cl = ngx_chain_get_free_buf(p->pool, &p->free);
1696 if (cl == NULL) {
1697 return NGX_ERROR;
1698 }
1699
1700 b = cl->buf;
16761701
16771702 ngx_memzero(b, sizeof(ngx_buf_t));
16781703
16861711 *prev = b;
16871712 prev = &b->shadow;
16881713
1689 cl = ngx_alloc_chain_link(p->pool);
1690 if (cl == NULL) {
1691 return NGX_ERROR;
1692 }
1693
1694 cl->buf = b;
1695 cl->next = NULL;
1696
16971714 if (p->in) {
16981715 *p->last_in = cl;
16991716 } else {
17081725
17091726 if (buf->last - buf->pos >= ctx->chunked.size) {
17101727
1711 buf->pos += ctx->chunked.size;
1728 buf->pos += (size_t) ctx->chunked.size;
17121729 b->last = buf->pos;
17131730 ctx->chunked.size = 0;
17141731
18711888 b->tag = u->output.tag;
18721889
18731890 if (buf->last - buf->pos >= ctx->chunked.size) {
1874 buf->pos += ctx->chunked.size;
1891 buf->pos += (size_t) ctx->chunked.size;
18751892 b->last = buf->pos;
18761893 ctx->chunked.size = 0;
18771894
20762093 v->no_cacheable = 0;
20772094 v->not_found = 0;
20782095
2079 v->data = ngx_pnalloc(r->connection->pool, NGX_OFF_T_LEN);
2096 v->data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
20802097
20812098 if (v->data == NULL) {
20822099 return NGX_ERROR;
23822399 * conf->body_set = NULL;
23832400 * conf->body_source = { 0, NULL };
23842401 * conf->redirects = NULL;
2402 * conf->ssl = 0;
2403 * conf->ssl_protocols = 0;
2404 * conf->ssl_ciphers = { 0, NULL };
23852405 */
23862406
23872407 conf->upstream.store = NGX_CONF_UNSET;
24132433 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
24142434 conf->upstream.cache_lock = NGX_CONF_UNSET;
24152435 conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
2436 conf->upstream.cache_revalidate = NGX_CONF_UNSET;
24162437 #endif
24172438
24182439 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
26562677 ngx_conf_merge_ptr_value(conf->upstream.no_cache,
26572678 prev->upstream.no_cache, NULL);
26582679
2659 if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
2660 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
2661 "\"proxy_no_cache\" functionality has been changed in 0.8.46, "
2662 "now it should be used together with \"proxy_cache_bypass\"");
2663 }
2664
26652680 ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
26662681 prev->upstream.cache_valid, NULL);
26672682
26742689
26752690 ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
26762691 prev->upstream.cache_lock_timeout, 5000);
2692
2693 ngx_conf_merge_value(conf->upstream.cache_revalidate,
2694 prev->upstream.cache_revalidate, 0);
26772695
26782696 #endif
26792697
26972715 #if (NGX_HTTP_SSL)
26982716 ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
26992717 prev->upstream.ssl_session_reuse, 1);
2718
2719 ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
2720 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3
2721 |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
2722 |NGX_SSL_TLSv1_2));
2723
2724 ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
2725 "DEFAULT");
2726
2727 if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) {
2728 return NGX_CONF_ERROR;
2729 }
27002730 #endif
27012731
27022732 ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
31423172 }
31433173
31443174 #if (NGX_HTTP_SSL)
3145 if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
3146 return NGX_CONF_ERROR;
3147 }
3175 plcf->ssl = 1;
31483176 #endif
31493177
31503178 return NGX_CONF_OK;
31573185 } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
31583186
31593187 #if (NGX_HTTP_SSL)
3160 if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) {
3161 return NGX_CONF_ERROR;
3162 }
3188 plcf->ssl = 1;
31633189
31643190 add = 8;
31653191 port = 443;
37413767
37423768 plcf->upstream.ssl->log = cf->log;
37433769
3744 if (ngx_ssl_create(plcf->upstream.ssl,
3745 NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1
3746 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2,
3747 NULL)
3770 if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL)
37483771 != NGX_OK)
37493772 {
3773 return NGX_ERROR;
3774 }
3775
3776 if (SSL_CTX_set_cipher_list(plcf->upstream.ssl->ctx,
3777 (const char *) plcf->ssl_ciphers.data)
3778 == 0)
3779 {
3780 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
3781 "SSL_CTX_set_cipher_list(\"%V\") failed",
3782 &plcf->ssl_ciphers);
37503783 return NGX_ERROR;
37513784 }
37523785
2121 * ... data ...
2222 *
2323 *
24 * the mutlipart format:
24 * the multipart format:
2525 *
2626 * "HTTP/1.0 206 Partial Content" CRLF
2727 * ... header ...
147147 {
148148 time_t if_range_time;
149149 ngx_str_t *if_range, *etag;
150 ngx_uint_t ranges;
150151 ngx_http_core_loc_conf_t *clcf;
151152 ngx_http_range_filter_ctx_t *ctx;
152153
226227 return NGX_ERROR;
227228 }
228229
229 switch (ngx_http_range_parse(r, ctx, clcf->max_ranges)) {
230 ranges = r->single_range ? 1 : clcf->max_ranges;
231
232 switch (ngx_http_range_parse(r, ctx, ranges)) {
230233
231234 case NGX_OK:
232235 ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
431434 + r->headers_out.content_type.len
432435 + sizeof(CRLF "Content-Range: bytes ") - 1;
433436
434 if (r->headers_out.charset.len) {
437 if (r->headers_out.content_type_len == r->headers_out.content_type.len
438 && r->headers_out.charset.len)
439 {
435440 len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
436441 }
437442
450455 * "Content-Range: bytes "
451456 */
452457
453 if (r->headers_out.charset.len) {
458 if (r->headers_out.content_type_len == r->headers_out.content_type.len
459 && r->headers_out.charset.len)
460 {
454461 ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
455462 CRLF "--%0muA" CRLF
456463 "Content-Type: %V; charset=%V" CRLF
460467 &r->headers_out.charset)
461468 - ctx->boundary_header.data;
462469
463 r->headers_out.charset.len = 0;
464
465470 } else if (r->headers_out.content_type.len) {
466471 ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
467472 CRLF "--%0muA" CRLF
500505
501506 r->headers_out.content_type_len = r->headers_out.content_type.len;
502507
508 r->headers_out.charset.len = 0;
509
503510 /* the size of the last boundary CRLF "--0123456789--" CRLF */
504511
505512 len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1;
1212 #define NGX_HTTP_REALIP_XREALIP 0
1313 #define NGX_HTTP_REALIP_XFWD 1
1414 #define NGX_HTTP_REALIP_HEADER 2
15 #define NGX_HTTP_REALIP_PROXY 3
1516
1617
1718 typedef struct {
155156
156157 break;
157158
159 case NGX_HTTP_REALIP_PROXY:
160
161 value = &r->connection->proxy_protocol_addr;
162
163 if (value->len == 0) {
164 return NGX_DECLINED;
165 }
166
167 xfwd = NULL;
168
169 break;
170
158171 default: /* NGX_HTTP_REALIP_HEADER */
159172
160173 part = &r->headers_in.headers.part;
229242
230243 c = r->connection;
231244
232 len = ngx_sock_ntop(addr->sockaddr, text, NGX_SOCKADDR_STRLEN, 0);
245 len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text,
246 NGX_SOCKADDR_STRLEN, 0);
233247 if (len == 0) {
234248 return NGX_HTTP_INTERNAL_SERVER_ERROR;
235249 }
338352
339353 if (ngx_strcmp(value[1].data, "X-Forwarded-For") == 0) {
340354 rlcf->type = NGX_HTTP_REALIP_XFWD;
355 return NGX_CONF_OK;
356 }
357
358 if (ngx_strcmp(value[1].data, "proxy_protocol") == 0) {
359 rlcf->type = NGX_HTTP_REALIP_PROXY;
341360 return NGX_CONF_OK;
342361 }
343362
1111
1212 #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4)
1313
14 #if !(NGX_PCRE)
15
16 #define ngx_regex_t void
17
18 #endif
19
2014
2115 typedef struct {
2216 ngx_hash_combined_t hash;
2317
2418 #if (NGX_PCRE)
2519 ngx_array_t *regex;
20 ngx_array_t *server_name_regex;
2621 #endif
2722
2823 ngx_flag_t no_referer;
2924 ngx_flag_t blocked_referer;
25 ngx_flag_t server_names;
3026
3127 ngx_hash_keys_arrays_t *keys;
3228
4036 void *child);
4137 static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd,
4238 void *conf);
43 static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
44 ngx_str_t *value, ngx_str_t *uri);
45 static char *ngx_http_add_regex_referer(ngx_conf_t *cf,
46 ngx_http_referer_conf_t *rlcf, ngx_str_t *name, ngx_regex_t *regex);
39 static ngx_int_t ngx_http_add_referer(ngx_conf_t *cf,
40 ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri);
41 static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf,
42 ngx_http_referer_conf_t *rlcf, ngx_str_t *name);
43 #if (NGX_PCRE)
44 static ngx_int_t ngx_http_add_regex_server_name(ngx_conf_t *cf,
45 ngx_http_referer_conf_t *rlcf, ngx_http_regex_t *regex);
46 #endif
4747 static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one,
4848 const void *two);
4949
116116 ngx_uint_t i, key;
117117 ngx_http_referer_conf_t *rlcf;
118118 u_char buf[256];
119 #if (NGX_PCRE)
120 ngx_int_t rc;
121 ngx_str_t referer;
122 #endif
119123
120124 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
121125
124128 && rlcf->hash.wc_tail == NULL
125129 #if (NGX_PCRE)
126130 && rlcf->regex == NULL
131 && rlcf->server_name_regex == NULL
127132 #endif
128133 )
129134 {
146151
147152 if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) {
148153 ref += 7;
154 len -= 7;
149155 goto valid_scheme;
150156
151157 } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) {
152158 ref += 8;
159 len -= 8;
153160 goto valid_scheme;
154161 }
155162 }
170177 break;
171178 }
172179
180 if (i == 256) {
181 goto invalid;
182 }
183
173184 buf[i] = ngx_tolower(*p);
174185 key = ngx_hash(key, buf[i++]);
175
176 if (i == 256) {
177 goto invalid;
178 }
179186 }
180187
181188 uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref);
186193
187194 #if (NGX_PCRE)
188195
196 if (rlcf->server_name_regex) {
197 referer.len = p - ref;
198 referer.data = buf;
199
200 rc = ngx_regex_exec_array(rlcf->server_name_regex, &referer,
201 r->connection->log);
202
203 if (rc == NGX_OK) {
204 goto valid;
205 }
206
207 if (rc == NGX_ERROR) {
208 return rc;
209 }
210
211 /* NGX_DECLINED */
212 }
213
189214 if (rlcf->regex) {
190 ngx_int_t rc;
191 ngx_str_t referer;
192
193 referer.len = len - 7;
215 referer.len = len;
194216 referer.data = ref;
195217
196218 rc = ngx_regex_exec_array(rlcf->regex, &referer, r->connection->log);
250272 return NULL;
251273 }
252274
275 /*
276 * set by ngx_pcalloc():
277 *
278 * conf->hash = { NULL };
279 * conf->server_names = 0;
280 * conf->keys = NULL;
281 */
282
253283 #if (NGX_PCRE)
254284 conf->regex = NGX_CONF_UNSET_PTR;
285 conf->server_name_regex = NGX_CONF_UNSET_PTR;
255286 #endif
256287
257288 conf->no_referer = NGX_CONF_UNSET;
269300 ngx_http_referer_conf_t *prev = parent;
270301 ngx_http_referer_conf_t *conf = child;
271302
272 ngx_hash_init_t hash;
303 ngx_uint_t n;
304 ngx_hash_init_t hash;
305 ngx_http_server_name_t *sn;
306 ngx_http_core_srv_conf_t *cscf;
273307
274308 if (conf->keys == NULL) {
275309 conf->hash = prev->hash;
276310
277311 #if (NGX_PCRE)
278312 ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
313 ngx_conf_merge_ptr_value(conf->server_name_regex,
314 prev->server_name_regex, NULL);
279315 #endif
280316 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
281317 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
285321 prev->referer_hash_bucket_size, 64);
286322
287323 return NGX_CONF_OK;
324 }
325
326 if (conf->server_names == 1) {
327 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
328
329 sn = cscf->server_names.elts;
330 for (n = 0; n < cscf->server_names.nelts; n++) {
331
332 #if (NGX_PCRE)
333 if (sn[n].regex) {
334
335 if (ngx_http_add_regex_server_name(cf, conf, sn[n].regex)
336 != NGX_OK)
337 {
338 return NGX_CONF_ERROR;
339 }
340
341 continue;
342 }
343 #endif
344
345 if (ngx_http_add_referer(cf, conf->keys, &sn[n].name, NULL)
346 != NGX_OK)
347 {
348 return NGX_CONF_ERROR;
349 }
350 }
288351 }
289352
290353 if ((conf->no_referer == 1 || conf->blocked_referer == 1)
365428
366429 #if (NGX_PCRE)
367430 ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
431 ngx_conf_merge_ptr_value(conf->server_name_regex, prev->server_name_regex,
432 NULL);
368433 #endif
369434
370435 if (conf->no_referer == NGX_CONF_UNSET) {
388453
389454 u_char *p;
390455 ngx_str_t *value, uri, name;
391 ngx_uint_t i, n;
456 ngx_uint_t i;
392457 ngx_http_variable_t *var;
393 ngx_http_server_name_t *sn;
394 ngx_http_core_srv_conf_t *cscf;
395458
396459 ngx_str_set(&name, "invalid_referer");
397460
398 var = ngx_http_add_variable(cf, &name,
399 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH);
461 var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
400462 if (var == NULL) {
401463 return NGX_CONF_ERROR;
402464 }
436498 continue;
437499 }
438500
439 ngx_str_null(&uri);
440
441501 if (ngx_strcmp(value[i].data, "server_names") == 0) {
442
443 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
444
445 sn = cscf->server_names.elts;
446 for (n = 0; n < cscf->server_names.nelts; n++) {
447
448 #if (NGX_PCRE)
449 if (sn[n].regex) {
450
451 if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name,
452 sn[n].regex->regex)
453 != NGX_OK)
454 {
455 return NGX_CONF_ERROR;
456 }
457
458 continue;
459 }
460 #endif
461
462 if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri)
463 != NGX_OK)
464 {
465 return NGX_CONF_ERROR;
466 }
467 }
468
502 rlcf->server_names = 1;
469503 continue;
470504 }
471505
472506 if (value[i].data[0] == '~') {
473 if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK)
474 {
507 if (ngx_http_add_regex_referer(cf, rlcf, &value[i]) != NGX_OK) {
475508 return NGX_CONF_ERROR;
476509 }
477510
478511 continue;
479512 }
513
514 ngx_str_null(&uri);
480515
481516 p = (u_char *) ngx_strchr(value[i].data, '/');
482517
495530 }
496531
497532
498 static char *
533 static ngx_int_t
499534 ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
500535 ngx_str_t *value, ngx_str_t *uri)
501536 {
502537 ngx_int_t rc;
503538 ngx_str_t *u;
504539
505 if (uri->len == 0) {
540 if (uri == NULL || uri->len == 0) {
506541 u = NGX_HTTP_REFERER_NO_URI_PART;
507542
508543 } else {
509544 u = ngx_palloc(cf->pool, sizeof(ngx_str_t));
510545 if (u == NULL) {
511 return NGX_CONF_ERROR;
546 return NGX_ERROR;
512547 }
513548
514549 *u = *uri;
517552 rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY);
518553
519554 if (rc == NGX_OK) {
520 return NGX_CONF_OK;
555 return NGX_OK;
521556 }
522557
523558 if (rc == NGX_DECLINED) {
530565 "conflicting parameter \"%V\"", value);
531566 }
532567
533 return NGX_CONF_ERROR;
534 }
535
536
537 static char *
568 return NGX_ERROR;
569 }
570
571
572 static ngx_int_t
538573 ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
539 ngx_str_t *name, ngx_regex_t *regex)
574 ngx_str_t *name)
540575 {
541576 #if (NGX_PCRE)
542577 ngx_regex_elt_t *re;
545580
546581 if (name->len == 1) {
547582 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name);
548 return NGX_CONF_ERROR;
583 return NGX_ERROR;
549584 }
550585
551586 if (rlcf->regex == NGX_CONF_UNSET_PTR) {
552587 rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t));
553588 if (rlcf->regex == NULL) {
554 return NGX_CONF_ERROR;
589 return NGX_ERROR;
555590 }
556591 }
557592
558593 re = ngx_array_push(rlcf->regex);
559594 if (re == NULL) {
560 return NGX_CONF_ERROR;
561 }
562
563 if (regex) {
564 re->regex = regex;
565 re->name = name->data;
566
567 return NGX_CONF_OK;
595 return NGX_ERROR;
568596 }
569597
570598 name->len--;
580608
581609 if (ngx_regex_compile(&rc) != NGX_OK) {
582610 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
583 return NGX_CONF_ERROR;
611 return NGX_ERROR;
584612 }
585613
586614 re->regex = rc.regex;
587615 re->name = name->data;
588616
589 return NGX_CONF_OK;
617 return NGX_OK;
590618
591619 #else
592620
594622 "the using of the regex \"%V\" requires PCRE library",
595623 name);
596624
597 return NGX_CONF_ERROR;
598
599 #endif
600 }
625 return NGX_ERROR;
626
627 #endif
628 }
629
630
631 #if (NGX_PCRE)
632
633 static ngx_int_t
634 ngx_http_add_regex_server_name(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
635 ngx_http_regex_t *regex)
636 {
637 ngx_regex_elt_t *re;
638
639 if (rlcf->server_name_regex == NGX_CONF_UNSET_PTR) {
640 rlcf->server_name_regex = ngx_array_create(cf->pool, 2,
641 sizeof(ngx_regex_elt_t));
642 if (rlcf->server_name_regex == NULL) {
643 return NGX_ERROR;
644 }
645 }
646
647 re = ngx_array_push(rlcf->server_name_regex);
648 if (re == NULL) {
649 return NGX_ERROR;
650 }
651
652 re->regex = regex->regex;
653 re->name = regex->name.data;
654
655 return NGX_OK;
656 }
657
658 #endif
601659
602660
603661 static int ngx_libc_cdecl
6464 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
6565 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
6666 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
67 { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
6768 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
6869 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
6970 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
258259 ngx_conf_set_msec_slot,
259260 NGX_HTTP_LOC_CONF_OFFSET,
260261 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
262 NULL },
263
264 { ngx_string("scgi_cache_revalidate"),
265 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
266 ngx_conf_set_flag_slot,
267 NGX_HTTP_LOC_CONF_OFFSET,
268 offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_revalidate),
261269 NULL },
262270
263271 #endif
367375 #if (NGX_HTTP_CACHE)
368376
369377 static ngx_keyval_t ngx_http_scgi_cache_headers[] = {
370 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
378 { ngx_string("HTTP_IF_MODIFIED_SINCE"),
379 ngx_string("$upstream_cache_last_modified") },
371380 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
372381 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
373382 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
391400 ngx_http_status_t *status;
392401 ngx_http_upstream_t *u;
393402 ngx_http_scgi_loc_conf_t *scf;
394
395 if (r->subrequest_in_memory) {
396 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
397 "ngx_http_scgi_module does not support "
398 "subrequests in memory");
399 return NGX_HTTP_INTERNAL_SERVER_ERROR;
400 }
401403
402404 if (ngx_http_upstream_create(r) != NGX_OK) {
403405 return NGX_HTTP_INTERNAL_SERVER_ERROR;
882884 return ngx_http_scgi_process_header(r);
883885 }
884886
885 if (u->state) {
887 if (u->state && u->state->status == 0) {
886888 u->state->status = status->code;
887889 }
888890
10101012 ngx_str_set(&u->headers_in.status_line, "200 OK");
10111013 }
10121014
1013 if (u->state) {
1015 if (u->state && u->state->status == 0) {
10141016 u->state->status = u->headers_in.status_n;
10151017 }
10161018
10981100 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
10991101 conf->upstream.cache_lock = NGX_CONF_UNSET;
11001102 conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
1103 conf->upstream.cache_revalidate = NGX_CONF_UNSET;
11011104 #endif
11021105
11031106 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
13371340
13381341 ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
13391342 prev->upstream.cache_lock_timeout, 5000);
1343
1344 ngx_conf_merge_value(conf->upstream.cache_revalidate,
1345 prev->upstream.cache_revalidate, 0);
13401346
13411347 #endif
13421348
14991505
15001506 s->key = h->key;
15011507 s->value = h->value;
1502 s->skip_empty = 0;
1508 s->skip_empty = 1;
15031509
15041510 next:
15051511
17271733 sc.source = &value[1];
17281734 sc.lengths = &scf->upstream.store_lengths;
17291735 sc.values = &scf->upstream.store_values;
1730 sc.variables = ngx_http_script_variables_count(&value[1]);;
1736 sc.variables = ngx_http_script_variables_count(&value[1]);
17311737 sc.complete_lengths = 1;
17321738 sc.complete_values = 1;
17331739
2020 ngx_flag_t enable;
2121 ngx_flag_t silent_errors;
2222 ngx_flag_t ignore_recycled_buffers;
23 ngx_flag_t last_modified;
2324
2425 ngx_hash_t types;
2526
161162 offsetof(ngx_http_ssi_loc_conf_t, types_keys),
162163 &ngx_http_html_default_types[0] },
163164
165 { ngx_string("ssi_last_modified"),
166 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
167 ngx_conf_set_flag_slot,
168 NGX_HTTP_LOC_CONF_OFFSET,
169 offsetof(ngx_http_ssi_loc_conf_t, last_modified),
170 NULL },
171
164172 ngx_null_command
165173 };
166174
204212 static u_char ngx_http_ssi_string[] = "<!--";
205213
206214 static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
215 static ngx_str_t ngx_http_ssi_timefmt = ngx_string("%A, %d-%b-%Y %H:%M:%S %Z");
207216 static ngx_str_t ngx_http_ssi_null_string = ngx_null_string;
208217
209218
350359 ctx->params.nalloc = NGX_HTTP_SSI_PARAMS_N;
351360 ctx->params.pool = r->pool;
352361
353 ngx_str_set(&ctx->timefmt, "%A, %d-%b-%Y %H:%M:%S %Z");
362 ctx->timefmt = ngx_http_ssi_timefmt;
354363 ngx_str_set(&ctx->errmsg,
355364 "[an error occurred while processing the directive]");
356365
358367
359368 if (r == r->main) {
360369 ngx_http_clear_content_length(r);
361 ngx_http_clear_last_modified(r);
362370 ngx_http_clear_accept_ranges(r);
363371 ngx_http_clear_etag(r);
372
373 if (!slcf->last_modified) {
374 ngx_http_clear_last_modified(r);
375 }
364376 }
365377
366378 return ngx_http_next_header_filter(r);
19701982 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
19711983 ngx_str_t **params)
19721984 {
1973 u_char *dst, *src;
1974 size_t len;
19751985 ngx_int_t rc, key;
19761986 ngx_str_t *uri, *file, *wait, *set, *stub, args;
19771987 ngx_buf_t *b;
20412051 if (rc != NGX_OK) {
20422052 return rc;
20432053 }
2044
2045 dst = uri->data;
2046 src = uri->data;
2047
2048 ngx_unescape_uri(&dst, &src, uri->len, NGX_UNESCAPE_URI);
2049
2050 len = (uri->data + uri->len) - src;
2051 if (len) {
2052 dst = ngx_movemem(dst, src, len);
2053 }
2054
2055 uri->len = dst - uri->data;
20562054
20572055 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
20582056 "ssi include: \"%V\"", uri);
27222720 {
27232721 ngx_http_ssi_ctx_t *ctx;
27242722 ngx_time_t *tp;
2723 ngx_str_t *timefmt;
27252724 struct tm tm;
27262725 char buf[NGX_HTTP_SSI_DATE_LEN];
27272726
27332732
27342733 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
27352734
2736 if (ctx == NULL
2737 || (ctx->timefmt.len == sizeof("%s") - 1
2738 && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's'))
2735 timefmt = ctx ? &ctx->timefmt : &ngx_http_ssi_timefmt;
2736
2737 if (timefmt->len == sizeof("%s") - 1
2738 && timefmt->data[0] == '%' && timefmt->data[1] == 's')
27392739 {
27402740 v->data = ngx_pnalloc(r->pool, NGX_TIME_T_LEN);
27412741 if (v->data == NULL) {
27542754 }
27552755
27562756 v->len = strftime(buf, NGX_HTTP_SSI_DATE_LEN,
2757 (char *) ctx->timefmt.data, &tm);
2757 (char *) timefmt->data, &tm);
27582758 if (v->len == 0) {
27592759 return NGX_ERROR;
27602760 }
28772877 slcf->enable = NGX_CONF_UNSET;
28782878 slcf->silent_errors = NGX_CONF_UNSET;
28792879 slcf->ignore_recycled_buffers = NGX_CONF_UNSET;
2880 slcf->last_modified = NGX_CONF_UNSET;
28802881
28812882 slcf->min_file_chunk = NGX_CONF_UNSET_SIZE;
28822883 slcf->value_len = NGX_CONF_UNSET_SIZE;
28952896 ngx_conf_merge_value(conf->silent_errors, prev->silent_errors, 0);
28962897 ngx_conf_merge_value(conf->ignore_recycled_buffers,
28972898 prev->ignore_recycled_buffers, 0);
2899 ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
28982900
28992901 ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024);
29002902 ngx_conf_merge_size_value(conf->value_len, prev->value_len, 255);
1616 #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
1717 #define NGX_DEFAULT_ECDH_CURVE "prime256v1"
1818
19 #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1"
20
21
22 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
23 static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
24 const unsigned char **out, unsigned char *outlen,
25 const unsigned char *in, unsigned int inlen, void *arg);
26 #endif
1927
2028 #ifdef TLSEXT_TYPE_next_proto_neg
2129 static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
110118 offsetof(ngx_http_ssl_srv_conf_t, ciphers),
111119 NULL },
112120
121 { ngx_string("ssl_buffer_size"),
122 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
123 ngx_conf_set_size_slot,
124 NGX_HTTP_SRV_CONF_OFFSET,
125 offsetof(ngx_http_ssl_srv_conf_t, buffer_size),
126 NULL },
127
113128 { ngx_string("ssl_verify_client"),
114129 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
115130 ngx_conf_set_enum_slot,
118133 &ngx_http_ssl_verify },
119134
120135 { ngx_string("ssl_verify_depth"),
121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
136 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
122137 ngx_conf_set_num_slot,
123138 NGX_HTTP_SRV_CONF_OFFSET,
124139 offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
150165 ngx_http_ssl_session_cache,
151166 NGX_HTTP_SRV_CONF_OFFSET,
152167 0,
168 NULL },
169
170 { ngx_string("ssl_session_tickets"),
171 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
172 ngx_conf_set_flag_slot,
173 NGX_HTTP_SRV_CONF_OFFSET,
174 offsetof(ngx_http_ssl_srv_conf_t, session_tickets),
175 NULL },
176
177 { ngx_string("ssl_session_ticket_key"),
178 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
179 ngx_conf_set_str_array_slot,
180 NGX_HTTP_SRV_CONF_OFFSET,
181 offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys),
153182 NULL },
154183
155184 { ngx_string("ssl_session_timeout"),
240269 { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
241270 (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
242271
272 { ngx_string("ssl_session_reused"), NULL, ngx_http_ssl_variable,
273 (uintptr_t) ngx_ssl_get_session_reused, NGX_HTTP_VAR_CHANGEABLE, 0 },
274
243275 { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
244276 (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
245277
266298 static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
267299
268300
301 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
302
303 static int
304 ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
305 unsigned char *outlen, const unsigned char *in, unsigned int inlen,
306 void *arg)
307 {
308 unsigned int srvlen;
309 unsigned char *srv;
310 #if (NGX_DEBUG)
311 unsigned int i;
312 #endif
313 #if (NGX_HTTP_SPDY)
314 ngx_http_connection_t *hc;
315 #endif
316 #if (NGX_HTTP_SPDY || NGX_DEBUG)
317 ngx_connection_t *c;
318
319 c = ngx_ssl_get_connection(ssl_conn);
320 #endif
321
322 #if (NGX_DEBUG)
323 for (i = 0; i < inlen; i += in[i] + 1) {
324 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
325 "SSL ALPN supported by client: %*s", in[i], &in[i + 1]);
326 }
327 #endif
328
329 #if (NGX_HTTP_SPDY)
330 hc = c->data;
331
332 if (hc->addr_conf->spdy) {
333 srv = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
334 srvlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
335
336 } else
337 #endif
338 {
339 srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
340 srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
341 }
342
343 if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
344 in, inlen)
345 != OPENSSL_NPN_NEGOTIATED)
346 {
347 return SSL_TLSEXT_ERR_NOACK;
348 }
349
350 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
351 "SSL ALPN selected: %*s", *outlen, *out);
352
353 return SSL_TLSEXT_ERR_OK;
354 }
355
356 #endif
357
358
269359 #ifdef TLSEXT_TYPE_next_proto_neg
270
271 #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1"
272360
273361 static int
274362 ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
416504
417505 sscf->enable = NGX_CONF_UNSET;
418506 sscf->prefer_server_ciphers = NGX_CONF_UNSET;
507 sscf->buffer_size = NGX_CONF_UNSET_SIZE;
419508 sscf->verify = NGX_CONF_UNSET_UINT;
420509 sscf->verify_depth = NGX_CONF_UNSET_UINT;
421510 sscf->builtin_session_cache = NGX_CONF_UNSET;
422511 sscf->session_timeout = NGX_CONF_UNSET;
512 sscf->session_tickets = NGX_CONF_UNSET;
513 sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
423514 sscf->stapling = NGX_CONF_UNSET;
424515 sscf->stapling_verify = NGX_CONF_UNSET;
425516
455546 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
456547 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1
457548 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
549
550 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
551 NGX_SSL_BUFSIZE);
458552
459553 ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
460554 ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
533627
534628 #endif
535629
630 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
631 SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL);
632 #endif
633
536634 #ifdef TLSEXT_TYPE_next_proto_neg
537635 SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx,
538636 ngx_http_ssl_npn_advertised, NULL);
560658 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
561659 "SSL_CTX_set_cipher_list(\"%V\") failed",
562660 &conf->ciphers);
563 }
661 return NGX_CONF_ERROR;
662 }
663
664 conf->ssl.buffer_size = conf->buffer_size;
564665
565666 if (conf->verify) {
566667
616717 if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
617718 conf->builtin_session_cache,
618719 conf->shm_zone, conf->session_timeout)
720 != NGX_OK)
721 {
722 return NGX_CONF_ERROR;
723 }
724
725 ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1);
726
727 #ifdef SSL_OP_NO_TICKET
728 if (!conf->session_tickets) {
729 SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
730 }
731 #endif
732
733 ngx_conf_merge_ptr_value(conf->session_ticket_keys,
734 prev->session_ticket_keys, NULL);
735
736 if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
619737 != NGX_OK)
620738 {
621739 return NGX_CONF_ERROR;
2525 ngx_uint_t verify;
2626 ngx_uint_t verify_depth;
2727
28 size_t buffer_size;
29
2830 ssize_t builtin_session_cache;
2931
3032 time_t session_timeout;
4143
4244 ngx_shm_zone_t *shm_zone;
4345
46 ngx_flag_t session_tickets;
47 ngx_array_t *session_ticket_keys;
48
4449 ngx_flag_t stapling;
4550 ngx_flag_t stapling_verify;
4651 ngx_str_t stapling_file;
9797 return rc;
9898 }
9999
100 r->headers_out.content_type_len = sizeof("text/plain") - 1;
100101 ngx_str_set(&r->headers_out.content_type, "text/plain");
102 r->headers_out.content_type_lowcase = NULL;
101103
102104 if (r->method == NGX_HTTP_HEAD) {
103105 r->headers_out.status = NGX_HTTP_OK;
144146 r->headers_out.content_length_n = b->last - b->pos;
145147
146148 b->last_buf = (r == r->main) ? 1 : 0;
149 b->last_in_chain = 1;
147150
148151 rc = ngx_http_send_header(r);
149152
1616 ngx_hash_t types;
1717
1818 ngx_flag_t once;
19 ngx_flag_t last_modified;
1920
2021 ngx_array_t *types_keys;
2122 } ngx_http_sub_loc_conf_t;
8687 ngx_conf_set_flag_slot,
8788 NGX_HTTP_LOC_CONF_OFFSET,
8889 offsetof(ngx_http_sub_loc_conf_t, once),
90 NULL },
91
92 { ngx_string("sub_filter_last_modified"),
93 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
94 ngx_conf_set_flag_slot,
95 NGX_HTTP_LOC_CONF_OFFSET,
96 offsetof(ngx_http_sub_loc_conf_t, last_modified),
8997 NULL },
9098
9199 ngx_null_command
166174
167175 if (r == r->main) {
168176 ngx_http_clear_content_length(r);
169 ngx_http_clear_last_modified(r);
170177 ngx_http_clear_etag(r);
178
179 if (!slcf->last_modified) {
180 ngx_http_clear_last_modified(r);
181 }
171182 }
172183
173184 return ngx_http_next_header_filter(r);
249260 return rc;
250261 }
251262
252 if (ctx->copy_start != ctx->copy_end) {
263 if (ctx->saved.len) {
253264
254265 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
255266 "saved: \"%V\"", &ctx->saved);
256267
257 if (ctx->saved.len) {
258
259 if (ctx->free) {
260 cl = ctx->free;
261 ctx->free = ctx->free->next;
262 b = cl->buf;
263 ngx_memzero(b, sizeof(ngx_buf_t));
264
265 } else {
266 b = ngx_calloc_buf(r->pool);
267 if (b == NULL) {
268 return NGX_ERROR;
269 }
270
271 cl = ngx_alloc_chain_link(r->pool);
272 if (cl == NULL) {
273 return NGX_ERROR;
274 }
275
276 cl->buf = b;
277 }
278
279 b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
280 if (b->pos == NULL) {
281 return NGX_ERROR;
282 }
283
284 ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
285 b->last = b->pos + ctx->saved.len;
286 b->memory = 1;
287
288 *ctx->last_out = cl;
289 ctx->last_out = &cl->next;
290
291 ctx->saved.len = 0;
292 }
293
294 if (ctx->free) {
295 cl = ctx->free;
296 ctx->free = ctx->free->next;
297 b = cl->buf;
298
299 } else {
300 b = ngx_alloc_buf(r->pool);
301 if (b == NULL) {
302 return NGX_ERROR;
303 }
304
305 cl = ngx_alloc_chain_link(r->pool);
306 if (cl == NULL) {
307 return NGX_ERROR;
308 }
309
310 cl->buf = b;
311 }
268 cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
269 if (cl == NULL) {
270 return NGX_ERROR;
271 }
272
273 b = cl->buf;
274
275 ngx_memzero(b, sizeof(ngx_buf_t));
276
277 b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
278 if (b->pos == NULL) {
279 return NGX_ERROR;
280 }
281
282 ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
283 b->last = b->pos + ctx->saved.len;
284 b->memory = 1;
285
286 *ctx->last_out = cl;
287 ctx->last_out = &cl->next;
288
289 ctx->saved.len = 0;
290 }
291
292 if (ctx->copy_start != ctx->copy_end) {
293
294 cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
295 if (cl == NULL) {
296 return NGX_ERROR;
297 }
298
299 b = cl->buf;
312300
313301 ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
314302
323311 b->file_pos += b->pos - ctx->buf->pos;
324312 }
325313
326 cl->next = NULL;
327314 *ctx->last_out = cl;
328315 ctx->last_out = &cl->next;
329316 }
337324 ctx->copy_end = NULL;
338325 }
339326
327 if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) {
328 ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos);
329 ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len);
330 }
331
340332 if (rc == NGX_AGAIN) {
341333 continue;
342334 }
344336
345337 /* rc == NGX_OK */
346338
347 b = ngx_calloc_buf(r->pool);
348 if (b == NULL) {
349 return NGX_ERROR;
350 }
351
352 cl = ngx_alloc_chain_link(r->pool);
339 cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
353340 if (cl == NULL) {
354341 return NGX_ERROR;
355342 }
343
344 b = cl->buf;
345
346 ngx_memzero(b, sizeof(ngx_buf_t));
356347
357348 slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
358349
374365 b->sync = 1;
375366 }
376367
377 cl->buf = b;
378 cl->next = NULL;
379368 *ctx->last_out = cl;
380369 ctx->last_out = &cl->next;
381370
384373 continue;
385374 }
386375
387 if (ctx->buf->last_buf || ngx_buf_in_memory(ctx->buf)) {
376 if (ctx->buf->last_buf && ctx->looked.len) {
377 cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
378 if (cl == NULL) {
379 return NGX_ERROR;
380 }
381
382 b = cl->buf;
383
384 ngx_memzero(b, sizeof(ngx_buf_t));
385
386 b->pos = ctx->looked.data;
387 b->last = b->pos + ctx->looked.len;
388 b->memory = 1;
389
390 *ctx->last_out = cl;
391 ctx->last_out = &cl->next;
392
393 ctx->looked.len = 0;
394 }
395
396 if (ctx->buf->last_buf || ctx->buf->flush
397 || ngx_buf_in_memory(ctx->buf))
398 {
388399 if (b == NULL) {
389 if (ctx->free) {
390 cl = ctx->free;
391 ctx->free = ctx->free->next;
392 b = cl->buf;
393 ngx_memzero(b, sizeof(ngx_buf_t));
394
395 } else {
396 b = ngx_calloc_buf(r->pool);
397 if (b == NULL) {
398 return NGX_ERROR;
399 }
400
401 cl = ngx_alloc_chain_link(r->pool);
402 if (cl == NULL) {
403 return NGX_ERROR;
404 }
405
406 cl->buf = b;
407 }
400 cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
401 if (cl == NULL) {
402 return NGX_ERROR;
403 }
404
405 b = cl->buf;
406
407 ngx_memzero(b, sizeof(ngx_buf_t));
408408
409409 b->sync = 1;
410410
411 cl->next = NULL;
412411 *ctx->last_out = cl;
413412 ctx->last_out = &cl->next;
414413 }
415414
416415 b->last_buf = ctx->buf->last_buf;
416 b->flush = ctx->buf->flush;
417417 b->shadow = ctx->buf;
418418
419419 b->recycled = ctx->buf->recycled;
506506 ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
507507 {
508508 u_char *p, *last, *copy_end, ch, match;
509 size_t looked;
509 size_t looked, i;
510510 ngx_http_sub_state_e state;
511511
512512 if (ctx->once) {
577577 looked++;
578578
579579 if (looked == ctx->match.len) {
580 if ((size_t) (p - ctx->pos) < looked) {
581 ctx->saved.len = 0;
582 }
583580
584581 ctx->state = sub_start_state;
585582 ctx->pos = p + 1;
586583 ctx->looked.len = 0;
584 ctx->saved.len = 0;
587585 ctx->copy_end = copy_end;
588586
589587 if (ctx->copy_start == NULL && copy_end) {
593591 return NGX_OK;
594592 }
595593
596 } else if (ch == ctx->match.data[0]) {
597 copy_end = p;
598 ctx->looked.data[0] = *p;
599 looked = 1;
600
601594 } else {
602 copy_end = p;
603 looked = 0;
604 state = sub_start_state;
605 }
606 }
595 /*
596 * check if there is another partial match in previously
597 * matched substring to catch cases like "aab" in "aaab"
598 */
599
600 ctx->looked.data[looked] = *p;
601 looked++;
602
603 for (i = 1; i < looked; i++) {
604 if (ngx_strncasecmp(ctx->looked.data + i,
605 ctx->match.data, looked - i)
606 == 0)
607 {
608 break;
609 }
610 }
611
612 if (i < looked) {
613 if (ctx->saved.len > i) {
614 ctx->saved.len = i;
615 }
616
617 if ((size_t) (p + 1 - ctx->buf->pos) >= looked - i) {
618 copy_end = p + 1 - (looked - i);
619 }
620
621 ngx_memmove(ctx->looked.data, ctx->looked.data + i, looked - i);
622 looked = looked - i;
623
624 } else {
625 copy_end = p;
626 looked = 0;
627 state = sub_start_state;
628 }
629
630 if (ctx->saved.len) {
631 p++;
632 goto out;
633 }
634 }
635 }
636
637 ctx->saved.len = 0;
638
639 out:
607640
608641 ctx->state = state;
609642 ctx->pos = p;
665698 * set by ngx_pcalloc():
666699 *
667700 * conf->match = { 0, NULL };
668 * conf->sub = { 0, NULL };
669 * conf->sub_lengths = NULL;
670 * conf->sub_values = NULL;
671701 * conf->types = { NULL };
672702 * conf->types_keys = NULL;
673703 */
674704
675705 slcf->once = NGX_CONF_UNSET;
706 slcf->last_modified = NGX_CONF_UNSET;
676707
677708 return slcf;
678709 }
686717
687718 ngx_conf_merge_value(conf->once, prev->once, 1);
688719 ngx_conf_merge_str_value(conf->match, prev->match, "");
720 ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
689721
690722 if (conf->value.value.data == NULL) {
691723 conf->value = prev->value;
173173
174174 for ( ;; ) {
175175
176 for (i = 0; i < iphp->addrlen; i++) {
176 for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) {
177177 hash = (hash * 113 + iphp->addr[i]) % 6271;
178178 }
179179
196196 n = p / (8 * sizeof(uintptr_t));
197197 m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
198198
199 if (!(iphp->rrp.tried[n] & m)) {
200
201 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
202 "get ip hash peer, hash: %ui %04XA", p, m);
203
204 peer = &iphp->rrp.peers->peer[p];
205
206 /* ngx_lock_mutex(iphp->rrp.peers->mutex); */
207
208 if (!peer->down) {
209
210 if (peer->max_fails == 0 || peer->fails < peer->max_fails) {
211 break;
212 }
213
214 if (now - peer->checked > peer->fail_timeout) {
215 peer->checked = now;
216 break;
217 }
218 }
219
220 iphp->rrp.tried[n] |= m;
221
222 /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
223
224 pc->tries--;
225 }
199 if (iphp->rrp.tried[n] & m) {
200 goto next;
201 }
202
203 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
204 "get ip hash peer, hash: %ui %04XA", p, m);
205
206 peer = &iphp->rrp.peers->peer[p];
207
208 /* ngx_lock_mutex(iphp->rrp.peers->mutex); */
209
210 if (peer->down) {
211 goto next_try;
212 }
213
214 if (peer->max_fails
215 && peer->fails >= peer->max_fails
216 && now - peer->checked <= peer->fail_timeout)
217 {
218 goto next_try;
219 }
220
221 break;
222
223 next_try:
224
225 iphp->rrp.tried[n] |= m;
226
227 /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
228
229 pc->tries--;
230
231 next:
226232
227233 if (++iphp->tries >= 20) {
228234 return iphp->get_rr_peer(pc, &iphp->rrp);
234240 pc->sockaddr = peer->sockaddr;
235241 pc->socklen = peer->socklen;
236242 pc->name = &peer->name;
243
244 if (now - peer->checked > peer->fail_timeout) {
245 peer->checked = now;
246 }
237247
238248 /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
239249
8080 { ngx_string("keepalive"),
8181 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12,
8282 ngx_http_upstream_keepalive,
83 0,
83 NGX_HTTP_SRV_CONF_OFFSET,
8484 0,
8585 NULL },
8686
480480 ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
481481 {
482482 ngx_http_upstream_srv_conf_t *uscf;
483 ngx_http_upstream_keepalive_srv_conf_t *kcf;
483 ngx_http_upstream_keepalive_srv_conf_t *kcf = conf;
484484
485485 ngx_int_t n;
486486 ngx_str_t *value;
487487 ngx_uint_t i;
488488
489489 uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
490
491 kcf = ngx_http_conf_upstream_srv_conf(uscf,
492 ngx_http_upstream_keepalive_module);
493490
494491 if (kcf->original_init_upstream) {
495492 return "is duplicate";
3333
3434 ngx_uint_t modifier1;
3535 ngx_uint_t modifier2;
36
37 #if (NGX_HTTP_SSL)
38 ngx_uint_t ssl;
39 ngx_uint_t ssl_protocols;
40 ngx_str_t ssl_ciphers;
41 #endif
3642 } ngx_http_uwsgi_loc_conf_t;
3743
3844
6571 void *conf);
6672 #endif
6773
74 #if (NGX_HTTP_SSL)
75 static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
76 ngx_http_uwsgi_loc_conf_t *uwcf);
77 #endif
78
6879
6980 static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = {
7081 ngx_conf_check_num_bounds, 0, 255
7788 { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
7889 { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
7990 { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
91 { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
8092 { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
8193 { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
8294 { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
8395 { ngx_null_string, 0 }
8496 };
97
98
99 #if (NGX_HTTP_SSL)
100
101 static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = {
102 { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
103 { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
104 { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
105 { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
106 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
107 { ngx_null_string, 0 }
108 };
109
110 #endif
85111
86112
87113 ngx_module_t ngx_http_uwsgi_module;
287313 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
288314 NULL },
289315
316 { ngx_string("uwsgi_cache_revalidate"),
317 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
318 ngx_conf_set_flag_slot,
319 NGX_HTTP_LOC_CONF_OFFSET,
320 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate),
321 NULL },
322
290323 #endif
291324
292325 { ngx_string("uwsgi_temp_path"),
351384 NGX_HTTP_LOC_CONF_OFFSET,
352385 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
353386 &ngx_http_upstream_ignore_headers_masks },
387
388 #if (NGX_HTTP_SSL)
389
390 { ngx_string("uwsgi_ssl_session_reuse"),
391 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
392 ngx_conf_set_flag_slot,
393 NGX_HTTP_LOC_CONF_OFFSET,
394 offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
395 NULL },
396
397 { ngx_string("uwsgi_ssl_protocols"),
398 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
399 ngx_conf_set_bitmask_slot,
400 NGX_HTTP_LOC_CONF_OFFSET,
401 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
402 &ngx_http_uwsgi_ssl_protocols },
403
404 { ngx_string("uwsgi_ssl_ciphers"),
405 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
406 ngx_conf_set_str_slot,
407 NGX_HTTP_LOC_CONF_OFFSET,
408 offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
409 NULL },
410
411 #endif
354412
355413 ngx_null_command
356414 };
400458 #if (NGX_HTTP_CACHE)
401459
402460 static ngx_keyval_t ngx_http_uwsgi_cache_headers[] = {
403 { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
461 { ngx_string("HTTP_IF_MODIFIED_SINCE"),
462 ngx_string("$upstream_cache_last_modified") },
404463 { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
405464 { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
406465 { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
425484 ngx_http_upstream_t *u;
426485 ngx_http_uwsgi_loc_conf_t *uwcf;
427486
428 if (r->subrequest_in_memory) {
429 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
430 "ngx_http_uwsgi_module does not support "
431 "subrequests in memory");
432 return NGX_HTTP_INTERNAL_SERVER_ERROR;
433 }
434
435487 if (ngx_http_upstream_create(r) != NGX_OK) {
436488 return NGX_HTTP_INTERNAL_SERVER_ERROR;
437489 }
445497
446498 uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
447499
448 if (uwcf->uwsgi_lengths) {
500 u = r->upstream;
501
502 if (uwcf->uwsgi_lengths == NULL) {
503
504 #if (NGX_HTTP_SSL)
505 u->ssl = (uwcf->upstream.ssl != NULL);
506
507 if (u->ssl) {
508 ngx_str_set(&u->schema, "suwsgi://");
509
510 } else {
511 ngx_str_set(&u->schema, "uwsgi://");
512 }
513 #else
514 ngx_str_set(&u->schema, "uwsgi://");
515 #endif
516
517 } else {
449518 if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
450519 return NGX_HTTP_INTERNAL_SERVER_ERROR;
451520 }
452521 }
453522
454 u = r->upstream;
455
456 ngx_str_set(&u->schema, "uwsgi://");
457523 u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;
458524
459525 u->conf = &uwcf->upstream;
491557 static ngx_int_t
492558 ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
493559 {
560 size_t add;
494561 ngx_url_t url;
495562 ngx_http_upstream_t *u;
496563
503570 return NGX_ERROR;
504571 }
505572
573 if (url.url.len > 8
574 && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
575 {
576 add = 8;
577
578 } else if (url.url.len > 9
579 && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
580 {
581
582 #if (NGX_HTTP_SSL)
583 add = 9;
584 r->upstream->ssl = 1;
585 #else
586 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
587 "suwsgi protocol requires SSL support");
588 return NGX_ERROR;
589 #endif
590
591 } else {
592 add = 0;
593 }
594
595 u = r->upstream;
596
597 if (add) {
598 u->schema.len = add;
599 u->schema.data = url.url.data;
600
601 url.url.data += add;
602 url.url.len -= add;
603
604 } else {
605 ngx_str_set(&u->schema, "uwsgi://");
606 }
607
506608 url.no_resolve = 1;
507609
508610 if (ngx_parse_url(r->pool, &url) != NGX_OK) {
513615
514616 return NGX_ERROR;
515617 }
516
517 u = r->upstream;
518618
519619 u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
520620 if (u->resolved == NULL) {
9161016 return ngx_http_uwsgi_process_header(r);
9171017 }
9181018
919 if (u->state) {
1019 if (u->state && u->state->status == 0) {
9201020 u->state->status = status->code;
9211021 }
9221022
10441144 ngx_str_set(&u->headers_in.status_line, "200 OK");
10451145 }
10461146
1047 if (u->state) {
1147 if (u->state && u->state->status == 0) {
10481148 u->state->status = u->headers_in.status_n;
10491149 }
10501150
11351235 conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
11361236 conf->upstream.cache_lock = NGX_CONF_UNSET;
11371237 conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
1238 conf->upstream.cache_revalidate = NGX_CONF_UNSET;
11381239 #endif
11391240
11401241 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
11411242 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
11421243
11431244 conf->upstream.intercept_errors = NGX_CONF_UNSET;
1245 #if (NGX_HTTP_SSL)
1246 conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
1247 #endif
11441248
11451249 /* "uwsgi_cyclic_temp_file" is disabled */
11461250 conf->upstream.cyclic_temp_file = 0;
13751479 ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
13761480 prev->upstream.cache_lock_timeout, 5000);
13771481
1482 ngx_conf_merge_value(conf->upstream.cache_revalidate,
1483 prev->upstream.cache_revalidate, 0);
1484
13781485 #endif
13791486
13801487 ngx_conf_merge_value(conf->upstream.pass_request_headers,
13841491
13851492 ngx_conf_merge_value(conf->upstream.intercept_errors,
13861493 prev->upstream.intercept_errors, 0);
1494
1495 #if (NGX_HTTP_SSL)
1496 ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
1497 prev->upstream.ssl_session_reuse, 1);
1498
1499 ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
1500 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3
1501 |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
1502 |NGX_SSL_TLSv1_2));
1503
1504 ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
1505 "DEFAULT");
1506
1507 if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
1508 return NGX_CONF_ERROR;
1509 }
1510
1511 if (conf->upstream.ssl == NULL) {
1512 conf->upstream.ssl = prev->upstream.ssl;
1513 }
1514 #endif
13871515
13881516 ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
13891517
15411669
15421670 s->key = h->key;
15431671 s->value = h->value;
1544 s->skip_empty = 0;
1672 s->skip_empty = 1;
15451673
15461674 next:
15471675
16631791 {
16641792 ngx_http_uwsgi_loc_conf_t *uwcf = conf;
16651793
1794 size_t add;
16661795 ngx_url_t u;
16671796 ngx_str_t *value, *url;
16681797 ngx_uint_t n;
16981827 return NGX_CONF_ERROR;
16991828 }
17001829
1830 #if (NGX_HTTP_SSL)
1831 uwcf->ssl = 1;
1832 #endif
1833
17011834 return NGX_CONF_OK;
17021835 }
17031836
1837 if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) {
1838 add = 8;
1839
1840 } else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) {
1841
1842 #if (NGX_HTTP_SSL)
1843 add = 9;
1844 uwcf->ssl = 1;
1845 #else
1846 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1847 "suwsgi protocol requires SSL support");
1848 return NGX_CONF_ERROR;
1849 #endif
1850
1851 } else {
1852 add = 0;
1853 }
1854
17041855 ngx_memzero(&u, sizeof(ngx_url_t));
17051856
1706 u.url = value[1];
1857 u.url.len = url->len - add;
1858 u.url.data = url->data + add;
17071859 u.no_resolve = 1;
17081860
17091861 uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
17631915 sc.source = &value[1];
17641916 sc.lengths = &uwcf->upstream.store_lengths;
17651917 sc.values = &uwcf->upstream.store_values;
1766 sc.variables = ngx_http_script_variables_count(&value[1]);;
1918 sc.variables = ngx_http_script_variables_count(&value[1]);
17671919 sc.complete_lengths = 1;
17681920 sc.complete_values = 1;
17691921
18371989 }
18381990
18391991 #endif
1992
1993
1994 #if (NGX_HTTP_SSL)
1995
1996 static ngx_int_t
1997 ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
1998 {
1999 ngx_pool_cleanup_t *cln;
2000
2001 uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
2002 if (uwcf->upstream.ssl == NULL) {
2003 return NGX_ERROR;
2004 }
2005
2006 uwcf->upstream.ssl->log = cf->log;
2007
2008 if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
2009 != NGX_OK)
2010 {
2011 return NGX_ERROR;
2012 }
2013
2014 if (SSL_CTX_set_cipher_list(uwcf->upstream.ssl->ctx,
2015 (const char *) uwcf->ssl_ciphers.data)
2016 == 0)
2017 {
2018 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
2019 "SSL_CTX_set_cipher_list(\"%V\") failed",
2020 &uwcf->ssl_ciphers);
2021 return NGX_ERROR;
2022 }
2023
2024 cln = ngx_pool_cleanup_add(cf->pool, 0);
2025 if (cln == NULL) {
2026 return NGX_ERROR;
2027 }
2028
2029 cln->handler = ngx_ssl_cleanup_ctx;
2030 cln->data = uwcf->upstream.ssl;
2031
2032 return NGX_OK;
2033 }
2034
2035 #endif
5757 ngx_hash_t types;
5858 ngx_array_t *types_keys;
5959 ngx_array_t *params; /* ngx_http_xslt_param_t */
60 ngx_flag_t last_modified;
6061 } ngx_http_xslt_filter_loc_conf_t;
6162
6263
102103 static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf);
103104 static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent,
104105 void *child);
106 static ngx_int_t ngx_http_xslt_filter_preconfiguration(ngx_conf_t *cf);
105107 static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf);
106108 static void ngx_http_xslt_filter_exit(ngx_cycle_t *cycle);
107109
149151 offsetof(ngx_http_xslt_filter_loc_conf_t, types_keys),
150152 &ngx_http_xslt_default_types[0] },
151153
154 { ngx_string("xslt_last_modified"),
155 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
156 ngx_conf_set_flag_slot,
157 NGX_HTTP_LOC_CONF_OFFSET,
158 offsetof(ngx_http_xslt_filter_loc_conf_t, last_modified),
159 NULL },
160
152161 ngx_null_command
153162 };
154163
155164
156165 static ngx_http_module_t ngx_http_xslt_filter_module_ctx = {
157 NULL, /* preconfiguration */
166 ngx_http_xslt_filter_preconfiguration, /* preconfiguration */
158167 ngx_http_xslt_filter_init, /* postconfiguration */
159168
160169 ngx_http_xslt_filter_create_main_conf, /* create main configuration */
299308 ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
300309 ngx_buf_t *b)
301310 {
302 ngx_int_t rc;
303 ngx_chain_t out;
304 ngx_pool_cleanup_t *cln;
311 ngx_int_t rc;
312 ngx_chain_t out;
313 ngx_pool_cleanup_t *cln;
314 ngx_http_xslt_filter_loc_conf_t *conf;
305315
306316 ctx->done = 1;
307317
326336 r->headers_out.content_length = NULL;
327337 }
328338
329 ngx_http_clear_last_modified(r);
330339 ngx_http_clear_etag(r);
340
341 conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
342
343 if (!conf->last_modified) {
344 ngx_http_clear_last_modified(r);
345 }
331346 }
332347
333348 rc = ngx_http_next_header_filter(r);
10571072 * conf->params = NULL;
10581073 */
10591074
1075 conf->last_modified = NGX_CONF_UNSET;
1076
10601077 return conf;
10611078 }
10621079
10871104 return NGX_CONF_ERROR;
10881105 }
10891106
1107 ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
1108
10901109 return NGX_CONF_OK;
10911110 }
10921111
10931112
10941113 static ngx_int_t
1095 ngx_http_xslt_filter_init(ngx_conf_t *cf)
1114 ngx_http_xslt_filter_preconfiguration(ngx_conf_t *cf)
10961115 {
10971116 xmlInitParser();
10981117
11001119 exsltRegisterAll();
11011120 #endif
11021121
1122 return NGX_OK;
1123 }
1124
1125
1126 static ngx_int_t
1127 ngx_http_xslt_filter_init(ngx_conf_t *cf)
1128 {
11031129 ngx_http_next_header_filter = ngx_http_top_header_filter;
11041130 ngx_http_top_header_filter = ngx_http_xslt_header_filter;
11051131
260260 sep = ';';
261261 goto multi;
262262 }
263
264 #if (NGX_HTTP_X_FORWARDED_FOR)
263 #if (NGX_HTTP_X_FORWARDED_FOR)
265264 if (hh->offset == offsetof(ngx_http_headers_in_t, x_forwarded_for)) {
266265 sep = ',';
267266 goto multi;
268267 }
269 #endif
268 #endif
270269
271270 if (hh->offset) {
272271
897896
898897 var.len = len;
899898 var.data = lowcase;
900
901 #if (NGX_DEBUG)
899 #if (NGX_DEBUG)
902900
903901 if (value) {
904902 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
907905 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
908906 "perl variable: \"%V\"", &var);
909907 }
910
911 #endif
908 #endif
912909
913910 vv = ngx_http_get_variable(r, &var, hash);
914911 if (vv == NULL) {
420420 return NGX_ERROR;
421421 }
422422
423 asv[0] = (SV *) i;
423 asv[0] = (SV *) (uintptr_t) i;
424424
425425 for (i = 0; args[i]; i++) {
426426 asv[i + 1] = newSVpvn((char *) args[i]->data, args[i]->len);
691691 if (args) {
692692 EXTEND(sp, (intptr_t) args[0]);
693693
694 for (i = 1; i <= (ngx_uint_t) args[0]; i++) {
694 for (i = 1; i <= (uintptr_t) args[0]; i++) {
695695 PUSHs(sv_2mortal(args[i]));
696696 }
697697 }
948948
949949 #endif
950950
951 rc = ngx_strcmp(first->name.data, second->name.data);
951 rc = ngx_filename_cmp(first->name.data, second->name.data,
952 ngx_min(first->name.len, second->name.len) + 1);
952953
953954 if (rc == 0 && !first->exact_match && second->exact_match) {
954955 /* an exact match must be before the same inclusive one */
974975 lq = (ngx_http_location_queue_t *) q;
975976 lx = (ngx_http_location_queue_t *) x;
976977
977 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
978
978 if (lq->name->len == lx->name->len
979 && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len)
980 == 0)
981 {
979982 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
980983 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
981984 "duplicate location \"%V\" in %s:%ui",
10271030 lx = (ngx_http_location_queue_t *) x;
10281031
10291032 if (len > lx->name->len
1030 || (ngx_strncmp(name, lx->name->data, len) != 0))
1033 || ngx_filename_cmp(name, lx->name->data, len) != 0)
10311034 {
10321035 break;
10331036 }
13451348 }
13461349 }
13471350
1348 #if (NGX_HTTP_SPDY && NGX_HTTP_SSL && !defined TLSEXT_TYPE_next_proto_neg)
1351 #if (NGX_HTTP_SPDY && NGX_HTTP_SSL \
1352 && !defined TLSEXT_TYPE_application_layer_protocol_negotiation \
1353 && !defined TLSEXT_TYPE_next_proto_neg)
13491354 if (lsopt->spdy && lsopt->ssl) {
13501355 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1351 "nginx was built without OpenSSL NPN support, "
1352 "SPDY is not enabled for %s", lsopt->addr);
1356 "nginx was built without OpenSSL ALPN or NPN "
1357 "support, SPDY is not enabled for %s", lsopt->addr);
13531358 }
13541359 #endif
13551360
18071812 ls->setfib = addr->opt.setfib;
18081813 #endif
18091814
1815 #if (NGX_HAVE_TCP_FASTOPEN)
1816 ls->fastopen = addr->opt.fastopen;
1817 #endif
1818
18101819 return ls;
18111820 }
18121821
18391848 #if (NGX_HTTP_SPDY)
18401849 addrs[i].conf.spdy = addr[i].opt.spdy;
18411850 #endif
1851 addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
18421852
18431853 if (addr[i].hash.buckets == NULL
18441854 && (addr[i].wc_head == NULL
1818 #define NGX_HTTP_CACHE_EXPIRED 3
1919 #define NGX_HTTP_CACHE_STALE 4
2020 #define NGX_HTTP_CACHE_UPDATING 5
21 #define NGX_HTTP_CACHE_HIT 6
22 #define NGX_HTTP_CACHE_SCARCE 7
21 #define NGX_HTTP_CACHE_REVALIDATED 6
22 #define NGX_HTTP_CACHE_HIT 7
23 #define NGX_HTTP_CACHE_SCARCE 8
2324
2425 #define NGX_HTTP_CACHE_KEY_LEN 16
2526
142143 ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r);
143144 void ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf);
144145 void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf);
146 void ngx_http_file_cache_update_header(ngx_http_request_t *r);
145147 ngx_int_t ngx_http_cache_send(ngx_http_request_t *);
146148 void ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf);
147149 time_t ngx_http_file_cache_valid(ngx_array_t *cache_valid, ngx_uint_t status);
168168 offset = c->busy_sendfile->file_pos;
169169
170170 if (file->aio) {
171 c->aio_sendfile = (offset != file->aio->last_offset);
171 c->busy_count = (offset == file->aio->last_offset) ?
172 c->busy_count + 1 : 0;
172173 file->aio->last_offset = offset;
173174
174 if (c->aio_sendfile == 0) {
175 if (c->busy_count > 2) {
175176 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
176177 "sendfile(%V) returned busy again",
177178 &file->name);
179 c->aio_sendfile = 0;
178180 }
179181 }
180182
11431143 }
11441144
11451145 if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
1146 r->access_code = rc;
1146 if (r->access_code != NGX_HTTP_UNAUTHORIZED) {
1147 r->access_code = rc;
1148 }
11471149
11481150 r->phase_handler++;
11491151 return NGX_AGAIN;
19321934 ngx_int_t
19331935 ngx_http_send_header(ngx_http_request_t *r)
19341936 {
1937 if (r->header_sent) {
1938 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1939 "header already sent");
1940 return NGX_ERROR;
1941 }
1942
19351943 if (r->err_status) {
19361944 r->headers_out.status = r->err_status;
19371945 r->headers_out.status_line.len = 0;
20152023 return NULL;
20162024 }
20172025
2018 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0) != NGX_OK) {
2026 if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, path)
2027 != NGX_OK)
2028 {
20192029 return NULL;
20202030 }
20212031
23572367 }
23582368
23592369
2360 ngx_uint_t
2370 static ngx_uint_t
23612371 ngx_http_gzip_quantity(u_char *p, u_char *last)
23622372 {
23632373 u_char c;
26162626 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
26172627 "rewrite or internal redirection cycle "
26182628 "while redirect to named location \"%V\"", name);
2629
2630 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2631 return NGX_DONE;
2632 }
2633
2634 if (r->uri.len == 0) {
2635 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2636 "empty URI in redirect to named location \"%V\"", name);
26192637
26202638 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
26212639 return NGX_DONE;
30303048 #if (NGX_HAVE_SETFIB)
30313049 lsopt.setfib = -1;
30323050 #endif
3051 #if (NGX_HAVE_TCP_FASTOPEN)
3052 lsopt.fastopen = -1;
3053 #endif
30333054 lsopt.wildcard = 1;
30343055
3035 (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
3056 (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr,
30363057 NGX_SOCKADDR_STRLEN, 1);
30373058
30383059 if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
32103231
32113232 #if (NGX_PCRE)
32123233 if (clcf->regex == NULL
3213 && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
3234 && ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
32143235 #else
3215 if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
3236 if (ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
32163237 #endif
32173238 {
32183239 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
34103431 {
34113432 ngx_http_core_main_conf_t *cmcf = conf;
34123433
3413 if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
3414 cmcf->server_names_hash_max_size = 512;
3415 }
3416
3417 if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
3418 cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
3419 }
3434 ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);
3435 ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size,
3436 ngx_cacheline_size);
34203437
34213438 cmcf->server_names_hash_bucket_size =
34223439 ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
34233440
34243441
3425 if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
3426 cmcf->variables_hash_max_size = 512;
3427 }
3428
3429 if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
3430 cmcf->variables_hash_bucket_size = 64;
3431 }
3442 ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
3443 ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
34323444
34333445 cmcf->variables_hash_bucket_size =
34343446 ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
36973709 prev->types_hash_max_size, 1024);
36983710
36993711 ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
3700 prev->types_hash_bucket_size,
3701 ngx_cacheline_size);
3712 prev->types_hash_bucket_size, 64);
37023713
37033714 conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
37043715 ngx_cacheline_size);
39783989 #if (NGX_HAVE_SETFIB)
39793990 lsopt.setfib = -1;
39803991 #endif
3992 #if (NGX_HAVE_TCP_FASTOPEN)
3993 lsopt.fastopen = -1;
3994 #endif
39813995 lsopt.wildcard = u.wildcard;
39823996 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
39833997 lsopt.ipv6only = 1;
39843998 #endif
39853999
3986 (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
4000 (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr,
39874001 NGX_SOCKADDR_STRLEN, 1);
39884002
39894003 for (n = 2; n < cf->args->nelts; n++) {
40044018 #if (NGX_HAVE_SETFIB)
40054019 if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
40064020 lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
4021 lsopt.set = 1;
4022 lsopt.bind = 1;
40074023
40084024 if (lsopt.setfib == NGX_ERROR) {
40094025 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
40144030 continue;
40154031 }
40164032 #endif
4033
4034 #if (NGX_HAVE_TCP_FASTOPEN)
4035 if (ngx_strncmp(value[n].data, "fastopen=", 9) == 0) {
4036 lsopt.fastopen = ngx_atoi(value[n].data + 9, value[n].len - 9);
4037 lsopt.set = 1;
4038 lsopt.bind = 1;
4039
4040 if (lsopt.fastopen == NGX_ERROR) {
4041 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4042 "invalid fastopen \"%V\"", &value[n]);
4043 return NGX_CONF_ERROR;
4044 }
4045
4046 continue;
4047 }
4048 #endif
4049
40174050 if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
40184051 lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
40194052 lsopt.set = 1;
42434276 #endif
42444277 }
42454278
4279 if (ngx_strcmp(value[n].data, "proxy_protocol") == 0) {
4280 lsopt.proxy_protocol = 1;
4281 continue;
4282 }
4283
42464284 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
42474285 "invalid parameter \"%V\"", &value[n]);
42484286 return NGX_CONF_ERROR;
44684506 { (u_char *) "COPY", (uint32_t) ~NGX_HTTP_COPY },
44694507 { (u_char *) "MOVE", (uint32_t) ~NGX_HTTP_MOVE },
44704508 { (u_char *) "OPTIONS", (uint32_t) ~NGX_HTTP_OPTIONS },
4471 { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
4509 { (u_char *) "PROPFIND", (uint32_t) ~NGX_HTTP_PROPFIND },
44724510 { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
44734511 { (u_char *) "LOCK", (uint32_t) ~NGX_HTTP_LOCK },
44744512 { (u_char *) "UNLOCK", (uint32_t) ~NGX_HTTP_UNLOCK },
48894927 {
48904928 ngx_http_core_loc_conf_t *clcf = conf;
48914929
4892 ngx_str_t *value, name;
4893
4894 if (clcf->error_log) {
4895 return "is duplicate";
4896 }
4897
4898 value = cf->args->elts;
4899
4900 if (ngx_strcmp(value[1].data, "stderr") == 0) {
4901 ngx_str_null(&name);
4902
4903 } else {
4904 name = value[1];
4905 }
4906
4907 clcf->error_log = ngx_log_create(cf->cycle, &name);
4908 if (clcf->error_log == NULL) {
4909 return NGX_CONF_ERROR;
4910 }
4911
4912 if (cf->args->nelts == 2) {
4913 clcf->error_log->log_level = NGX_LOG_ERR;
4914 return NGX_CONF_OK;
4915 }
4916
4917 return ngx_log_set_levels(cf, clcf->error_log);
4930 return ngx_log_set_log(cf, &clcf->error_log);
49184931 }
49194932
49204933
8181 unsigned ipv6only:1;
8282 #endif
8383 unsigned so_keepalive:2;
84 unsigned proxy_protocol:1;
8485
8586 int backlog;
8687 int rcvbuf;
8889 #if (NGX_HAVE_SETFIB)
8990 int setfib;
9091 #endif
92 #if (NGX_HAVE_TCP_FASTOPEN)
93 int fastopen;
94 #endif
9195 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
9296 int tcp_keepidle;
9397 int tcp_keepintvl;
239243 #if (NGX_HTTP_SPDY)
240244 unsigned spdy:1;
241245 #endif
246 unsigned proxy_protocol:1;
242247 };
243248
244249
5252 ngx_string("EXPIRED"),
5353 ngx_string("STALE"),
5454 ngx_string("UPDATING"),
55 ngx_string("REVALIDATED"),
5556 ngx_string("HIT")
5657 };
5758
444445 timer = c->wait_time - ngx_current_msec;
445446
446447 if ((ngx_msec_int_t) timer <= 0) {
447 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
448 "http file cache lock timeout");
448 ngx_log_error(NGX_LOG_INFO, ev->log, 0, "cache lock timeout");
449449 c->lock = 0;
450450 goto wakeup;
451451 }
503503 return NGX_DECLINED;
504504 }
505505
506 if (h->body_start > c->body_start) {
506 if ((size_t) h->body_start > c->body_start) {
507507 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
508508 "cache file \"%s\" has too long header",
509509 c->file.name.data);
874874
875875 c = r->cache;
876876
877 ngx_memzero(h, sizeof(ngx_http_file_cache_header_t));
878
877879 h->valid_sec = c->valid_sec;
878880 h->last_modified = c->last_modified;
879881 h->date = c->date;
966968 c->node->updating = 0;
967969
968970 ngx_shmtx_unlock(&cache->shpool->mutex);
971 }
972
973
974 void
975 ngx_http_file_cache_update_header(ngx_http_request_t *r)
976 {
977 ssize_t n;
978 ngx_err_t err;
979 ngx_file_t file;
980 ngx_file_info_t fi;
981 ngx_http_cache_t *c;
982 ngx_http_file_cache_header_t h;
983
984 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
985 "http file cache update header");
986
987 c = r->cache;
988
989 ngx_memzero(&file, sizeof(ngx_file_t));
990
991 file.name = c->file.name;
992 file.log = r->connection->log;
993 file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, NGX_FILE_OPEN, 0);
994
995 if (file.fd == NGX_INVALID_FILE) {
996 err = ngx_errno;
997
998 /* cache file may have been deleted */
999
1000 if (err == NGX_ENOENT) {
1001 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1002 "http file cache \"%s\" not found",
1003 file.name.data);
1004 return;
1005 }
1006
1007 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
1008 ngx_open_file_n " \"%s\" failed", file.name.data);
1009 return;
1010 }
1011
1012 /*
1013 * make sure cache file wasn't replaced;
1014 * if it was, do nothing
1015 */
1016
1017 if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
1018 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
1019 ngx_fd_info_n " \"%s\" failed", file.name.data);
1020 goto done;
1021 }
1022
1023 if (c->uniq != ngx_file_uniq(&fi)
1024 || c->length != ngx_file_size(&fi))
1025 {
1026 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1027 "http file cache \"%s\" changed",
1028 file.name.data);
1029 goto done;
1030 }
1031
1032 n = ngx_read_file(&file, (u_char *) &h,
1033 sizeof(ngx_http_file_cache_header_t), 0);
1034
1035 if (n == NGX_ERROR) {
1036 goto done;
1037 }
1038
1039 if ((size_t) n != sizeof(ngx_http_file_cache_header_t)) {
1040 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
1041 ngx_read_file_n " read only %z of %z from \"%s\"",
1042 n, sizeof(ngx_http_file_cache_header_t), file.name.data);
1043 goto done;
1044 }
1045
1046 if (h.last_modified != c->last_modified
1047 || h.crc32 != c->crc32
1048 || h.header_start != c->header_start
1049 || h.body_start != c->body_start)
1050 {
1051 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1052 "http file cache \"%s\" content changed",
1053 file.name.data);
1054 goto done;
1055 }
1056
1057 /*
1058 * update cache file header with new data,
1059 * notably h.valid_sec and h.date
1060 */
1061
1062 ngx_memzero(&h, sizeof(ngx_http_file_cache_header_t));
1063
1064 h.valid_sec = c->valid_sec;
1065 h.last_modified = c->last_modified;
1066 h.date = c->date;
1067 h.crc32 = c->crc32;
1068 h.valid_msec = (u_short) c->valid_msec;
1069 h.header_start = (u_short) c->header_start;
1070 h.body_start = (u_short) c->body_start;
1071
1072 (void) ngx_write_file(&file, (u_char *) &h,
1073 sizeof(ngx_http_file_cache_header_t), 0);
1074
1075 done:
1076
1077 if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
1078 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
1079 ngx_close_file_n " \"%s\" failed", file.name.data);
1080 }
9691081 }
9701082
9711083
9191 ngx_string("411 Length Required"),
9292 ngx_string("412 Precondition Failed"),
9393 ngx_string("413 Request Entity Too Large"),
94 ngx_null_string, /* "414 Request-URI Too Large", but we never send it
95 * because we treat such requests as the HTTP/0.9
96 * requests and send only a body without a header
97 */
94 ngx_string("414 Request-URI Too Large"),
9895 ngx_string("415 Unsupported Media Type"),
9996 ngx_string("416 Requested Range Not Satisfiable"),
10097
266263 len += ngx_http_status_lines[status].len;
267264
268265 } else {
269 len += NGX_INT_T_LEN;
266 len += NGX_INT_T_LEN + 1 /* SP */;
267 status_line = NULL;
268 }
269
270 if (status_line && status_line->len == 0) {
271 status = r->headers_out.status;
272 len += NGX_INT_T_LEN + 1 /* SP */;
270273 status_line = NULL;
271274 }
272275 }
447450 b->last = ngx_copy(b->last, status_line->data, status_line->len);
448451
449452 } else {
450 b->last = ngx_sprintf(b->last, "%03ui", status);
453 b->last = ngx_sprintf(b->last, "%03ui ", status);
451454 }
452455 *b->last++ = CR; *b->last++ = LF;
453456
211211 case 5:
212212 if (ngx_str5cmp(m, 'M', 'K', 'C', 'O', 'L')) {
213213 r->method = NGX_HTTP_MKCOL;
214 break;
214215 }
215216
216217 if (ngx_str5cmp(m, 'P', 'A', 'T', 'C', 'H')) {
217218 r->method = NGX_HTTP_PATCH;
219 break;
218220 }
219221
220222 if (ngx_str5cmp(m, 'T', 'R', 'A', 'C', 'E')) {
221223 r->method = NGX_HTTP_TRACE;
224 break;
222225 }
223226
224227 break;
882885 break;
883886 }
884887
888 if (ch == '_') {
889 if (allow_underscores) {
890 hash = ngx_hash(0, ch);
891 r->lowcase_header[0] = ch;
892 i = 1;
893
894 } else {
895 r->invalid_header = 1;
896 }
897
898 break;
899 }
900
885901 if (ch == '\0') {
886902 return NGX_HTTP_PARSE_INVALID_HEADER;
887903 }
12571273 * the line feed
12581274 */
12591275
1260 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1261 "s:%d in:'%Xd:%c', out:'%c'", state, ch, ch, *u);
1276 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1277 "s:%d in:'%Xd:%c'", state, ch, ch);
12621278
12631279 switch (state) {
12641280
17761792 ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
17771793 ngx_str_t *args, ngx_uint_t *flags)
17781794 {
1779 u_char ch, *p;
1780 size_t len;
1795 u_char ch, *p, *src, *dst;
1796 size_t len;
1797 ngx_uint_t quoted;
17811798
17821799 len = uri->len;
17831800 p = uri->data;
1801 quoted = 0;
17841802
17851803 if (len == 0 || p[0] == '?') {
17861804 goto unsafe;
17871805 }
17881806
1789 if (p[0] == '.' && len == 3 && p[1] == '.' && (ngx_path_separator(p[2]))) {
1807 if (p[0] == '.' && len > 1 && p[1] == '.'
1808 && (len == 2 || ngx_path_separator(p[2])))
1809 {
17901810 goto unsafe;
17911811 }
17921812
17931813 for ( /* void */ ; len; len--) {
17941814
17951815 ch = *p++;
1816
1817 if (ch == '%') {
1818 quoted = 1;
1819 continue;
1820 }
17961821
17971822 if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
17981823 continue;
18031828 args->data = p;
18041829 uri->len -= len;
18051830
1806 return NGX_OK;
1831 break;
18071832 }
18081833
18091834 if (ch == '\0') {
18121837
18131838 if (ngx_path_separator(ch) && len > 2) {
18141839
1815 /* detect "/../" */
1816
1817 if (p[0] == '.' && p[1] == '.' && ngx_path_separator(p[2])) {
1840 /* detect "/../" and "/.." */
1841
1842 if (p[0] == '.' && p[1] == '.'
1843 && (len == 3 || ngx_path_separator(p[2])))
1844 {
18181845 goto unsafe;
1846 }
1847 }
1848 }
1849
1850 if (quoted) {
1851 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1852 "escaped URI: \"%V\"", uri);
1853
1854 src = uri->data;
1855
1856 dst = ngx_pnalloc(r->pool, uri->len);
1857 if (dst == NULL) {
1858 return NGX_ERROR;
1859 }
1860
1861 uri->data = dst;
1862
1863 ngx_unescape_uri(&dst, &src, uri->len, 0);
1864
1865 uri->len = dst - uri->data;
1866
1867 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1868 "unescaped URI: \"%V\"", uri);
1869
1870 len = uri->len;
1871 p = uri->data;
1872
1873 if (p[0] == '.' && len > 1 && p[1] == '.'
1874 && (len == 2 || ngx_path_separator(p[2])))
1875 {
1876 goto unsafe;
1877 }
1878
1879 for ( /* void */ ; len; len--) {
1880
1881 ch = *p++;
1882
1883 if (ch == '\0') {
1884 goto unsafe;
1885 }
1886
1887 if (ngx_path_separator(ch) && len > 2) {
1888
1889 /* detect "/../" and "/.." */
1890
1891 if (p[0] == '.' && p[1] == '.'
1892 && (len == 3 || ngx_path_separator(p[2])))
1893 {
1894 goto unsafe;
1895 }
18191896 }
18201897 }
18211898 }
21812258 ctx->length = 3 /* "0" LF LF */;
21822259 break;
21832260 case sw_chunk_size:
2184 ctx->length = 2 /* LF LF */
2185 + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0);
2261 ctx->length = 1 /* LF */
2262 + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */
2263 : 1 /* LF */);
21862264 break;
21872265 case sw_chunk_extension:
21882266 case sw_chunk_extension_almost_done:
6969 #if 0
7070 /* TODO: SSI may pass NULL */
7171 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
72 "http postpone filter NULL inactive request",
73 &r->uri, &r->args);
72 "http postpone filter NULL inactive request");
7473 #endif
7574
7675 return NGX_OK;
107106
108107 if (pr->out == NULL) {
109108 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
110 "http postpone filter NULL output",
111 &r->uri, &r->args);
109 "http postpone filter NULL output");
112110
113111 } else {
114112 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
342342 }
343343 #endif
344344
345 if (hc->addr_conf->proxy_protocol) {
346 hc->proxy_protocol = 1;
347 c->log->action = "reading PROXY protocol";
348 }
349
345350 if (rev->ready) {
346351 /* the deferred accept(), rtsig, aio, iocp */
347352
367372 static void
368373 ngx_http_wait_request_handler(ngx_event_t *rev)
369374 {
375 u_char *p;
370376 size_t size;
371377 ssize_t n;
372378 ngx_buf_t *b;
456462 }
457463
458464 b->last += n;
465
466 if (hc->proxy_protocol) {
467 hc->proxy_protocol = 0;
468
469 p = ngx_proxy_protocol_parse(c, b->pos, b->last);
470
471 if (p == NULL) {
472 ngx_http_close_connection(c);
473 return;
474 }
475
476 b->pos = p;
477
478 if (b->pos == b->last) {
479 c->log->action = "waiting for request";
480 b->pos = b->start;
481 b->last = b->start;
482 ngx_post_event(rev, &ngx_posted_events);
483 return;
484 }
485 }
459486
460487 c->log->action = "reading client request line";
461488
556583 r->start_msec = tp->msec;
557584
558585 r->method = NGX_HTTP_UNKNOWN;
586 r->http_version = NGX_HTTP_VERSION_10;
559587
560588 r->headers_in.content_length_n = -1;
561589 r->headers_in.keep_alive_n = -1;
587615 static void
588616 ngx_http_ssl_handshake(ngx_event_t *rev)
589617 {
590 u_char buf[1];
618 u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
619 size_t size;
591620 ssize_t n;
592621 ngx_err_t err;
593622 ngx_int_t rc;
596625 ngx_http_ssl_srv_conf_t *sscf;
597626
598627 c = rev->data;
628 hc = c->data;
599629
600630 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
601631 "http check ssl handshake");
611641 return;
612642 }
613643
614 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
644 size = hc->proxy_protocol ? sizeof(buf) : 1;
645
646 n = recv(c->fd, (char *) buf, size, MSG_PEEK);
615647
616648 err = ngx_socket_errno;
617649
636668 ngx_http_close_connection(c);
637669
638670 return;
671 }
672
673 if (hc->proxy_protocol) {
674 hc->proxy_protocol = 0;
675
676 p = ngx_proxy_protocol_parse(c, buf, buf + n);
677
678 if (p == NULL) {
679 ngx_http_close_connection(c);
680 return;
681 }
682
683 size = p - buf;
684
685 if (c->recv(c, buf, size) != (ssize_t) size) {
686 ngx_http_close_connection(c);
687 return;
688 }
689
690 c->log->action = "SSL handshaking";
691
692 if (n == (ssize_t) size) {
693 ngx_post_event(rev, &ngx_posted_events);
694 return;
695 }
696
697 n = 1;
698 buf[0] = *p;
639699 }
640700
641701 if (n == 1) {
643703 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
644704 "https ssl handshake: 0x%02Xd", buf[0]);
645705
646 hc = c->data;
647706 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
648707 ngx_http_ssl_module);
649708
703762
704763 c->ssl->no_wait_shutdown = 1;
705764
706 #if (NGX_HTTP_SPDY && defined TLSEXT_TYPE_next_proto_neg)
765 #if (NGX_HTTP_SPDY \
766 && (defined TLSEXT_TYPE_application_layer_protocol_negotiation \
767 || defined TLSEXT_TYPE_next_proto_neg))
707768 {
708769 unsigned int len;
709770 const unsigned char *data;
710771 static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED);
711772
773 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
774 SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
775
776 #ifdef TLSEXT_TYPE_next_proto_neg
777 if (len == 0) {
778 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
779 }
780 #endif
781
782 #else /* TLSEXT_TYPE_next_proto_neg */
712783 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
784 #endif
713785
714786 if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) {
715787 ngx_http_spdy_init(c->read);
19282000 ngx_http_connection_t *hc;
19292001 ngx_http_core_loc_conf_t *clcf;
19302002 ngx_http_core_srv_conf_t *cscf;
2003
2004 #if (NGX_SUPPRESS_WARN)
2005 cscf = NULL;
2006 #endif
19312007
19322008 hc = r->http_connection;
19332009
26692745
26702746 #endif
26712747
2748 #if (NGX_HAVE_EPOLLRDHUP)
2749
2750 if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && rev->pending_eof) {
2751 socklen_t len;
2752
2753 rev->eof = 1;
2754 c->error = 1;
2755
2756 err = 0;
2757 len = sizeof(ngx_err_t);
2758
2759 /*
2760 * BSDs and Linux return 0 and set a pending error in err
2761 * Solaris returns -1 and sets errno
2762 */
2763
2764 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
2765 == -1)
2766 {
2767 err = ngx_socket_errno;
2768 }
2769
2770 goto closed;
2771 }
2772
2773 #endif
2774
26722775 n = recv(c->fd, buf, 1, MSG_PEEK);
26732776
26742777 if (n == 0) {
27092812 ngx_log_error(NGX_LOG_INFO, c->log, err,
27102813 "client prematurely closed connection");
27112814
2712 ngx_http_finalize_request(r, 0);
2815 ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
27132816 }
27142817
27152818
31423245 return;
31433246 }
31443247
3145 timer = (ngx_msec_t) (r->lingering_time - ngx_time());
3146 if (timer <= 0) {
3248 timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
3249 if ((ngx_msec_int_t) timer <= 0) {
31473250 ngx_http_close_request(r, 0);
31483251 return;
31493252 }
33183421 return;
33193422 }
33203423
3321 for (cln = r->cleanup; cln; cln = cln->next) {
3424 cln = r->cleanup;
3425 r->cleanup = NULL;
3426
3427 while (cln) {
33223428 if (cln->handler) {
33233429 cln->handler(cln->data);
33243430 }
3431
3432 cln = cln->next;
33253433 }
33263434
33273435 #if (NGX_STAT_STUB)
308308 ngx_int_t nfree;
309309
310310 #if (NGX_HTTP_SSL)
311 ngx_uint_t ssl; /* unsigned ssl:1; */
312 #endif
311 unsigned ssl:1;
312 #endif
313 unsigned proxy_protocol:1;
313314 } ngx_http_connection_t;
314315
315316
419420 #endif
420421
421422 size_t limit_rate;
423 size_t limit_rate_after;
422424
423425 /* used to learn the Apache compatible response length without a header */
424426 size_t header_size;
525527 unsigned filter_need_in_memory:1;
526528 unsigned filter_need_temporary:1;
527529 unsigned allow_ranges:1;
530 unsigned single_range:1;
528531
529532 #if (NGX_STAT_STUB)
530533 unsigned stat_reading:1;
583586 #define ngx_http_set_connection_log(c, l) \
584587 \
585588 c->log->file = l->file; \
589 c->log->next = l->next; \
586590 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { \
587591 c->log->log_level = l->log_level; \
588592 }
4242 r->main->count++;
4343
4444 #if (NGX_HTTP_SPDY)
45 if (r->spdy_stream) {
45 if (r->spdy_stream && r == r->main) {
4646 rc = ngx_http_spdy_read_request_body(r, post_handler);
4747 goto done;
4848 }
581581 }
582582
583583 if (r->lingering_time) {
584 timer = (ngx_msec_t) (r->lingering_time - ngx_time());
585
586 if (timer <= 0) {
584 timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
585
586 if ((ngx_msec_int_t) timer <= 0) {
587587 r->discard_body = 0;
588588 r->lingering_close = 0;
589589 ngx_http_finalize_request(r, NGX_ERROR);
725725 size = b->last - b->pos;
726726
727727 if ((off_t) size > rb->chunked->size) {
728 b->pos += rb->chunked->size;
728 b->pos += (size_t) rb->chunked->size;
729729 rb->chunked->size = 0;
730730
731731 } else {
764764 size = b->last - b->pos;
765765
766766 if ((off_t) size > r->headers_in.content_length_n) {
767 b->pos += r->headers_in.content_length_n;
767 b->pos += (size_t) r->headers_in.content_length_n;
768768 r->headers_in.content_length_n = 0;
769769
770770 } else {
881881 rb->rest -= size;
882882
883883 } else {
884 cl->buf->pos += rb->rest;
884 cl->buf->pos += (size_t) rb->rest;
885885 rb->rest = 0;
886886 b->last = cl->buf->pos;
887887 b->last_buf = 1;
987987 size = cl->buf->last - cl->buf->pos;
988988
989989 if ((off_t) size > rb->chunked->size) {
990 cl->buf->pos += rb->chunked->size;
990 cl->buf->pos += (size_t) rb->chunked->size;
991991 r->headers_in.content_length_n += rb->chunked->size;
992992 rb->chunked->size = 0;
993993
13261326 {
13271327 ngx_http_script_full_name_code_t *code;
13281328
1329 ngx_str_t value;
1329 ngx_str_t value, *prefix;
13301330
13311331 code = (ngx_http_script_full_name_code_t *) e->ip;
13321332
13331333 value.data = e->buf.data;
13341334 value.len = e->pos - e->buf.data;
13351335
1336 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->conf_prefix)
1337 != NGX_OK)
1338 {
1336 prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
1337 (ngx_str_t *) &ngx_cycle->prefix;
1338
1339 if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
13391340 e->ip = ngx_http_script_exit;
13401341 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
13411342 return;
13921393
13931394 e->sp--;
13941395
1395 if (e->sp->len && (e->sp->len !=1 || e->sp->data[0] != '0')) {
1396 if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
13961397 if (code->loc_conf) {
13971398 e->request->loc_conf = code->loc_conf;
13981399 ngx_http_update_location_config(e->request);
4141
4242 #define ngx_spdy_frame_parse_sid(p) \
4343 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
44 #define ngx_spdy_frame_parse_delta(p) \
45 (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff)
4446
4547
4648 #define ngx_spdy_ctl_frame_check(h) \
47 (((h) & 0xffffff00) == ngx_spdy_ctl_frame_head(0))
49 (((h) & 0xffff0000) == ngx_spdy_ctl_frame_head(0))
4850 #define ngx_spdy_data_frame_check(h) \
4951 (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31))
5052
51 #define ngx_spdy_ctl_frame_type(h) ((h) & 0x000000ff)
53 #define ngx_spdy_ctl_frame_type(h) ((h) & 0x0000ffff)
5254 #define ngx_spdy_frame_flags(p) ((p) >> 24)
5355 #define ngx_spdy_frame_length(p) ((p) & 0x00ffffff)
56 #define ngx_spdy_frame_id(p) ((p) & 0x00ffffff)
5457
5558
5659 #define NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE 4096
6366 #define NGX_SPDY_CANCEL 5
6467 #define NGX_SPDY_INTERNAL_ERROR 6
6568 #define NGX_SPDY_FLOW_CONTROL_ERROR 7
69 #define NGX_SPDY_STREAM_IN_USE 8
70 #define NGX_SPDY_STREAM_ALREADY_CLOSED 9
71 /* deprecated 10 */
72 #define NGX_SPDY_FRAME_TOO_LARGE 11
6673
6774 #define NGX_SPDY_SETTINGS_MAX_STREAMS 4
75 #define NGX_SPDY_SETTINGS_INIT_WINDOW 7
6876
6977 #define NGX_SPDY_SETTINGS_FLAG_PERSIST 0x01
78 #define NGX_SPDY_SETTINGS_FLAG_PERSISTED 0x02
79
80 #define NGX_SPDY_MAX_WINDOW NGX_MAX_INT32_VALUE
81 #define NGX_SPDY_CONNECTION_WINDOW 65536
82 #define NGX_SPDY_INIT_STREAM_WINDOW 65536
83 #define NGX_SPDY_STREAM_WINDOW NGX_SPDY_MAX_WINDOW
7084
7185 typedef struct {
7286 ngx_uint_t hash;
8094 static void ngx_http_spdy_write_handler(ngx_event_t *wev);
8195 static void ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc);
8296
83 static u_char *ngx_http_spdy_state_detect_settings(
84 ngx_http_spdy_connection_t *sc, u_char *pos, u_char *end);
97 static u_char *ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc,
98 u_char *pos, u_char *end);
8599 static u_char *ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc,
86100 u_char *pos, u_char *end);
87101 static u_char *ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc,
92106 u_char *pos, u_char *end);
93107 static u_char *ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc,
94108 u_char *pos, u_char *end);
109 static u_char *ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc,
110 u_char *pos, u_char *end);
95111 static u_char *ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc,
112 u_char *pos, u_char *end);
113 static u_char *ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc,
96114 u_char *pos, u_char *end);
97115 static u_char *ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc,
98116 u_char *pos, u_char *end);
102120 u_char *pos, u_char *end);
103121 static u_char *ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc,
104122 u_char *pos, u_char *end);
105 static u_char *ngx_http_spdy_state_noop(ngx_http_spdy_connection_t *sc,
106 u_char *pos, u_char *end);
107123 static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc,
108124 u_char *pos, u_char *end);
109125 static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
113129 static u_char *ngx_http_spdy_state_internal_error(
114130 ngx_http_spdy_connection_t *sc);
115131
132 static ngx_int_t ngx_http_spdy_send_window_update(
133 ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ngx_uint_t delta);
116134 static ngx_int_t ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc,
117135 ngx_uint_t sid, ngx_uint_t status, ngx_uint_t priority);
118136 static ngx_int_t ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc);
137155 static ngx_int_t ngx_http_spdy_handle_request_header(ngx_http_request_t *r);
138156 static ngx_int_t ngx_http_spdy_parse_method(ngx_http_request_t *r);
139157 static ngx_int_t ngx_http_spdy_parse_scheme(ngx_http_request_t *r);
140 static ngx_int_t ngx_http_spdy_parse_url(ngx_http_request_t *r);
158 static ngx_int_t ngx_http_spdy_parse_host(ngx_http_request_t *r);
159 static ngx_int_t ngx_http_spdy_parse_path(ngx_http_request_t *r);
141160 static ngx_int_t ngx_http_spdy_parse_version(ngx_http_request_t *r);
142161
143162 static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r);
144163 static void ngx_http_spdy_run_request(ngx_http_request_t *r);
145164 static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r);
165
166 static ngx_int_t ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc,
167 ngx_http_spdy_stream_t *stream, ngx_uint_t status);
168
169 static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev);
146170
147171 static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev);
148172 static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev);
149173 static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
150174 ngx_int_t rc);
151175
176 static ngx_int_t ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc,
177 ssize_t delta);
178
152179 static void ngx_http_spdy_pool_cleanup(void *data);
153180
154181 static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size);
155182 static void ngx_http_spdy_zfree(void *opaque, void *address);
156183
157184
158 static const u_char ngx_http_spdy_dict[] =
159 "options" "get" "head" "post" "put" "delete" "trace"
160 "accept" "accept-charset" "accept-encoding" "accept-language"
161 "authorization" "expect" "from" "host"
162 "if-modified-since" "if-match" "if-none-match" "if-range"
163 "if-unmodifiedsince" "max-forwards" "proxy-authorization"
164 "range" "referer" "te" "user-agent"
165 "100" "101" "200" "201" "202" "203" "204" "205" "206"
166 "300" "301" "302" "303" "304" "305" "306" "307"
167 "400" "401" "402" "403" "404" "405" "406" "407" "408" "409" "410"
168 "411" "412" "413" "414" "415" "416" "417"
169 "500" "501" "502" "503" "504" "505"
170 "accept-ranges" "age" "etag" "location" "proxy-authenticate" "public"
171 "retry-after" "server" "vary" "warning" "www-authenticate" "allow"
172 "content-base" "content-encoding" "cache-control" "connection" "date"
173 "trailer" "transfer-encoding" "upgrade" "via" "warning"
174 "content-language" "content-length" "content-location"
175 "content-md5" "content-range" "content-type" "etag" "expires"
176 "last-modified" "set-cookie"
177 "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"
178 "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
179 "chunked" "text/html" "image/png" "image/jpg" "image/gif"
180 "application/xml" "application/xhtml" "text/plain" "public" "max-age"
181 "charset=iso-8859-1" "utf-8" "gzip" "deflate" "HTTP/1.1" "status"
182 "version" "url";
185 static const u_char ngx_http_spdy_dict[] = {
186 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, /* - - - - o p t i */
187 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, /* o n s - - - - h */
188 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, /* e a d - - - - p */
189 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, /* o s t - - - - p */
190 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, /* u t - - - - d e */
191 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, /* l e t e - - - - */
192 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, /* t r a c e - - - */
193 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, /* - a c c e p t - */
194 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */
195 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* t - c h a r s e */
196 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, /* t - - - - a c c */
197 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e p t - e n c o */
198 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, /* d i n g - - - - */
199 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, /* a c c e p t - l */
200 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, /* a n g u a g e - */
201 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */
202 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, /* t - r a n g e s */
203 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, /* - - - - a g e - */
204 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, /* - - - a l l o w */
205 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, /* - - - - a u t h */
206 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, /* o r i z a t i o */
207 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, /* n - - - - c a c */
208 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, /* h e - c o n t r */
209 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, /* o l - - - - c o */
210 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, /* n n e c t i o n */
211 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
212 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, /* e n t - b a s e */
213 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
214 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e n t - e n c o */
215 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, /* d i n g - - - - */
216 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, /* c o n t e n t - */
217 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, /* l a n g u a g e */
218 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */
219 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, /* e n t - l e n g */
220 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, /* t h - - - - c o */
221 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, /* n t e n t - l o */
222 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* c a t i o n - - */
223 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */
224 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, /* t - m d 5 - - - */
225 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, /* - c o n t e n t */
226 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, /* - r a n g e - - */
227 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */
228 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, /* t - t y p e - - */
229 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, /* - - d a t e - - */
230 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, /* - - e t a g - - */
231 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, /* - - e x p e c t */
232 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, /* - - - - e x p i */
233 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, /* r e s - - - - f */
234 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, /* r o m - - - - h */
235 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, /* o s t - - - - i */
236 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, /* f - m a t c h - */
237 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, /* - - - i f - m o */
238 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, /* d i f i e d - s */
239 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, /* i n c e - - - - */
240 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, /* i f - n o n e - */
241 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, /* m a t c h - - - */
242 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, /* - i f - r a n g */
243 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, /* e - - - - i f - */
244 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, /* u n m o d i f i */
245 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, /* e d - s i n c e */
246 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, /* - - - - l a s t */
247 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, /* - m o d i f i e */
248 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, /* d - - - - l o c */
249 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, /* a t i o n - - - */
250 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, /* - m a x - f o r */
251 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, /* w a r d s - - - */
252 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, /* - p r a g m a - */
253 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, /* - - - p r o x y */
254 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, /* - a u t h e n t */
255 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, /* i c a t e - - - */
256 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, /* - p r o x y - a */
257 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, /* u t h o r i z a */
258 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, /* t i o n - - - - */
259 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, /* r a n g e - - - */
260 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, /* - r e f e r e r */
261 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, /* - - - - r e t r */
262 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, /* y - a f t e r - */
263 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, /* - - - s e r v e */
264 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, /* r - - - - t e - */
265 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, /* - - - t r a i l */
266 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, /* e r - - - - t r */
267 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, /* a n s f e r - e */
268 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, /* n c o d i n g - */
269 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, /* - - - u p g r a */
270 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, /* d e - - - - u s */
271 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, /* e r - a g e n t */
272 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, /* - - - - v a r y */
273 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, /* - - - - v i a - */
274 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, /* - - - w a r n i */
275 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, /* n g - - - - w w */
276 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, /* w - a u t h e n */
277 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, /* t i c a t e - - */
278 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, /* - - m e t h o d */
279 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, /* - - - - g e t - */
280 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, /* - - - s t a t u */
281 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, /* s - - - - 2 0 0 */
282 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, /* - O K - - - - v */
283 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* e r s i o n - - */
284 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, /* - - H T T P - 1 */
285 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, /* - 1 - - - - u r */
286 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, /* l - - - - p u b */
287 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, /* l i c - - - - s */
288 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, /* e t - c o o k i */
289 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, /* e - - - - k e e */
290 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, /* p - a l i v e - */
291 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, /* - - - o r i g i */
292 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, /* n 1 0 0 1 0 1 2 */
293 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, /* 0 1 2 0 2 2 0 5 */
294 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, /* 2 0 6 3 0 0 3 0 */
295 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, /* 2 3 0 3 3 0 4 3 */
296 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, /* 0 5 3 0 6 3 0 7 */
297 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, /* 4 0 2 4 0 5 4 0 */
298 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, /* 6 4 0 7 4 0 8 4 */
299 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, /* 0 9 4 1 0 4 1 1 */
300 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, /* 4 1 2 4 1 3 4 1 */
301 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, /* 4 4 1 5 4 1 6 4 */
302 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, /* 1 7 5 0 2 5 0 4 */
303 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, /* 5 0 5 2 0 3 - N */
304 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, /* o n - A u t h o */
305 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, /* r i t a t i v e */
306 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, /* - I n f o r m a */
307 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, /* t i o n 2 0 4 - */
308 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, /* N o - C o n t e */
309 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, /* n t 3 0 1 - M o */
310 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, /* v e d - P e r m */
311 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, /* a n e n t l y 4 */
312 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, /* 0 0 - B a d - R */
313 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, /* e q u e s t 4 0 */
314 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, /* 1 - U n a u t h */
315 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, /* o r i z e d 4 0 */
316 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, /* 3 - F o r b i d */
317 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, /* d e n 4 0 4 - N */
318 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, /* o t - F o u n d */
319 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, /* 5 0 0 - I n t e */
320 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, /* r n a l - S e r */
321 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, /* v e r - E r r o */
322 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, /* r 5 0 1 - N o t */
323 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, /* - I m p l e m e */
324 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, /* n t e d 5 0 3 - */
325 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, /* S e r v i c e - */
326 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, /* U n a v a i l a */
327 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, /* b l e J a n - F */
328 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, /* e b - M a r - A */
329 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, /* p r - M a y - J */
330 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, /* u n - J u l - A */
331 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, /* u g - S e p t - */
332 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, /* O c t - N o v - */
333 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, /* D e c - 0 0 - 0 */
334 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, /* 0 - 0 0 - M o n */
335 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, /* - - T u e - - W */
336 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, /* e d - - T h u - */
337 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, /* - F r i - - S a */
338 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, /* t - - S u n - - */
339 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, /* G M T c h u n k */
340 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, /* e d - t e x t - */
341 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, /* h t m l - i m a */
342 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, /* g e - p n g - i */
343 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, /* m a g e - j p g */
344 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, /* - i m a g e - g */
345 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* i f - a p p l i */
346 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */
347 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* m l - a p p l i */
348 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */
349 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, /* h t m l - x m l */
350 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, /* - t e x t - p l */
351 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, /* a i n - t e x t */
352 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, /* - j a v a s c r */
353 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, /* i p t - p u b l */
354 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, /* i c p r i v a t */
355 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, /* e m a x - a g e */
356 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, /* - g z i p - d e */
357 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, /* f l a t e - s d */
358 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* c h c h a r s e */
359 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, /* t - u t f - 8 c */
360 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, /* h a r s e t - i */
361 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, /* s o - 8 8 5 9 - */
362 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, /* 1 - u t f - - - */
363 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e /* - e n q - 0 - */
364 };
183365
184366
185367 static ngx_http_spdy_request_header_t ngx_http_spdy_request_headers[] = {
186368 { 0, 6, "method", ngx_http_spdy_parse_method },
187369 { 0, 6, "scheme", ngx_http_spdy_parse_scheme },
188 { 0, 3, "url", ngx_http_spdy_parse_url },
370 { 0, 4, "host", ngx_http_spdy_parse_host },
371 { 0, 4, "path", ngx_http_spdy_parse_path },
189372 { 0, 7, "version", ngx_http_spdy_parse_version },
190373 };
191374
232415 sc->connection = c;
233416 sc->http_connection = hc;
234417
235 sc->handler = ngx_http_spdy_state_detect_settings;
418 sc->send_window = NGX_SPDY_CONNECTION_WINDOW;
419 sc->recv_window = NGX_SPDY_CONNECTION_WINDOW;
420
421 sc->init_window = NGX_SPDY_INIT_STREAM_WINDOW;
422
423 sc->handler = ngx_http_spdy_state_head;
424
425 if (hc->proxy_protocol) {
426 c->log->action = "reading PROXY protocol";
427 sc->handler = ngx_http_spdy_proxy_protocol;
428 }
236429
237430 sc->zstream_in.zalloc = ngx_http_spdy_zalloc;
238431 sc->zstream_in.zfree = ngx_http_spdy_zfree;
294487 return;
295488 }
296489
490 if (ngx_http_spdy_send_settings(sc) == NGX_ERROR) {
491 ngx_http_close_connection(c);
492 return;
493 }
494
495 if (ngx_http_spdy_send_window_update(sc, 0, NGX_SPDY_MAX_WINDOW
496 - sc->recv_window)
497 == NGX_ERROR)
498 {
499 ngx_http_close_connection(c);
500 return;
501 }
502
503 sc->recv_window = NGX_SPDY_MAX_WINDOW;
504
505 ngx_queue_init(&sc->waiting);
506 ngx_queue_init(&sc->posted);
507
297508 c->data = sc;
298509
299510 rev->handler = ngx_http_spdy_read_handler;
343554 break;
344555 }
345556
346 if (n == 0 && (sc->waiting || sc->processing)) {
557 if (n == 0 && (sc->incomplete || sc->processing)) {
347558 ngx_log_error(NGX_LOG_INFO, c->log, 0,
348559 "client closed prematurely connection");
349560 }
357568 end += n;
358569
359570 sc->buffer_used = 0;
360 sc->waiting = 0;
571 sc->incomplete = 0;
361572
362573 do {
363574 p = sc->handler(sc, p, end);
375586 return;
376587 }
377588
589 if (sc->last_out && ngx_http_spdy_send_output_queue(sc) == NGX_ERROR) {
590 ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST);
591 return;
592 }
593
378594 sc->blocked = 0;
379595
380596 if (sc->processing) {
392608 ngx_http_spdy_write_handler(ngx_event_t *wev)
393609 {
394610 ngx_int_t rc;
611 ngx_queue_t *q;
395612 ngx_connection_t *c;
396 ngx_http_spdy_stream_t *stream, *s, *sn;
613 ngx_http_spdy_stream_t *stream;
397614 ngx_http_spdy_connection_t *sc;
398615
399616 c = wev->data;
408625
409626 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy write handler");
410627
411 sc->blocked = 2;
628 sc->blocked = 1;
412629
413630 rc = ngx_http_spdy_send_output_queue(sc);
414631
417634 return;
418635 }
419636
420 stream = NULL;
421
422 for (s = sc->last_stream; s; s = sn) {
423 sn = s->next;
424 s->next = stream;
425 stream = s;
426 }
427
428 sc->last_stream = NULL;
429
430 sc->blocked = 1;
431
432 for ( /* void */ ; stream; stream = sn) {
433 sn = stream->next;
637 while (!ngx_queue_empty(&sc->posted)) {
638 q = ngx_queue_head(&sc->posted);
639
640 ngx_queue_remove(q);
641
642 stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
643
434644 stream->handled = 0;
435645
436646 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
483693 out = frame;
484694
485695 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
486 "spdy frame out: %p sid:%ui prio:%ui bl:%ui size:%uz",
696 "spdy frame out: %p sid:%ui prio:%ui bl:%d len:%uz",
487697 out, out->stream ? out->stream->id : 0, out->priority,
488 out->blocked, out->size);
698 out->blocked, out->length);
489699 }
490700
491701 cl = c->send_chain(c, cl, 0);
516726 }
517727 }
518728
519 for ( /* void */ ; out; out = out->next) {
729 for ( /* void */ ; out; out = fn) {
730 fn = out->next;
731
520732 if (out->handler(sc, out) != NGX_OK) {
521733 out->blocked = 1;
522734 out->priority = NGX_SPDY_HIGHEST_PRIORITY;
524736 }
525737
526738 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0,
527 "spdy frame sent: %p sid:%ui bl:%ui size:%uz",
739 "spdy frame sent: %p sid:%ui bl:%d len:%uz",
528740 out, out->stream ? out->stream->id : 0,
529 out->blocked, out->size);
741 out->blocked, out->length);
530742 }
531743
532744 frame = NULL;
566778
567779 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
568780 ngx_http_spdy_module);
569 if (sc->waiting) {
781 if (sc->incomplete) {
570782 ngx_add_timer(c->read, sscf->recv_timeout);
571783 return;
572784 }
604816
605817
606818 static u_char *
607 ngx_http_spdy_state_detect_settings(ngx_http_spdy_connection_t *sc,
608 u_char *pos, u_char *end)
609 {
610 if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) {
611 return ngx_http_spdy_state_save(sc, pos, end,
612 ngx_http_spdy_state_detect_settings);
613 }
614
615 /*
616 * Since this is the first frame in a buffer,
617 * then it is properly aligned
618 */
619
620 if (*(uint32_t *) pos == htonl(ngx_spdy_ctl_frame_head(NGX_SPDY_SETTINGS)))
621 {
622 sc->length = ngx_spdy_frame_length(htonl(((uint32_t *) pos)[1]));
623
624 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
625 "spdy SETTINGS frame received, size: %uz", sc->length);
626
627 pos += NGX_SPDY_FRAME_HEADER_SIZE;
628
629 return ngx_http_spdy_state_settings(sc, pos, end);
630 }
631
632 ngx_http_spdy_send_settings(sc);
633
634 return ngx_http_spdy_state_head(sc, pos, end);
819 ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos,
820 u_char *end)
821 {
822 pos = ngx_proxy_protocol_parse(sc->connection, pos, end);
823
824 if (pos == NULL) {
825 return ngx_http_spdy_state_protocol_error(sc);
826 }
827
828 sc->connection->log->action = "processing SPDY";
829
830 return ngx_http_spdy_state_complete(sc, pos, end);
635831 }
636832
637833
639835 ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos,
640836 u_char *end)
641837 {
642 uint32_t head, flen;
838 uint32_t head, flen;
839 ngx_uint_t type;
643840
644841 if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) {
645842 return ngx_http_spdy_state_save(sc, pos, end,
658855 pos += sizeof(uint32_t);
659856
660857 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
661 "spdy process frame head:%08Xd f:%ui l:%ui",
858 "spdy process frame head:%08XD f:%Xd l:%uz",
662859 head, sc->flags, sc->length);
663860
664861 if (ngx_spdy_ctl_frame_check(head)) {
665 switch (ngx_spdy_ctl_frame_type(head)) {
862 type = ngx_spdy_ctl_frame_type(head);
863
864 switch (type) {
666865
667866 case NGX_SPDY_SYN_STREAM:
668867 return ngx_http_spdy_state_syn_stream(sc, pos, end);
674873 return ngx_http_spdy_state_rst_stream(sc, pos, end);
675874
676875 case NGX_SPDY_SETTINGS:
677 return ngx_http_spdy_state_skip(sc, pos, end);
678
679 case NGX_SPDY_NOOP:
680 return ngx_http_spdy_state_noop(sc, pos, end);
876 return ngx_http_spdy_state_settings(sc, pos, end);
681877
682878 case NGX_SPDY_PING:
683879 return ngx_http_spdy_state_ping(sc, pos, end);
688884 case NGX_SPDY_HEADERS:
689885 return ngx_http_spdy_state_protocol_error(sc);
690886
691 default: /* TODO logging */
887 case NGX_SPDY_WINDOW_UPDATE:
888 return ngx_http_spdy_state_window_update(sc, pos, end);
889
890 default:
891 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
892 "spdy control frame with unknown type %ui", type);
692893 return ngx_http_spdy_state_skip(sc, pos, end);
693894 }
694895 }
728929 sc->length -= NGX_SPDY_SYN_STREAM_SIZE;
729930
730931 sid = ngx_spdy_frame_parse_sid(pos);
731 prio = pos[8] >> 6;
932 prio = pos[8] >> 5;
732933
733934 pos += NGX_SPDY_SYN_STREAM_SIZE;
734935
741942 if (sc->processing >= sscf->concurrent_streams) {
742943
743944 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
744 "spdy concurrent streams excessed %ui", sc->processing);
945 "spdy concurrent streams exceeded %ui", sc->processing);
745946
746947 if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_REFUSED_STREAM,
747948 prio)
8081009 sc->zstream_in.next_in = pos;
8091010 sc->zstream_in.avail_in = size;
8101011 sc->zstream_in.next_out = buf->last;
1012
1013 /* one byte is reserved for null-termination of the last header value */
8111014 sc->zstream_in.avail_out = buf->end - buf->last - 1;
8121015
8131016 z = inflate(&sc->zstream_in, Z_NO_FLUSH);
8501053 if (r->headers_in.headers.part.elts == NULL) {
8511054
8521055 if (buf->last - buf->pos < NGX_SPDY_NV_NUM_SIZE) {
1056
1057 if (complete) {
1058 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1059 "client sent SYN_STREAM frame "
1060 "with invalid HEADERS block");
1061 ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_BAD_REQUEST);
1062 return ngx_http_spdy_state_protocol_error(sc);
1063 }
1064
8531065 return ngx_http_spdy_state_save(sc, pos, end,
8541066 ngx_http_spdy_state_headers);
8551067 }
8561068
857 sc->headers = ngx_spdy_frame_parse_uint16(buf->pos);
1069 sc->entries = ngx_spdy_frame_parse_uint32(buf->pos);
8581070
8591071 buf->pos += NGX_SPDY_NV_NUM_SIZE;
8601072
8611073 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
862 "spdy headers count: %ui", sc->headers);
863
864 if (ngx_list_init(&r->headers_in.headers, r->pool, sc->headers + 3,
1074 "spdy HEADERS block consists of %ui entries",
1075 sc->entries);
1076
1077 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
8651078 sizeof(ngx_table_elt_t))
8661079 != NGX_OK)
8671080 {
8801093 }
8811094 }
8821095
883 while (sc->headers) {
1096 while (sc->entries) {
8841097
8851098 rc = ngx_http_spdy_parse_header(r);
8861099
8871100 switch (rc) {
8881101
8891102 case NGX_DONE:
890 sc->headers--;
1103 sc->entries--;
8911104
8921105 case NGX_OK:
8931106 break;
9111124 return ngx_http_spdy_state_headers_error(sc, pos, end);
9121125 }
9131126
1127 /* null-terminate the last processed header name or value */
1128 *buf->pos = '\0';
1129
9141130 buf = r->header_in;
9151131
9161132 sc->zstream_in.next_out = buf->last;
1133
1134 /* one byte is reserved for null-termination */
9171135 sc->zstream_in.avail_out = buf->end - buf->last - 1;
9181136
9191137 z = inflate(&sc->zstream_in, Z_NO_FLUSH);
9821200 }
9831201 }
9841202
985 if (buf->pos != buf->last) {
986 /* TODO: improve error message */
987 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
988 "end %ui %p %p", complete, buf->pos, buf->last);
1203 if (buf->pos != buf->last || sc->zstream_in.avail_in) {
1204 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1205 "client sent SYN_STREAM frame "
1206 "with invalid HEADERS block");
9891207 ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_BAD_REQUEST);
9901208 return ngx_http_spdy_state_protocol_error(sc);
9911209 }
9941212 return ngx_http_spdy_state_save(sc, pos, end,
9951213 ngx_http_spdy_state_headers);
9961214 }
1215
1216 /* null-terminate the last header value */
1217 *buf->pos = '\0';
9971218
9981219 ngx_http_spdy_run_request(r);
9991220
10631284
10641285
10651286 static u_char *
1287 ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, u_char *pos,
1288 u_char *end)
1289 {
1290 size_t delta;
1291 ngx_uint_t sid;
1292 ngx_event_t *wev;
1293 ngx_queue_t *q;
1294 ngx_http_spdy_stream_t *stream;
1295
1296 if (end - pos < NGX_SPDY_WINDOW_UPDATE_SIZE) {
1297 return ngx_http_spdy_state_save(sc, pos, end,
1298 ngx_http_spdy_state_window_update);
1299 }
1300
1301 if (sc->length != NGX_SPDY_WINDOW_UPDATE_SIZE) {
1302 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1303 "client sent WINDOW_UPDATE frame "
1304 "with incorrect length %uz", sc->length);
1305
1306 return ngx_http_spdy_state_protocol_error(sc);
1307 }
1308
1309 sid = ngx_spdy_frame_parse_sid(pos);
1310
1311 pos += NGX_SPDY_SID_SIZE;
1312
1313 delta = ngx_spdy_frame_parse_delta(pos);
1314
1315 pos += NGX_SPDY_DELTA_SIZE;
1316
1317 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1318 "spdy WINDOW_UPDATE sid:%ui delta:%ui", sid, delta);
1319
1320 if (sid) {
1321 stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1322
1323 if (stream == NULL) {
1324 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1325 "client sent WINDOW_UPDATE frame "
1326 "for unknown stream %ui", sid);
1327
1328 if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_INVALID_STREAM,
1329 NGX_SPDY_LOWEST_PRIORITY)
1330 == NGX_ERROR)
1331 {
1332 return ngx_http_spdy_state_internal_error(sc);
1333 }
1334
1335 return ngx_http_spdy_state_complete(sc, pos, end);
1336 }
1337
1338 if (stream->send_window > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) {
1339
1340 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1341 "client violated flow control for stream %ui: "
1342 "received WINDOW_UPDATE frame with delta %uz "
1343 "that is not allowed for window %z",
1344 sid, delta, stream->send_window);
1345
1346 if (ngx_http_spdy_terminate_stream(sc, stream,
1347 NGX_SPDY_FLOW_CONTROL_ERROR)
1348 == NGX_ERROR)
1349 {
1350 return ngx_http_spdy_state_internal_error(sc);
1351 }
1352
1353 return ngx_http_spdy_state_complete(sc, pos, end);
1354 }
1355
1356 stream->send_window += delta;
1357
1358 if (stream->exhausted) {
1359 stream->exhausted = 0;
1360
1361 wev = stream->request->connection->write;
1362
1363 if (!wev->timer_set) {
1364 wev->delayed = 0;
1365 wev->handler(wev);
1366 }
1367 }
1368
1369 } else {
1370 sc->send_window += delta;
1371
1372 if (sc->send_window > NGX_SPDY_MAX_WINDOW) {
1373 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1374 "client violated connection flow control: "
1375 "received WINDOW_UPDATE frame with delta %uz "
1376 "that is not allowed for window %uz",
1377 delta, sc->send_window);
1378
1379 return ngx_http_spdy_state_protocol_error(sc);
1380 }
1381
1382 while (!ngx_queue_empty(&sc->waiting)) {
1383 q = ngx_queue_head(&sc->waiting);
1384
1385 ngx_queue_remove(q);
1386
1387 stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
1388
1389 stream->handled = 0;
1390
1391 wev = stream->request->connection->write;
1392
1393 if (!wev->timer_set) {
1394 wev->delayed = 0;
1395 wev->handler(wev);
1396
1397 if (sc->send_window == 0) {
1398 break;
1399 }
1400 }
1401 }
1402 }
1403
1404 return ngx_http_spdy_state_complete(sc, pos, end);
1405 }
1406
1407
1408 static u_char *
10661409 ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos,
1410 u_char *end)
1411 {
1412 ngx_http_spdy_stream_t *stream;
1413
1414 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1415 "spdy DATA frame");
1416
1417 if (sc->length > sc->recv_window) {
1418 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1419 "client violated connection flow control: length of "
1420 "received DATA frame %uz, while available window %uz",
1421 sc->length, sc->recv_window);
1422
1423 return ngx_http_spdy_state_protocol_error(sc);
1424 }
1425
1426 sc->recv_window -= sc->length;
1427
1428 if (sc->recv_window < NGX_SPDY_MAX_WINDOW / 4) {
1429
1430 if (ngx_http_spdy_send_window_update(sc, 0,
1431 NGX_SPDY_MAX_WINDOW
1432 - sc->recv_window)
1433 == NGX_ERROR)
1434 {
1435 return ngx_http_spdy_state_internal_error(sc);
1436 }
1437
1438 sc->recv_window = NGX_SPDY_MAX_WINDOW;
1439 }
1440
1441 stream = sc->stream;
1442
1443 if (stream == NULL) {
1444 return ngx_http_spdy_state_skip(sc, pos, end);
1445 }
1446
1447 if (sc->length > stream->recv_window) {
1448 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1449 "client violated flow control for stream %ui: length of "
1450 "received DATA frame %uz, while available window %uz",
1451 stream->id, sc->length, stream->recv_window);
1452
1453 if (ngx_http_spdy_terminate_stream(sc, stream,
1454 NGX_SPDY_FLOW_CONTROL_ERROR)
1455 == NGX_ERROR)
1456 {
1457 return ngx_http_spdy_state_internal_error(sc);
1458 }
1459
1460 return ngx_http_spdy_state_skip(sc, pos, end);
1461 }
1462
1463 stream->recv_window -= sc->length;
1464
1465 if (stream->recv_window < NGX_SPDY_STREAM_WINDOW / 4) {
1466
1467 if (ngx_http_spdy_send_window_update(sc, stream->id,
1468 NGX_SPDY_STREAM_WINDOW
1469 - stream->recv_window)
1470 == NGX_ERROR)
1471 {
1472 return ngx_http_spdy_state_internal_error(sc);
1473 }
1474
1475 stream->recv_window = NGX_SPDY_STREAM_WINDOW;
1476 }
1477
1478 if (stream->in_closed) {
1479 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1480 "client sent DATA frame for half closed stream %ui",
1481 stream->id);
1482
1483 if (ngx_http_spdy_terminate_stream(sc, stream,
1484 NGX_SPDY_STREAM_ALREADY_CLOSED)
1485 == NGX_ERROR)
1486 {
1487 return ngx_http_spdy_state_internal_error(sc);
1488 }
1489
1490 return ngx_http_spdy_state_skip(sc, pos, end);
1491 }
1492
1493 return ngx_http_spdy_state_read_data(sc, pos, end);
1494 }
1495
1496
1497 static u_char *
1498 ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, u_char *pos,
10671499 u_char *end)
10681500 {
10691501 size_t size;
10701502 ssize_t n;
10711503 ngx_buf_t *buf;
10721504 ngx_int_t rc;
1073 ngx_uint_t complete;
10741505 ngx_temp_file_t *tf;
10751506 ngx_http_request_t *r;
10761507 ngx_http_spdy_stream_t *stream;
10791510
10801511 stream = sc->stream;
10811512
1082 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1083 "spdy DATA frame");
1084
10851513 if (stream == NULL) {
10861514 return ngx_http_spdy_state_skip(sc, pos, end);
10871515 }
10881516
1089 if (stream->in_closed) {
1090 /* TODO log */
1091 return ngx_http_spdy_state_protocol_error(sc);
1092 }
1093
10941517 if (stream->skip_data) {
10951518
10961519 if (sc->flags & NGX_SPDY_FLAG_FIN) {
11031526
11041527 size = end - pos;
11051528
1106 if (size >= sc->length) {
1529 if (size > sc->length) {
11071530 size = sc->length;
1108 complete = 1;
1109
1110 } else {
1111 sc->length -= size;
1112 complete = 0;
11131531 }
11141532
11151533 r = stream->request;
11511569 }
11521570 }
11531571
1572 sc->length -= size;
1573
11541574 if (tf) {
11551575 buf->start = pos;
11561576 buf->pos = pos;
11791599 r->request_length += size;
11801600 }
11811601
1182 if (!complete) {
1602 if (sc->length) {
11831603 return ngx_http_spdy_state_save(sc, pos, end,
1184 ngx_http_spdy_state_data);
1604 ngx_http_spdy_state_read_data);
11851605 }
11861606
11871607 if (sc->flags & NGX_SPDY_FLAG_FIN) {
11881608
11891609 stream->in_closed = 1;
1610
1611 if (r->headers_in.content_length_n < 0) {
1612 r->headers_in.content_length_n = rb->rest;
1613
1614 } else if (r->headers_in.content_length_n != rb->rest) {
1615 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1616 "client prematurely closed stream: "
1617 "%O of %O bytes of request body received",
1618 rb->rest, r->headers_in.content_length_n);
1619
1620 stream->skip_data = NGX_SPDY_DATA_ERROR;
1621 goto error;
1622 }
11901623
11911624 if (tf) {
11921625 ngx_memzero(buf, sizeof(ngx_buf_t));
11981631 rb->buf = NULL;
11991632 }
12001633
1201 if (r->headers_in.content_length_n < 0) {
1202 r->headers_in.content_length_n = rb->rest;
1203 }
1204
12051634 if (rb->post_handler) {
1635 r->read_event_handler = ngx_http_block_reading;
12061636 rb->post_handler(r);
12071637 }
12081638 }
12361666 ngx_uint_t sid, status;
12371667 ngx_event_t *ev;
12381668 ngx_connection_t *fc;
1239 ngx_http_request_t *r;
12401669 ngx_http_spdy_stream_t *stream;
12411670
12421671 if (end - pos < NGX_SPDY_RST_STREAM_SIZE) {
12451674 }
12461675
12471676 if (sc->length != NGX_SPDY_RST_STREAM_SIZE) {
1248 /* TODO logging */
1677 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1678 "client sent RST_STREAM frame with incorrect length %uz",
1679 sc->length);
1680
12491681 return ngx_http_spdy_state_protocol_error(sc);
12501682 }
12511683
12601692 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
12611693 "spdy RST_STREAM sid:%ui st:%ui", sid, status);
12621694
1695 stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1696 if (stream == NULL) {
1697 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1698 "unknown stream, probably it has been closed already");
1699 return ngx_http_spdy_state_complete(sc, pos, end);
1700 }
1701
1702 stream->in_closed = 1;
1703 stream->out_closed = 1;
1704
1705 fc = stream->request->connection;
1706 fc->error = 1;
12631707
12641708 switch (status) {
12651709
1266 case NGX_SPDY_PROTOCOL_ERROR:
1267 /* TODO logging */
1268 return ngx_http_spdy_state_protocol_error(sc);
1269
1270 case NGX_SPDY_INVALID_STREAM:
1271 /* TODO */
1710 case NGX_SPDY_CANCEL:
1711 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1712 "client canceled stream %ui", sid);
12721713 break;
12731714
1274 case NGX_SPDY_REFUSED_STREAM:
1275 /* TODO */
1715 case NGX_SPDY_INTERNAL_ERROR:
1716 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1717 "client terminated stream %ui because of internal error",
1718 sid);
12761719 break;
12771720
1278 case NGX_SPDY_UNSUPPORTED_VERSION:
1279 /* TODO logging */
1280 return ngx_http_spdy_state_protocol_error(sc);
1281
1282 case NGX_SPDY_CANCEL:
1283 case NGX_SPDY_INTERNAL_ERROR:
1284 stream = ngx_http_spdy_get_stream_by_id(sc, sid);
1285 if (stream == NULL) {
1286 /* TODO false cancel */
1287 break;
1288 }
1289
1290 stream->in_closed = 1;
1291 stream->out_closed = 1;
1292
1293 r = stream->request;
1294
1295 fc = r->connection;
1296 fc->error = 1;
1297
1298 ev = fc->read;
1299 ev->handler(ev);
1300
1721 default:
1722 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
1723 "client terminated stream %ui with status %ui",
1724 sid, status);
13011725 break;
1302
1303 case NGX_SPDY_FLOW_CONTROL_ERROR:
1304 /* TODO logging */
1305 return ngx_http_spdy_state_protocol_error(sc);
1306
1307 default:
1308 /* TODO */
1309 return ngx_http_spdy_state_protocol_error(sc);
1310 }
1726 }
1727
1728 ev = fc->read;
1729 ev->handler(ev);
13111730
13121731 return ngx_http_spdy_state_complete(sc, pos, end);
13131732 }
13811800 ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, u_char *pos,
13821801 u_char *end)
13831802 {
1384 ngx_uint_t v;
1385 ngx_http_spdy_srv_conf_t *sscf;
1386
1387 if (sc->headers == 0) {
1803 ngx_uint_t fid, val;
1804
1805 if (sc->entries == 0) {
13881806
13891807 if (end - pos < NGX_SPDY_SETTINGS_NUM_SIZE) {
13901808 return ngx_http_spdy_state_save(sc, pos, end,
13911809 ngx_http_spdy_state_settings);
13921810 }
13931811
1394 sc->headers = ngx_spdy_frame_parse_uint32(pos);
1812 sc->entries = ngx_spdy_frame_parse_uint32(pos);
13951813
13961814 pos += NGX_SPDY_SETTINGS_NUM_SIZE;
13971815 sc->length -= NGX_SPDY_SETTINGS_NUM_SIZE;
13981816
1399 if (sc->length < sc->headers * NGX_SPDY_SETTINGS_PAIR_SIZE) {
1817 if (sc->length < sc->entries * NGX_SPDY_SETTINGS_PAIR_SIZE) {
14001818 /* TODO logging */
14011819 return ngx_http_spdy_state_protocol_error(sc);
14021820 }
14031821
14041822 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
14051823 "spdy SETTINGS frame consists of %ui entries",
1406 sc->headers);
1407 }
1408
1409 while (sc->headers) {
1824 sc->entries);
1825 }
1826
1827 while (sc->entries) {
14101828 if (end - pos < NGX_SPDY_SETTINGS_PAIR_SIZE) {
14111829 return ngx_http_spdy_state_save(sc, pos, end,
14121830 ngx_http_spdy_state_settings);
14131831 }
14141832
1415 sc->headers--;
1416
1417 if (pos[0] != NGX_SPDY_SETTINGS_MAX_STREAMS) {
1418 pos += NGX_SPDY_SETTINGS_PAIR_SIZE;
1419 sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE;
1833 sc->entries--;
1834 sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE;
1835
1836 fid = ngx_spdy_frame_parse_uint32(pos);
1837
1838 pos += NGX_SPDY_SETTINGS_FID_SIZE;
1839
1840 val = ngx_spdy_frame_parse_uint32(pos);
1841
1842 pos += NGX_SPDY_SETTINGS_VAL_SIZE;
1843
1844 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1845 "spdy SETTINGS entry fl:%ui id:%ui val:%ui",
1846 ngx_spdy_frame_flags(fid), ngx_spdy_frame_id(fid), val);
1847
1848 if (ngx_spdy_frame_flags(fid) == NGX_SPDY_SETTINGS_FLAG_PERSISTED) {
14201849 continue;
14211850 }
14221851
1423 v = ngx_spdy_frame_parse_uint32(pos + NGX_SPDY_SETTINGS_IDF_SIZE);
1424
1425 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
1426 ngx_http_spdy_module);
1427
1428 if (v != sscf->concurrent_streams) {
1429 ngx_http_spdy_send_settings(sc);
1430 }
1431
1432 return ngx_http_spdy_state_skip(sc, pos, end);
1433 }
1434
1435 ngx_http_spdy_send_settings(sc);
1436
1437 return ngx_http_spdy_state_complete(sc, pos, end);
1438 }
1439
1440
1441 static u_char *
1442 ngx_http_spdy_state_noop(ngx_http_spdy_connection_t *sc, u_char *pos,
1443 u_char *end)
1444 {
1445 if (sc->length) {
1446 /* TODO logging */
1447 return ngx_http_spdy_state_protocol_error(sc);
1852 switch (ngx_spdy_frame_id(fid)) {
1853
1854 case NGX_SPDY_SETTINGS_INIT_WINDOW:
1855
1856 if (val > NGX_SPDY_MAX_WINDOW) {
1857 ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0,
1858 "client sent SETTINGS frame with "
1859 "incorrect INIT_WINDOW value: %ui", val);
1860
1861 return ngx_http_spdy_state_protocol_error(sc);
1862 }
1863
1864 if (ngx_http_spdy_adjust_windows(sc, val - sc->init_window)
1865 != NGX_OK)
1866 {
1867 return ngx_http_spdy_state_internal_error(sc);
1868 }
1869
1870 sc->init_window = val;
1871
1872 continue;
1873 }
14481874 }
14491875
14501876 return ngx_http_spdy_state_complete(sc, pos, end);
14641890 ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc,
14651891 u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler)
14661892 {
1467 #if 1
1468 if (end - pos > NGX_SPDY_STATE_BUFFER_SIZE) {
1893 size_t size;
1894
1895 size = end - pos;
1896
1897 if (size > NGX_SPDY_STATE_BUFFER_SIZE) {
14691898 ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
14701899 "spdy state buffer overflow: "
1471 "%i bytes required", end - pos);
1900 "%uz bytes required", size);
14721901 return ngx_http_spdy_state_internal_error(sc);
14731902 }
1474 #endif
14751903
14761904 ngx_memcpy(sc->buffer, pos, NGX_SPDY_STATE_BUFFER_SIZE);
14771905
1478 sc->buffer_used = end - pos;
1906 sc->buffer_used = size;
14791907 sc->handler = handler;
1480 sc->waiting = 1;
1908 sc->incomplete = 1;
14811909
14821910 return end;
14831911 }
15041932 /* TODO */
15051933 ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR);
15061934 return NULL;
1935 }
1936
1937
1938 static ngx_int_t
1939 ngx_http_spdy_send_window_update(ngx_http_spdy_connection_t *sc, ngx_uint_t sid,
1940 ngx_uint_t delta)
1941 {
1942 u_char *p;
1943 ngx_buf_t *buf;
1944 ngx_http_spdy_out_frame_t *frame;
1945
1946 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
1947 "spdy write WINDOW_UPDATE sid:%ui delta:%ui", sid, delta);
1948
1949 frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_WINDOW_UPDATE_SIZE,
1950 NGX_SPDY_HIGHEST_PRIORITY);
1951 if (frame == NULL) {
1952 return NGX_ERROR;
1953 }
1954
1955 buf = frame->first->buf;
1956
1957 p = buf->pos;
1958
1959 p = ngx_spdy_frame_write_head(p, NGX_SPDY_WINDOW_UPDATE);
1960 p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_WINDOW_UPDATE_SIZE);
1961
1962 p = ngx_spdy_frame_write_sid(p, sid);
1963 p = ngx_spdy_frame_aligned_write_uint32(p, delta);
1964
1965 buf->last = p;
1966
1967 ngx_http_spdy_queue_frame(sc, frame);
1968
1969 return NGX_OK;
15071970 }
15081971
15091972
15862049 {
15872050 u_char *p;
15882051 ngx_buf_t *buf;
1589 ngx_pool_t *pool;
15902052 ngx_chain_t *cl;
15912053 ngx_http_spdy_srv_conf_t *sscf;
15922054 ngx_http_spdy_out_frame_t *frame;
15942056 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
15952057 "spdy create SETTINGS frame");
15962058
1597 pool = sc->connection->pool;
1598
1599 frame = ngx_palloc(pool, sizeof(ngx_http_spdy_out_frame_t));
2059 frame = ngx_palloc(sc->pool, sizeof(ngx_http_spdy_out_frame_t));
16002060 if (frame == NULL) {
16012061 return NGX_ERROR;
16022062 }
16032063
1604 cl = ngx_alloc_chain_link(pool);
2064 cl = ngx_alloc_chain_link(sc->pool);
16052065 if (cl == NULL) {
16062066 return NGX_ERROR;
16072067 }
16082068
1609 buf = ngx_create_temp_buf(pool, NGX_SPDY_FRAME_HEADER_SIZE
1610 + NGX_SPDY_SETTINGS_NUM_SIZE
1611 + NGX_SPDY_SETTINGS_PAIR_SIZE);
2069 buf = ngx_create_temp_buf(sc->pool, NGX_SPDY_FRAME_HEADER_SIZE
2070 + NGX_SPDY_SETTINGS_NUM_SIZE
2071 + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE);
16122072 if (buf == NULL) {
16132073 return NGX_ERROR;
16142074 }
16212081 frame->first = cl;
16222082 frame->last = cl;
16232083 frame->handler = ngx_http_spdy_settings_frame_handler;
2084 frame->stream = NULL;
16242085 #if (NGX_DEBUG)
1625 frame->stream = NULL;
1626 frame->size = NGX_SPDY_FRAME_HEADER_SIZE
1627 + NGX_SPDY_SETTINGS_NUM_SIZE
1628 + NGX_SPDY_SETTINGS_PAIR_SIZE;
2086 frame->length = NGX_SPDY_SETTINGS_NUM_SIZE
2087 + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE;
16292088 #endif
16302089 frame->priority = NGX_SPDY_HIGHEST_PRIORITY;
16312090 frame->blocked = 0;
16342093
16352094 p = ngx_spdy_frame_write_head(p, NGX_SPDY_SETTINGS);
16362095 p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_CLEAR_SETTINGS,
1637 NGX_SPDY_SETTINGS_NUM_SIZE
1638 + NGX_SPDY_SETTINGS_PAIR_SIZE);
1639
1640 p = ngx_spdy_frame_aligned_write_uint32(p, 1);
1641 p = ngx_spdy_frame_aligned_write_uint32(p,
1642 NGX_SPDY_SETTINGS_MAX_STREAMS << 24
1643 | NGX_SPDY_SETTINGS_FLAG_PERSIST);
2096 NGX_SPDY_SETTINGS_NUM_SIZE
2097 + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE);
2098
2099 p = ngx_spdy_frame_aligned_write_uint32(p, 2);
16442100
16452101 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
16462102 ngx_http_spdy_module);
16472103
2104 p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_MAX_STREAMS);
16482105 p = ngx_spdy_frame_aligned_write_uint32(p, sscf->concurrent_streams);
2106
2107 p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_INIT_WINDOW);
2108 p = ngx_spdy_frame_aligned_write_uint32(p, NGX_SPDY_STREAM_WINDOW);
16492109
16502110 buf->last = p;
16512111
16742134
16752135
16762136 static ngx_http_spdy_out_frame_t *
1677 ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t size,
2137 ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t length,
16782138 ngx_uint_t priority)
16792139 {
16802140 ngx_chain_t *cl;
16832143 frame = sc->free_ctl_frames;
16842144
16852145 if (frame) {
1686 sc->free_ctl_frames = frame->free;
2146 sc->free_ctl_frames = frame->next;
16872147
16882148 cl = frame->first;
16892149 cl->buf->pos = cl->buf->start;
17102170 frame->first = cl;
17112171 frame->last = cl;
17122172 frame->handler = ngx_http_spdy_ctl_frame_handler;
1713 }
1714
1715 frame->free = NULL;
2173 frame->stream = NULL;
2174 }
17162175
17172176 #if (NGX_DEBUG)
1718 if (size > NGX_SPDY_CTL_FRAME_BUFFER_SIZE - NGX_SPDY_FRAME_HEADER_SIZE) {
2177 if (length > NGX_SPDY_CTL_FRAME_BUFFER_SIZE - NGX_SPDY_FRAME_HEADER_SIZE) {
17192178 ngx_log_error(NGX_LOG_ALERT, sc->pool->log, 0,
1720 "requested control frame is too big: %z", size);
2179 "requested control frame is too big: %uz", length);
17212180 return NULL;
17222181 }
17232182
1724 frame->stream = NULL;
1725 frame->size = size;
2183 frame->length = length;
17262184 #endif
17272185
17282186 frame->priority = priority;
17442202 return NGX_AGAIN;
17452203 }
17462204
1747 frame->free = sc->free_ctl_frames;
2205 frame->next = sc->free_ctl_frames;
17482206 sc->free_ctl_frames = frame;
17492207
17502208 return NGX_OK;
18132271
18142272 rev->data = fc;
18152273 rev->ready = 1;
1816 rev->handler = ngx_http_empty_handler;
2274 rev->handler = ngx_http_spdy_close_stream_handler;
18172275 rev->log = log;
18182276
18192277 ngx_memcpy(wev, rev, sizeof(ngx_event_t));
18632321 stream->id = id;
18642322 stream->request = r;
18652323 stream->connection = sc;
2324
2325 stream->send_window = sc->init_window;
2326 stream->recv_window = NGX_SPDY_STREAM_WINDOW;
2327
18662328 stream->priority = priority;
18672329
18682330 sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module);
19062368 ngx_http_spdy_parse_header(ngx_http_request_t *r)
19072369 {
19082370 u_char *p, *end, ch;
1909 ngx_uint_t len, hash;
2371 ngx_uint_t hash;
19102372 ngx_http_core_srv_conf_t *cscf;
19112373
19122374 enum {
19292391 return NGX_AGAIN;
19302392 }
19312393
1932 len = ngx_spdy_frame_parse_uint16(p);
1933
1934 if (!len) {
2394 r->lowcase_index = ngx_spdy_frame_parse_uint32(p);
2395
2396 if (r->lowcase_index == 0) {
19352397 return NGX_HTTP_PARSE_INVALID_HEADER;
19362398 }
19372399
2400 /* null-terminate the previous header value */
2401 *p = '\0';
2402
19382403 p += NGX_SPDY_NV_NLEN_SIZE;
19392404
1940 r->header_name_end = p + len;
1941 r->lowcase_index = len;
19422405 r->invalid_header = 0;
19432406
19442407 state = sw_name;
19472410
19482411 case sw_name:
19492412
1950 if (r->header_name_end > end) {
2413 if ((ngx_uint_t) (end - p) < r->lowcase_index) {
19512414 break;
19522415 }
19532416
19542417 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
19552418
19562419 r->header_name_start = p;
2420 r->header_name_end = p + r->lowcase_index;
2421
2422 if (p[0] == ':') {
2423 p++;
2424 }
19572425
19582426 hash = 0;
19592427
19982466 break;
19992467 }
20002468
2001 len = ngx_spdy_frame_parse_uint16(p);
2002
2003 if (!len) {
2004 return NGX_ERROR;
2005 }
2469 r->lowcase_index = ngx_spdy_frame_parse_uint32(p);
2470
2471 /* null-terminate header name */
2472 *p = '\0';
20062473
20072474 p += NGX_SPDY_NV_VLEN_SIZE;
20082475
2009 r->header_end = p + len;
2010
20112476 state = sw_value;
20122477
20132478 /* fall through */
20142479
20152480 case sw_value:
20162481
2017 if (r->header_end > end) {
2482 if ((ngx_uint_t) (end - p) < r->lowcase_index) {
20182483 break;
20192484 }
20202485
20212486 r->header_start = p;
20222487
2023 for ( /* void */ ; p != r->header_end; p++) {
2024
2488 while (r->lowcase_index--) {
20252489 ch = *p;
20262490
20272491 if (ch == '\0') {
20302494 return NGX_ERROR;
20312495 }
20322496
2033 r->header_size = p - r->header_start;
2497 r->header_end = p;
20342498 r->header_in->pos = p + 1;
20352499
20362500 return NGX_OK;
20392503 if (ch == CR || ch == LF) {
20402504 return NGX_HTTP_PARSE_INVALID_HEADER;
20412505 }
2042 }
2043
2044 r->header_size = p - r->header_start;
2506
2507 p++;
2508 }
2509
2510 r->header_end = p;
20452511 r->header_in->pos = p;
20462512
20472513 r->state = 0;
20902556 }
20912557
20922558 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2093 "spdy large header alloc: %p %uz",
2559 "spdy large header alloc: %p %z",
20942560 buf->pos, buf->end - buf->last);
20952561
20962562 old = r->header_in->pos;
20982564
20992565 if (rest) {
21002566 buf->last = ngx_cpymem(new, old, rest);
2101 }
2102
2103 if (r->header_name_end > old) {
2104 r->header_name_end = new + (r->header_name_end - old);
2105
2106 } else if (r->header_end > old) {
2107 r->header_end = new + (r->header_end - old);
21082567 }
21092568
21102569 r->header_in = buf;
21342593 return NGX_OK;
21352594 }
21362595
2137 } else {
2596 }
2597
2598 if (r->header_name_start[0] == ':') {
2599 r->header_name_start++;
2600
21382601 for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) {
21392602 sh = &ngx_http_spdy_request_headers[i];
21402603
21412604 if (sh->hash != r->header_hash
2142 || sh->len != r->lowcase_index
2143 || ngx_strncmp(sh->header, r->header_name_start,
2144 r->lowcase_index)
2145 != 0)
2605 || sh->len != r->header_name_end - r->header_name_start
2606 || ngx_strncmp(sh->header, r->header_name_start, sh->len) != 0)
21462607 {
21472608 continue;
21482609 }
21492610
21502611 return sh->handler(r);
21512612 }
2613
2614 return NGX_HTTP_PARSE_INVALID_REQUEST;
21522615 }
21532616
21542617 h = ngx_list_push(&r->headers_in.headers);
21602623
21612624 h->hash = r->header_hash;
21622625
2163 h->key.len = r->lowcase_index;
2626 h->key.len = r->header_name_end - r->header_name_start;
21642627 h->key.data = r->header_name_start;
2165 h->key.data[h->key.len] = '\0';
2166
2167 h->value.len = r->header_size;
2628
2629 h->value.len = r->header_end - r->header_start;
21682630 h->value.data = r->header_start;
2169 h->value.data[h->value.len] = '\0';
21702631
21712632 h->lowcase_key = h->key.data;
21722633
21752636
21762637
21772638 void
2178 ngx_http_spdy_request_headers_init()
2639 ngx_http_spdy_request_headers_init(void)
21792640 {
21802641 ngx_uint_t i;
21812642 ngx_http_spdy_request_header_t *h;
22252686 return NGX_HTTP_PARSE_INVALID_HEADER;
22262687 }
22272688
2228 len = r->header_size;
2689 len = r->header_end - r->header_start;
22292690
22302691 r->method_name.len = len;
22312692 r->method_name.data = r->header_start;
22862747
22872748
22882749 static ngx_int_t
2289 ngx_http_spdy_parse_url(ngx_http_request_t *r)
2750 ngx_http_spdy_parse_host(ngx_http_request_t *r)
2751 {
2752 ngx_table_elt_t *h;
2753
2754 if (r->headers_in.host) {
2755 return NGX_HTTP_PARSE_INVALID_HEADER;
2756 }
2757
2758 h = ngx_list_push(&r->headers_in.headers);
2759 if (h == NULL) {
2760 ngx_http_spdy_close_stream(r->spdy_stream,
2761 NGX_HTTP_INTERNAL_SERVER_ERROR);
2762 return NGX_ERROR;
2763 }
2764
2765 r->headers_in.host = h;
2766
2767 h->hash = r->header_hash;
2768
2769 h->key.len = r->header_name_end - r->header_name_start;
2770 h->key.data = r->header_name_start;
2771
2772 h->value.len = r->header_end - r->header_start;
2773 h->value.data = r->header_start;
2774
2775 h->lowcase_key = h->key.data;
2776
2777 return NGX_OK;
2778 }
2779
2780
2781 static ngx_int_t
2782 ngx_http_spdy_parse_path(ngx_http_request_t *r)
22902783 {
22912784 if (r->unparsed_uri.len) {
22922785 return NGX_HTTP_PARSE_INVALID_HEADER;
23182811
23192812 p = r->header_start;
23202813
2321 if (r->header_size < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) {
2814 if (r->header_end - p < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) {
23222815 return NGX_HTTP_PARSE_INVALID_REQUEST;
23232816 }
23242817
23342827
23352828 ch = *p;
23362829
2830 if (ch == '.') {
2831 break;
2832 }
2833
23372834 if (ch < '0' || ch > '9') {
23382835 return NGX_HTTP_PARSE_INVALID_REQUEST;
23392836 }
23642861 r->http_minor = r->http_minor * 10 + ch - '0';
23652862 }
23662863
2367 r->http_protocol.len = r->header_size;
2864 r->http_protocol.len = r->header_end - r->header_start;
23682865 r->http_protocol.data = r->header_start;
23692866 r->http_version = r->http_major * 1000 + r->http_minor;
23702867
24612958 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
24622959
24632960 if (ngx_http_process_request_header(r) != NGX_OK) {
2961 return;
2962 }
2963
2964 if (r->headers_in.content_length_n > 0 && r->spdy_stream->in_closed) {
2965 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2966 "client prematurely closed stream");
2967
2968 r->spdy_stream->skip_data = NGX_SPDY_DATA_ERROR;
2969
2970 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
24642971 return;
24652972 }
24662973
25963103
25973104 r->request_body->post_handler = post_handler;
25983105
3106 r->read_event_handler = ngx_http_test_reading;
3107 r->write_event_handler = ngx_http_request_empty_handler;
3108
25993109 return NGX_AGAIN;
3110 }
3111
3112
3113 static ngx_int_t
3114 ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc,
3115 ngx_http_spdy_stream_t *stream, ngx_uint_t status)
3116 {
3117 ngx_event_t *rev;
3118 ngx_connection_t *fc;
3119
3120 if (ngx_http_spdy_send_rst_stream(sc, stream->id, status,
3121 NGX_SPDY_HIGHEST_PRIORITY)
3122 == NGX_ERROR)
3123 {
3124 return NGX_ERROR;
3125 }
3126
3127 stream->out_closed = 1;
3128
3129 fc = stream->request->connection;
3130 fc->error = 1;
3131
3132 rev = fc->read;
3133 rev->handler(rev);
3134
3135 return NGX_OK;
3136 }
3137
3138
3139 static void
3140 ngx_http_spdy_close_stream_handler(ngx_event_t *ev)
3141 {
3142 ngx_connection_t *fc;
3143 ngx_http_request_t *r;
3144
3145 fc = ev->data;
3146 r = fc->data;
3147
3148 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3149 "spdy close stream handler");
3150
3151 ngx_http_spdy_close_stream(r->spdy_stream, 0);
26003152 }
26013153
26023154
26113163
26123164 sc = stream->connection;
26133165
2614 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
2615 "spdy close stream %ui, processing %ui",
2616 stream->id, sc->processing);
3166 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
3167 "spdy close stream %ui, queued %ui, processing %ui",
3168 stream->id, stream->queued, sc->processing);
3169
3170 fc = stream->request->connection;
3171
3172 if (stream->queued) {
3173 fc->write->handler = ngx_http_spdy_close_stream_handler;
3174 return;
3175 }
26173176
26183177 if (!stream->out_closed) {
26193178 if (ngx_http_spdy_send_rst_stream(sc, stream->id,
26493208 index = &s->index;
26503209 }
26513210
2652 fc = stream->request->connection;
2653
26543211 ngx_http_free_request(stream->request, rc);
26553212
26563213 ev = fc->read;
26573214
26583215 if (ev->active || ev->disabled) {
2659 ngx_del_event(ev, NGX_READ_EVENT, 0);
3216 ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
3217 "spdy fake read event was activated");
26603218 }
26613219
26623220 if (ev->timer_set) {
26703228 ev = fc->write;
26713229
26723230 if (ev->active || ev->disabled) {
2673 ngx_del_event(ev, NGX_WRITE_EVENT, 0);
3231 ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0,
3232 "spdy fake write event was activated");
26743233 }
26753234
26763235 if (ev->timer_set) {
28013360
28023361 c->error = 1;
28033362 c->read->handler = ngx_http_empty_handler;
3363 c->write->handler = ngx_http_empty_handler;
28043364
28053365 sc->last_out = NULL;
28063366
28153375 stream = sc->streams_index[i];
28163376
28173377 while (stream) {
3378 stream->handled = 0;
3379
28183380 r = stream->request;
2819
28203381 fc = r->connection;
3382
28213383 fc->error = 1;
28223384
2823 if (stream->waiting) {
2824 r->blocked -= stream->waiting;
2825 stream->waiting = 0;
3385 if (stream->queued) {
3386 stream->queued = 0;
3387
28263388 ev = fc->write;
3389 ev->delayed = 0;
28273390
28283391 } else {
28293392 ev = fc->read;
28463409 }
28473410
28483411
3412 static ngx_int_t
3413 ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, ssize_t delta)
3414 {
3415 ngx_uint_t i, size;
3416 ngx_event_t *wev;
3417 ngx_http_spdy_stream_t *stream, *sn;
3418 ngx_http_spdy_srv_conf_t *sscf;
3419
3420 sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx,
3421 ngx_http_spdy_module);
3422
3423 size = ngx_http_spdy_streams_index_size(sscf);
3424
3425 for (i = 0; i < size; i++) {
3426
3427 for (stream = sc->streams_index[i]; stream; stream = sn) {
3428 sn = stream->index;
3429
3430 if (delta > 0
3431 && stream->send_window
3432 > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta))
3433 {
3434 if (ngx_http_spdy_terminate_stream(sc, stream,
3435 NGX_SPDY_FLOW_CONTROL_ERROR)
3436 == NGX_ERROR)
3437 {
3438 return NGX_ERROR;
3439 }
3440
3441 continue;
3442 }
3443
3444 stream->send_window += delta;
3445
3446 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
3447 "spdy:%ui adjust window:%z",
3448 stream->id, stream->send_window);
3449
3450 if (stream->send_window > 0 && stream->exhausted) {
3451 stream->exhausted = 0;
3452
3453 wev = stream->request->connection->write;
3454
3455 if (!wev->timer_set) {
3456 wev->delayed = 0;
3457 wev->handler(wev);
3458 }
3459 }
3460 }
3461 }
3462
3463 return NGX_OK;
3464 }
3465
3466
28493467 static void
28503468 ngx_http_spdy_pool_cleanup(void *data)
28513469 {
1414 #include <zlib.h>
1515
1616
17 #define NGX_SPDY_VERSION 2
18
19 #ifdef TLSEXT_TYPE_next_proto_neg
20 #define NGX_SPDY_NPN_ADVERTISE "\x06spdy/2"
21 #define NGX_SPDY_NPN_NEGOTIATED "spdy/2"
22 #endif
17 #define NGX_SPDY_VERSION 3
18
19 #define NGX_SPDY_NPN_ADVERTISE "\x08spdy/3.1"
20 #define NGX_SPDY_NPN_NEGOTIATED "spdy/3.1"
2321
2422 #define NGX_SPDY_STATE_BUFFER_SIZE 16
2523
2927 #define NGX_SPDY_SYN_REPLY 2
3028 #define NGX_SPDY_RST_STREAM 3
3129 #define NGX_SPDY_SETTINGS 4
32 #define NGX_SPDY_NOOP 5
3330 #define NGX_SPDY_PING 6
3431 #define NGX_SPDY_GOAWAY 7
3532 #define NGX_SPDY_HEADERS 8
33 #define NGX_SPDY_WINDOW_UPDATE 9
3634
3735 #define NGX_SPDY_FRAME_HEADER_SIZE 8
3836
3937 #define NGX_SPDY_SID_SIZE 4
38 #define NGX_SPDY_DELTA_SIZE 4
4039
4140 #define NGX_SPDY_SYN_STREAM_SIZE 10
42 #define NGX_SPDY_SYN_REPLY_SIZE 6
41 #define NGX_SPDY_SYN_REPLY_SIZE 4
4342 #define NGX_SPDY_RST_STREAM_SIZE 8
4443 #define NGX_SPDY_PING_SIZE 4
45 #define NGX_SPDY_GOAWAY_SIZE 4
46 #define NGX_SPDY_NV_NUM_SIZE 2
47 #define NGX_SPDY_NV_NLEN_SIZE 2
48 #define NGX_SPDY_NV_VLEN_SIZE 2
44 #define NGX_SPDY_GOAWAY_SIZE 8
45 #define NGX_SPDY_WINDOW_UPDATE_SIZE 8
46 #define NGX_SPDY_NV_NUM_SIZE 4
47 #define NGX_SPDY_NV_NLEN_SIZE 4
48 #define NGX_SPDY_NV_VLEN_SIZE 4
4949 #define NGX_SPDY_SETTINGS_NUM_SIZE 4
50 #define NGX_SPDY_SETTINGS_IDF_SIZE 4
50 #define NGX_SPDY_SETTINGS_FID_SIZE 4
5151 #define NGX_SPDY_SETTINGS_VAL_SIZE 4
5252
5353 #define NGX_SPDY_SETTINGS_PAIR_SIZE \
54 (NGX_SPDY_SETTINGS_IDF_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE)
54 (NGX_SPDY_SETTINGS_FID_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE)
5555
5656 #define NGX_SPDY_HIGHEST_PRIORITY 0
57 #define NGX_SPDY_LOWEST_PRIORITY 3
57 #define NGX_SPDY_LOWEST_PRIORITY 7
5858
5959 #define NGX_SPDY_FLAG_FIN 0x01
6060 #define NGX_SPDY_FLAG_UNIDIRECTIONAL 0x02
8080
8181 ngx_uint_t processing;
8282
83 size_t send_window;
84 size_t recv_window;
85 size_t init_window;
86
87 ngx_queue_t waiting;
88
8389 u_char buffer[NGX_SPDY_STATE_BUFFER_SIZE];
8490 size_t buffer_used;
8591 ngx_http_spdy_handler_pt handler;
95101 ngx_http_spdy_stream_t **streams_index;
96102
97103 ngx_http_spdy_out_frame_t *last_out;
98 ngx_http_spdy_stream_t *last_stream;
104
105 ngx_queue_t posted;
99106
100107 ngx_http_spdy_stream_t *stream;
101108
102 ngx_uint_t headers;
109 ngx_uint_t entries;
103110 size_t length;
104111 u_char flags;
105112
106113 ngx_uint_t last_sid;
107114
108 unsigned blocked:2;
109 unsigned waiting:1; /* FIXME better name */
115 unsigned blocked:1;
116 unsigned incomplete:1;
110117 };
111118
112119
115122 ngx_http_request_t *request;
116123 ngx_http_spdy_connection_t *connection;
117124 ngx_http_spdy_stream_t *index;
118 ngx_http_spdy_stream_t *next;
119125
120126 ngx_uint_t header_buffers;
121 ngx_uint_t waiting;
127 ngx_uint_t queued;
128
129 /*
130 * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the
131 * send_window to become negative, hence it's signed.
132 */
133 ssize_t send_window;
134 size_t recv_window;
135
122136 ngx_http_spdy_out_frame_t *free_frames;
123137 ngx_chain_t *free_data_headers;
124
125 unsigned priority:2;
138 ngx_chain_t *free_bufs;
139
140 ngx_queue_t queue;
141
142 unsigned priority:3;
126143 unsigned handled:1;
144 unsigned blocked:1;
145 unsigned exhausted:1;
127146 unsigned in_closed:1;
128147 unsigned out_closed:1;
129148 unsigned skip_data:2;
137156 ngx_int_t (*handler)(ngx_http_spdy_connection_t *sc,
138157 ngx_http_spdy_out_frame_t *frame);
139158
140 ngx_http_spdy_out_frame_t *free;
141
142159 ngx_http_spdy_stream_t *stream;
143 size_t size;
160 size_t length;
144161
145162 ngx_uint_t priority;
146163 unsigned blocked:1;
156173
157174 for (out = &sc->last_out; *out; out = &(*out)->next)
158175 {
176 /*
177 * NB: higher values represent lower priorities.
178 */
159179 if (frame->priority >= (*out)->priority) {
160180 break;
161181 }
172192 {
173193 ngx_http_spdy_out_frame_t **out;
174194
175 for (out = &sc->last_out; *out && !(*out)->blocked; out = &(*out)->next)
195 for (out = &sc->last_out; *out; out = &(*out)->next)
176196 {
177 if (frame->priority >= (*out)->priority) {
197 if ((*out)->blocked) {
178198 break;
179199 }
180200 }
185205
186206
187207 void ngx_http_spdy_init(ngx_event_t *rev);
188 void ngx_http_spdy_request_headers_init();
208 void ngx_http_spdy_request_headers_init(void);
189209
190210 ngx_int_t ngx_http_spdy_read_request_body(ngx_http_request_t *r,
191211 ngx_http_client_body_handler_pt post_handler);
228248
229249 #define ngx_spdy_frame_write_flags_and_len(p, f, l) \
230250 ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (l))
231
232 #define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32
251 #define ngx_spdy_frame_write_flags_and_id(p, f, i) \
252 ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (i))
253
254 #define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32
255 #define ngx_spdy_frame_write_window ngx_spdy_frame_aligned_write_uint32
233256
234257 #endif /* _NGX_HTTP_SPDY_H_INCLUDED_ */
1313 #include <zlib.h>
1414
1515
16 #define NGX_SPDY_WRITE_BUFFERED NGX_HTTP_WRITE_BUFFERED
17
1816 #define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1)
1917 #define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1)
2018
21 #define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint16
22 #define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint16
23 #define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint16
19 #define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint32
20 #define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint32
21 #define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint32
2422
2523 #define ngx_http_spdy_nv_write_name(p, h) \
2624 ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
2826 #define ngx_http_spdy_nv_write_val(p, h) \
2927 ngx_cpymem(ngx_http_spdy_nv_write_vlen(p, sizeof(h) - 1), h, sizeof(h) - 1)
3028
29
30 static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc,
31 ngx_chain_t *in, off_t limit);
32
3133 static ngx_inline ngx_int_t ngx_http_spdy_filter_send(
3234 ngx_connection_t *fc, ngx_http_spdy_stream_t *stream);
33
35 static ngx_inline ngx_int_t ngx_http_spdy_flow_control(
36 ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream);
37 static void ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
38 ngx_http_spdy_stream_t *stream);
39
40 static ngx_chain_t *ngx_http_spdy_filter_get_shadow(
41 ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size);
3442 static ngx_http_spdy_out_frame_t *ngx_http_spdy_filter_get_data_frame(
35 ngx_http_spdy_stream_t *stream, size_t len, ngx_uint_t flags,
36 ngx_chain_t *first, ngx_chain_t *last);
43 ngx_http_spdy_stream_t *stream, size_t len, ngx_chain_t *first,
44 ngx_chain_t *last);
3745
3846 static ngx_int_t ngx_http_spdy_syn_frame_handler(
3947 ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame);
8189
8290
8391 static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
84 static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
8592
8693
8794 static ngx_int_t
158165 }
159166
160167 len = NGX_SPDY_NV_NUM_SIZE
161 + ngx_http_spdy_nv_nsize("version")
168 + ngx_http_spdy_nv_nsize(":version")
162169 + ngx_http_spdy_nv_vsize("HTTP/1.1")
163 + ngx_http_spdy_nv_nsize("status")
164 + ngx_http_spdy_nv_vsize("418");
170 + ngx_http_spdy_nv_nsize(":status")
171 + (r->headers_out.status_line.len
172 ? NGX_SPDY_NV_VLEN_SIZE + r->headers_out.status_line.len
173 : ngx_http_spdy_nv_vsize("418"));
165174
166175 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
167176
299308
300309 last = buf + NGX_SPDY_NV_NUM_SIZE;
301310
302 last = ngx_http_spdy_nv_write_name(last, "version");
311 last = ngx_http_spdy_nv_write_name(last, ":version");
303312 last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1");
304313
305 last = ngx_http_spdy_nv_write_name(last, "status");
306 last = ngx_spdy_frame_write_uint16(last, 3);
307 last = ngx_sprintf(last, "%03ui", r->headers_out.status);
314 last = ngx_http_spdy_nv_write_name(last, ":status");
315
316 if (r->headers_out.status_line.len) {
317 last = ngx_http_spdy_nv_write_vlen(last,
318 r->headers_out.status_line.len);
319 last = ngx_cpymem(last, r->headers_out.status_line.data,
320 r->headers_out.status_line.len);
321 } else {
322 last = ngx_http_spdy_nv_write_vlen(last, 3);
323 last = ngx_sprintf(last, "%03ui", r->headers_out.status);
324 }
308325
309326 count = 2;
310327
440457 }
441458
442459 if (header[i].hash == 0 || header[i].hash == 2) {
443 continue;
444 }
445
446 if ((header[i].key.len == 6
447 && ngx_strncasecmp(header[i].key.data,
448 (u_char *) "status", 6) == 0)
449 || (header[i].key.len == 7
450 && ngx_strncasecmp(header[i].key.data,
451 (u_char *) "version", 7) == 0))
452 {
453 header[i].hash = 0;
454460 continue;
455461 }
456462
499505 count++;
500506 }
501507
502 (void) ngx_spdy_frame_write_uint16(buf, count);
508 (void) ngx_http_spdy_nv_write_num(buf, count);
503509
504510 stream = r->spdy_stream;
505511 sc = stream->connection;
546552
547553 r->header_size = len;
548554
555 len -= NGX_SPDY_FRAME_HEADER_SIZE;
556
549557 if (r->header_only) {
550558 b->last_buf = 1;
551 p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN,
552 len - NGX_SPDY_FRAME_HEADER_SIZE);
559 p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN, len);
560
553561 } else {
554 p = ngx_spdy_frame_write_flags_and_len(p, 0,
555 len - NGX_SPDY_FRAME_HEADER_SIZE);
562 p = ngx_spdy_frame_write_flags_and_len(p, 0, len);
556563 }
557564
558565 (void) ngx_spdy_frame_write_sid(p, stream->id);
573580 frame->first = cl;
574581 frame->last = cl;
575582 frame->handler = ngx_http_spdy_syn_frame_handler;
576 frame->free = NULL;
577583 frame->stream = stream;
578 frame->size = len;
584 frame->length = len;
579585 frame->priority = stream->priority;
580586 frame->blocked = 1;
581587 frame->fin = r->header_only;
582588
583589 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0,
584 "spdy:%ui create SYN_REPLY frame %p: size:%uz",
585 stream->id, frame, frame->size);
590 "spdy:%ui create SYN_REPLY frame %p: len:%uz",
591 stream->id, frame, frame->length);
586592
587593 ngx_http_spdy_queue_blocked_frame(sc, frame);
588
589 r->blocked++;
590594
591595 cln = ngx_http_cleanup_add(r, 0);
592596 if (cln == NULL) {
596600 cln->handler = ngx_http_spdy_filter_cleanup;
597601 cln->data = stream;
598602
599 stream->waiting = 1;
603 stream->queued = 1;
604
605 c->send_chain = ngx_http_spdy_send_chain;
606 c->need_last_buf = 1;
600607
601608 return ngx_http_spdy_filter_send(c, stream);
602609 }
603610
604611
605 static ngx_int_t
606 ngx_http_spdy_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
612 static ngx_chain_t *
613 ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit)
607614 {
608 off_t size;
609 ngx_buf_t *b;
610 ngx_chain_t *cl, *ll, *out, **ln;
611 ngx_http_spdy_stream_t *stream;
612 ngx_http_spdy_out_frame_t *frame;
613
615 off_t size, offset;
616 size_t rest, frame_size;
617 ngx_chain_t *cl, *out, **ln;
618 ngx_http_request_t *r;
619 ngx_http_spdy_stream_t *stream;
620 ngx_http_spdy_loc_conf_t *slcf;
621 ngx_http_spdy_out_frame_t *frame;
622 ngx_http_spdy_connection_t *sc;
623
624 r = fc->data;
614625 stream = r->spdy_stream;
615626
616 if (stream == NULL) {
617 return ngx_http_next_body_filter(r, in);
618 }
619
620 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
621 "spdy body filter \"%V?%V\"", &r->uri, &r->args);
622
623 if (in == NULL || r->header_only) {
624
625 if (stream->waiting) {
626 return NGX_AGAIN;
627 }
628
629 r->connection->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
630
631 return NGX_OK;
632 }
633
627 #if (NGX_SUPPRESS_WARN)
634628 size = 0;
635 ln = &out;
636 ll = in;
637
638 for ( ;; ) {
639 b = ll->buf;
640 #if 1
641 if (ngx_buf_size(b) == 0 && !ngx_buf_special(b)) {
642 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
643 "zero size buf in spdy body filter "
644 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
645 b->temporary,
646 b->recycled,
647 b->in_file,
648 b->start,
649 b->pos,
650 b->last,
651 b->file,
652 b->file_pos,
653 b->file_last);
654
655 ngx_debug_point();
656 return NGX_ERROR;
657 }
658629 #endif
630
631 while (in) {
632 size = ngx_buf_size(in->buf);
633
634 if (size || in->buf->last_buf) {
635 break;
636 }
637
638 in = in->next;
639 }
640
641 if (in == NULL) {
642
643 if (stream->queued) {
644 fc->write->delayed = 1;
645 } else {
646 fc->buffered &= ~NGX_SPDY_BUFFERED;
647 }
648
649 return NULL;
650 }
651
652 sc = stream->connection;
653
654 if (size && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) {
655 fc->write->delayed = 1;
656 return in;
657 }
658
659 if (limit == 0 || limit > (off_t) sc->send_window) {
660 limit = sc->send_window;
661 }
662
663 if (limit > stream->send_window) {
664 limit = (stream->send_window > 0) ? stream->send_window : 0;
665 }
666
667 if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
659668 cl = ngx_alloc_chain_link(r->pool);
660669 if (cl == NULL) {
661 return NGX_ERROR;
662 }
663
664 size += ngx_buf_size(b);
665 cl->buf = b;
666
667 *ln = cl;
668 ln = &cl->next;
669
670 if (ll->next == NULL) {
670 return NGX_CHAIN_ERROR;
671 }
672
673 cl->buf = in->buf;
674 in->buf = cl->buf->shadow;
675
676 offset = ngx_buf_in_memory(in->buf)
677 ? (cl->buf->pos - in->buf->pos)
678 : (cl->buf->file_pos - in->buf->file_pos);
679
680 cl->next = stream->free_bufs;
681 stream->free_bufs = cl;
682
683 } else {
684 offset = 0;
685 }
686
687 #if (NGX_SUPPRESS_WARN)
688 cl = NULL;
689 #endif
690
691 slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module);
692
693 frame_size = (limit <= (off_t) slcf->chunk_size) ? (size_t) limit
694 : slcf->chunk_size;
695
696 for ( ;; ) {
697 ln = &out;
698 rest = frame_size;
699
700 while ((off_t) rest >= size) {
701
702 if (offset) {
703 cl = ngx_http_spdy_filter_get_shadow(stream, in->buf,
704 offset, size);
705 if (cl == NULL) {
706 return NGX_CHAIN_ERROR;
707 }
708
709 offset = 0;
710
711 } else {
712 cl = ngx_alloc_chain_link(r->pool);
713 if (cl == NULL) {
714 return NGX_CHAIN_ERROR;
715 }
716
717 cl->buf = in->buf;
718 }
719
720 *ln = cl;
721 ln = &cl->next;
722
723 rest -= (size_t) size;
724 in = in->next;
725
726 if (in == NULL) {
727 frame_size -= rest;
728 rest = 0;
729 break;
730 }
731
732 size = ngx_buf_size(in->buf);
733 }
734
735 if (rest) {
736 cl = ngx_http_spdy_filter_get_shadow(stream, in->buf,
737 offset, rest);
738 if (cl == NULL) {
739 return NGX_CHAIN_ERROR;
740 }
741
742 cl->buf->flush = 0;
743 cl->buf->last_buf = 0;
744
745 *ln = cl;
746
747 offset += rest;
748 size -= rest;
749 }
750
751 frame = ngx_http_spdy_filter_get_data_frame(stream, frame_size,
752 out, cl);
753 if (frame == NULL) {
754 return NGX_CHAIN_ERROR;
755 }
756
757 ngx_http_spdy_queue_frame(sc, frame);
758
759 sc->send_window -= frame_size;
760
761 stream->send_window -= frame_size;
762 stream->queued++;
763
764 if (in == NULL) {
671765 break;
672766 }
673767
674 ll = ll->next;
675 }
676
677 if (size > NGX_SPDY_MAX_FRAME_SIZE) {
678 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
679 "FIXME: chain too big in spdy filter: %O", size);
680 return NGX_ERROR;
681 }
682
683 frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
684 b->last_buf, out, cl);
685 if (frame == NULL) {
686 return NGX_ERROR;
687 }
688
689 ngx_http_spdy_queue_frame(stream->connection, frame);
690
691 stream->waiting++;
692
693 r->main->blocked++;
694
695 return ngx_http_spdy_filter_send(r->connection, stream);
768 limit -= frame_size;
769
770 if (limit == 0) {
771 break;
772 }
773
774 if (limit < (off_t) slcf->chunk_size) {
775 frame_size = (size_t) limit;
776 }
777 }
778
779 if (offset) {
780 cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size);
781 if (cl == NULL) {
782 return NGX_CHAIN_ERROR;
783 }
784
785 in->buf = cl->buf;
786 ngx_free_chain(r->pool, cl);
787 }
788
789 if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) {
790 return NGX_CHAIN_ERROR;
791 }
792
793 if (in && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) {
794 fc->write->delayed = 1;
795 }
796
797 return in;
798 }
799
800
801 static ngx_chain_t *
802 ngx_http_spdy_filter_get_shadow(ngx_http_spdy_stream_t *stream, ngx_buf_t *buf,
803 off_t offset, off_t size)
804 {
805 ngx_buf_t *chunk;
806 ngx_chain_t *cl;
807
808 cl = ngx_chain_get_free_buf(stream->request->pool, &stream->free_bufs);
809 if (cl == NULL) {
810 return NULL;
811 }
812
813 chunk = cl->buf;
814
815 ngx_memcpy(chunk, buf, sizeof(ngx_buf_t));
816
817 chunk->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow;
818 chunk->shadow = buf;
819
820 if (ngx_buf_in_memory(chunk)) {
821 chunk->pos += offset;
822 chunk->last = chunk->pos + size;
823 }
824
825 if (chunk->in_file) {
826 chunk->file_pos += offset;
827 chunk->file_last = chunk->file_pos + size;
828 }
829
830 return cl;
696831 }
697832
698833
699834 static ngx_http_spdy_out_frame_t *
700835 ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream,
701 size_t len, ngx_uint_t fin, ngx_chain_t *first, ngx_chain_t *last)
836 size_t len, ngx_chain_t *first, ngx_chain_t *last)
702837 {
703838 u_char *p;
704839 ngx_buf_t *buf;
710845 frame = stream->free_frames;
711846
712847 if (frame) {
713 stream->free_frames = frame->free;
848 stream->free_frames = frame->next;
714849
715850 } else {
716851 frame = ngx_palloc(stream->request->pool,
720855 }
721856 }
722857
858 flags = last->buf->last_buf ? NGX_SPDY_FLAG_FIN : 0;
859
723860 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0,
724 "spdy:%ui create DATA frame %p: len:%uz fin:%ui",
725 stream->id, frame, len, fin);
726
727 if (len || fin) {
728
729 flags = fin ? NGX_SPDY_FLAG_FIN : 0;
730
731 cl = ngx_chain_get_free_buf(stream->request->pool,
732 &stream->free_data_headers);
733 if (cl == NULL) {
861 "spdy:%ui create DATA frame %p: len:%uz flags:%ui",
862 stream->id, frame, len, flags);
863
864 cl = ngx_chain_get_free_buf(stream->request->pool,
865 &stream->free_data_headers);
866 if (cl == NULL) {
867 return NULL;
868 }
869
870 buf = cl->buf;
871
872 if (buf->start) {
873 p = buf->start;
874 buf->pos = p;
875
876 p += NGX_SPDY_SID_SIZE;
877
878 (void) ngx_spdy_frame_write_flags_and_len(p, flags, len);
879
880 } else {
881 p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE);
882 if (p == NULL) {
734883 return NULL;
735884 }
736885
737 buf = cl->buf;
738
739 if (buf->start) {
740 p = buf->start;
741 buf->pos = p;
742
743 p += sizeof(uint32_t);
744
745 (void) ngx_spdy_frame_write_flags_and_len(p, flags, len);
746
747 } else {
748 p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE);
749 if (p == NULL) {
750 return NULL;
751 }
752
753 buf->pos = p;
754 buf->start = p;
755
756 p = ngx_spdy_frame_write_sid(p, stream->id);
757 p = ngx_spdy_frame_write_flags_and_len(p, flags, len);
758
759 buf->last = p;
760 buf->end = p;
761
762 buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_module;
763 buf->memory = 1;
764 }
765
766 cl->next = first;
767 first = cl;
768 }
886 buf->pos = p;
887 buf->start = p;
888
889 p = ngx_spdy_frame_write_sid(p, stream->id);
890 p = ngx_spdy_frame_write_flags_and_len(p, flags, len);
891
892 buf->last = p;
893 buf->end = p;
894
895 buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame;
896 buf->memory = 1;
897 }
898
899 cl->next = first;
900 first = cl;
901
902 last->buf->flush = 1;
769903
770904 frame->first = first;
771905 frame->last = last;
772906 frame->handler = ngx_http_spdy_data_frame_handler;
773 frame->free = NULL;
774907 frame->stream = stream;
775 frame->size = NGX_SPDY_FRAME_HEADER_SIZE + len;
908 frame->length = len;
776909 frame->priority = stream->priority;
777910 frame->blocked = 0;
778 frame->fin = fin;
911 frame->fin = last->buf->last_buf;
779912
780913 return frame;
781914 }
784917 static ngx_inline ngx_int_t
785918 ngx_http_spdy_filter_send(ngx_connection_t *fc, ngx_http_spdy_stream_t *stream)
786919 {
920 stream->blocked = 1;
921
787922 if (ngx_http_spdy_send_output_queue(stream->connection) == NGX_ERROR) {
788923 fc->error = 1;
789924 return NGX_ERROR;
790925 }
791926
792 if (stream->waiting) {
793 fc->buffered |= NGX_SPDY_WRITE_BUFFERED;
927 stream->blocked = 0;
928
929 if (stream->queued) {
930 fc->buffered |= NGX_SPDY_BUFFERED;
794931 fc->write->delayed = 1;
795932 return NGX_AGAIN;
796933 }
797934
798 fc->buffered &= ~NGX_SPDY_WRITE_BUFFERED;
935 fc->buffered &= ~NGX_SPDY_BUFFERED;
799936
800937 return NGX_OK;
938 }
939
940
941 static ngx_inline ngx_int_t
942 ngx_http_spdy_flow_control(ngx_http_spdy_connection_t *sc,
943 ngx_http_spdy_stream_t *stream)
944 {
945 if (stream->send_window <= 0) {
946 stream->exhausted = 1;
947 return NGX_DECLINED;
948 }
949
950 if (sc->send_window == 0) {
951 ngx_http_spdy_waiting_queue(sc, stream);
952 return NGX_DECLINED;
953 }
954
955 return NGX_OK;
956 }
957
958
959 static void
960 ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc,
961 ngx_http_spdy_stream_t *stream)
962 {
963 ngx_queue_t *q;
964 ngx_http_spdy_stream_t *s;
965
966 if (stream->handled) {
967 return;
968 }
969
970 stream->handled = 1;
971
972 for (q = ngx_queue_last(&sc->waiting);
973 q != ngx_queue_sentinel(&sc->waiting);
974 q = ngx_queue_prev(q))
975 {
976 s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue);
977
978 /*
979 * NB: higher values represent lower priorities.
980 */
981 if (stream->priority >= s->priority) {
982 break;
983 }
984 }
985
986 ngx_queue_insert_after(q, &stream->queue);
801987 }
802988
803989
8331019 ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc,
8341020 ngx_http_spdy_out_frame_t *frame)
8351021 {
1022 ngx_buf_t *buf;
8361023 ngx_chain_t *cl, *ln;
8371024 ngx_http_spdy_stream_t *stream;
8381025
8401027
8411028 cl = frame->first;
8421029
843 if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_module) {
1030 if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame) {
8441031
8451032 if (cl->buf->pos != cl->buf->last) {
8461033 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0,
8631050 }
8641051
8651052 for ( ;; ) {
1053 if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
1054 buf = cl->buf->shadow;
1055
1056 if (ngx_buf_in_memory(buf)) {
1057 buf->pos = cl->buf->pos;
1058 }
1059
1060 if (buf->in_file) {
1061 buf->file_pos = cl->buf->file_pos;
1062 }
1063 }
1064
8661065 if (ngx_buf_size(cl->buf) != 0) {
8671066
8681067 if (cl != frame->first) {
8791078
8801079 ln = cl->next;
8811080
882 ngx_free_chain(stream->request->pool, cl);
1081 if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) {
1082 cl->next = stream->free_bufs;
1083 stream->free_bufs = cl;
1084
1085 } else {
1086 ngx_free_chain(stream->request->pool, cl);
1087 }
8831088
8841089 if (cl == frame->last) {
8851090 goto done;
9111116
9121117 r = stream->request;
9131118
914 r->connection->sent += frame->size;
915 r->blocked--;
1119 r->connection->sent += NGX_SPDY_FRAME_HEADER_SIZE + frame->length;
9161120
9171121 if (frame->fin) {
9181122 stream->out_closed = 1;
9191123 }
9201124
921 frame->free = stream->free_frames;
1125 frame->next = stream->free_frames;
9221126 stream->free_frames = frame;
9231127
924 stream->waiting--;
1128 stream->queued--;
9251129 }
9261130
9271131
9291133 ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc,
9301134 ngx_http_spdy_stream_t *stream)
9311135 {
932 ngx_connection_t *fc;
933
934 fc = stream->request->connection;
935
936 fc->write->delayed = 0;
937
938 if (stream->handled) {
1136 ngx_event_t *wev;
1137
1138 if (stream->handled || stream->blocked || stream->exhausted) {
9391139 return;
9401140 }
9411141
942 if (sc->blocked == 2) {
1142 wev = stream->request->connection->write;
1143
1144 if (!wev->timer_set) {
1145 wev->delayed = 0;
1146
9431147 stream->handled = 1;
944
945 stream->next = sc->last_stream;
946 sc->last_stream = stream;
1148 ngx_queue_insert_tail(&sc->posted, &stream->queue);
9471149 }
9481150 }
9491151
9531155 {
9541156 ngx_http_spdy_stream_t *stream = data;
9551157
956 ngx_http_request_t *r;
957 ngx_http_spdy_out_frame_t *frame, **fn;
958
959 if (stream->waiting == 0) {
1158 size_t delta;
1159 ngx_http_spdy_out_frame_t *frame, **fn;
1160 ngx_http_spdy_connection_t *sc;
1161
1162 if (stream->handled) {
1163 stream->handled = 0;
1164 ngx_queue_remove(&stream->queue);
1165 }
1166
1167 if (stream->queued == 0) {
9601168 return;
9611169 }
9621170
963 r = stream->request;
964
965 fn = &stream->connection->last_out;
1171 delta = 0;
1172 sc = stream->connection;
1173 fn = &sc->last_out;
9661174
9671175 for ( ;; ) {
9681176 frame = *fn;
9721180 }
9731181
9741182 if (frame->stream == stream && !frame->blocked) {
975
976 stream->waiting--;
977 r->blocked--;
978
9791183 *fn = frame->next;
1184
1185 delta += frame->length;
1186
1187 if (--stream->queued == 0) {
1188 break;
1189 }
1190
9801191 continue;
9811192 }
9821193
9831194 fn = &frame->next;
9841195 }
1196
1197 if (sc->send_window == 0 && delta && !ngx_queue_empty(&sc->waiting)) {
1198 ngx_queue_add(&sc->posted, &sc->waiting);
1199 ngx_queue_init(&sc->waiting);
1200 }
1201
1202 sc->send_window += delta;
9851203 }
9861204
9871205
9911209 ngx_http_next_header_filter = ngx_http_top_header_filter;
9921210 ngx_http_top_header_filter = ngx_http_spdy_header_filter;
9931211
994 ngx_http_next_body_filter = ngx_http_top_body_filter;
995 ngx_http_top_body_filter = ngx_http_spdy_body_filter;
996
9971212 return NGX_OK;
9981213 }
2121
2222 static void *ngx_http_spdy_create_main_conf(ngx_conf_t *cf);
2323 static char *ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf);
24
2524 static void *ngx_http_spdy_create_srv_conf(ngx_conf_t *cf);
2625 static char *ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent,
26 void *child);
27 static void *ngx_http_spdy_create_loc_conf(ngx_conf_t *cf);
28 static char *ngx_http_spdy_merge_loc_conf(ngx_conf_t *cf, void *parent,
2729 void *child);
2830
2931 static char *ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post,
3133 static char *ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data);
3234 static char *ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post,
3335 void *data);
36 static char *ngx_http_spdy_chunk_size(ngx_conf_t *cf, void *post, void *data);
3437
3538
3639 static ngx_conf_num_bounds_t ngx_http_spdy_headers_comp_bounds = {
4346 { ngx_http_spdy_pool_size };
4447 static ngx_conf_post_t ngx_http_spdy_streams_index_mask_post =
4548 { ngx_http_spdy_streams_index_mask };
49 static ngx_conf_post_t ngx_http_spdy_chunk_size_post =
50 { ngx_http_spdy_chunk_size };
4651
4752
4853 static ngx_command_t ngx_http_spdy_commands[] = {
96101 offsetof(ngx_http_spdy_srv_conf_t, headers_comp),
97102 &ngx_http_spdy_headers_comp_bounds },
98103
104 { ngx_string("spdy_chunk_size"),
105 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
106 ngx_conf_set_size_slot,
107 NGX_HTTP_LOC_CONF_OFFSET,
108 offsetof(ngx_http_spdy_loc_conf_t, chunk_size),
109 &ngx_http_spdy_chunk_size_post },
110
99111 ngx_null_command
100112 };
101113
110122 ngx_http_spdy_create_srv_conf, /* create server configuration */
111123 ngx_http_spdy_merge_srv_conf, /* merge server configuration */
112124
113 NULL, /* create location configuration */
114 NULL /* merge location configuration */
125 ngx_http_spdy_create_loc_conf, /* create location configuration */
126 ngx_http_spdy_merge_loc_conf /* merge location configuration */
115127 };
116128
117129
167179 ngx_http_variable_value_t *v, uintptr_t data)
168180 {
169181 if (r->spdy_stream) {
170 v->len = 1;
182 v->len = sizeof("3.1") - 1;
171183 v->valid = 1;
172184 v->no_cacheable = 0;
173185 v->not_found = 0;
174 v->data = (u_char *) "2";
186 v->data = (u_char *) "3.1";
175187
176188 return NGX_OK;
177189 }
238250 {
239251 ngx_http_spdy_main_conf_t *smcf = conf;
240252
241 if (smcf->recv_buffer_size == NGX_CONF_UNSET_SIZE) {
242 smcf->recv_buffer_size = 256 * 1024;
243 }
253 ngx_conf_init_size_value(smcf->recv_buffer_size, 256 * 1024);
244254
245255 return NGX_CONF_OK;
246256 }
290300 prev->keepalive_timeout, 180000);
291301
292302 ngx_conf_merge_value(conf->headers_comp, prev->headers_comp, 0);
303
304 return NGX_CONF_OK;
305 }
306
307
308 static void *
309 ngx_http_spdy_create_loc_conf(ngx_conf_t *cf)
310 {
311 ngx_http_spdy_loc_conf_t *slcf;
312
313 slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_loc_conf_t));
314 if (slcf == NULL) {
315 return NULL;
316 }
317
318 slcf->chunk_size = NGX_CONF_UNSET_SIZE;
319
320 return slcf;
321 }
322
323
324 static char *
325 ngx_http_spdy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
326 {
327 ngx_http_spdy_loc_conf_t *prev = parent;
328 ngx_http_spdy_loc_conf_t *conf = child;
329
330 ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024);
293331
294332 return NGX_CONF_OK;
295333 }
348386
349387 return NGX_CONF_OK;
350388 }
389
390
391 static char *
392 ngx_http_spdy_chunk_size(ngx_conf_t *cf, void *post, void *data)
393 {
394 size_t *sp = data;
395
396 if (*sp == 0) {
397 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
398 "the spdy chunk size cannot be zero");
399 return NGX_CONF_ERROR;
400 }
401
402 if (*sp > NGX_SPDY_MAX_FRAME_SIZE) {
403 *sp = NGX_SPDY_MAX_FRAME_SIZE;
404 }
405
406 return NGX_CONF_OK;
407 }
2929 } ngx_http_spdy_srv_conf_t;
3030
3131
32 typedef struct {
33 size_t chunk_size;
34 } ngx_http_spdy_loc_conf_t;
35
36
3237 extern ngx_module_t ngx_http_spdy_module;
3338
3439
369369 ngx_http_core_loc_conf_t *clcf;
370370
371371 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
372 "http special response: %d, \"%V?%V\"",
372 "http special response: %i, \"%V?%V\"",
373373 error, &r->uri, &r->args);
374374
375375 r->err_status = error;
1515 static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
1616 ngx_http_upstream_t *u);
1717 static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
18 ngx_http_variable_value_t *v, uintptr_t data);
19 static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
1820 ngx_http_variable_value_t *v, uintptr_t data);
1921 #endif
2022
357359 ngx_http_upstream_cache_status, 0,
358360 NGX_HTTP_VAR_NOCACHEABLE, 0 },
359361
362 { ngx_string("upstream_cache_last_modified"), NULL,
363 ngx_http_upstream_cache_last_modified, 0,
364 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
365
360366 #endif
361367
362368 { ngx_null_string, NULL, NULL, 0, 0, 0 }
368374 { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502 },
369375 { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503 },
370376 { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 },
377 { 403, NGX_HTTP_UPSTREAM_FT_HTTP_403 },
371378 { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 },
372379 { 0, 0 }
373380 };
604611 if (uscf->host.len == host->len
605612 && ((uscf->port == 0 && u->resolved->no_port)
606613 || uscf->port == u->resolved->port)
607 && ngx_memcmp(uscf->host.data, host->data, host->len) == 0)
614 && ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0)
608615 {
609616 goto found;
610617 }
636643 }
637644
638645 ctx->name = *host;
639 ctx->type = NGX_RESOLVE_A;
640646 ctx->handler = ngx_http_upstream_resolve_handler;
641647 ctx->data = r;
642648 ctx->timeout = clcf->resolver_timeout;
708714 if (r->cache->header_start + 256 >= u->conf->buffer_size) {
709715 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
710716 "%V_buffer_size %uz is not enough for cache key, "
711 "it should increased at least to %uz",
717 "it should be increased to at least %uz",
712718 &u->conf->module, u->conf->buffer_size,
713719 ngx_align(r->cache->header_start + 256, 1024));
714720
910916
911917 #if (NGX_DEBUG)
912918 {
913 in_addr_t addr;
919 u_char text[NGX_SOCKADDR_STRLEN];
920 ngx_str_t addr;
914921 ngx_uint_t i;
915922
923 addr.data = text;
924
916925 for (i = 0; i < ctx->naddrs; i++) {
917 addr = ntohl(ur->addrs[i]);
918
919 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
920 "name was resolved to %ud.%ud.%ud.%ud",
921 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
922 (addr >> 8) & 0xff, addr & 0xff);
926 addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
927 text, NGX_SOCKADDR_STRLEN, 0);
928
929 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
930 "name was resolved to %V", &addr);
923931 }
924932 }
925933 #endif
10681076
10691077 #endif
10701078
1079 #if (NGX_HAVE_EPOLLRDHUP)
1080
1081 if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ev->pending_eof) {
1082 socklen_t len;
1083
1084 ev->eof = 1;
1085 c->error = 1;
1086
1087 err = 0;
1088 len = sizeof(ngx_err_t);
1089
1090 /*
1091 * BSDs and Linux return 0 and set a pending error in err
1092 * Solaris returns -1 and sets errno
1093 */
1094
1095 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
1096 == -1)
1097 {
1098 err = ngx_socket_errno;
1099 }
1100
1101 if (err) {
1102 ev->error = 1;
1103 }
1104
1105 if (!u->cacheable && u->peer.connection) {
1106 ngx_log_error(NGX_LOG_INFO, ev->log, err,
1107 "epoll_wait() reported that client prematurely closed "
1108 "connection, so upstream connection is closed too");
1109 ngx_http_upstream_finalize_request(r, u,
1110 NGX_HTTP_CLIENT_CLOSED_REQUEST);
1111 return;
1112 }
1113
1114 ngx_log_error(NGX_LOG_INFO, ev->log, err,
1115 "epoll_wait() reported that client prematurely closed "
1116 "connection");
1117
1118 if (u->peer.connection == NULL) {
1119 ngx_http_upstream_finalize_request(r, u,
1120 NGX_HTTP_CLIENT_CLOSED_REQUEST);
1121 }
1122
1123 return;
1124 }
1125
1126 #endif
1127
10711128 n = recv(c->fd, buf, 1, MSG_PEEK);
10721129
10731130 err = ngx_socket_errno;
11791236 return;
11801237 }
11811238
1182 /* rc == NGX_OK || rc == NGX_AGAIN */
1239 /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */
11831240
11841241 c = u->peer.connection;
11851242
12801337 {
12811338 ngx_int_t rc;
12821339
1340 if (ngx_http_upstream_test_connect(c) != NGX_OK) {
1341 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1342 return;
1343 }
1344
12831345 if (ngx_ssl_create_connection(u->conf->ssl, c,
12841346 NGX_SSL_BUFFER|NGX_SSL_CLIENT)
12851347 != NGX_OK)
13311393 c->write->handler = ngx_http_upstream_handler;
13321394 c->read->handler = ngx_http_upstream_handler;
13331395
1396 c = r->connection;
1397
13341398 ngx_http_upstream_send_request(r, u);
13351399
1336 return;
1337 }
1400 ngx_http_run_posted_requests(c);
1401 return;
1402 }
1403
1404 c = r->connection;
13381405
13391406 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
13401407
1408 ngx_http_run_posted_requests(c);
13411409 }
13421410
13431411 #endif
14701538
14711539 ngx_add_timer(c->read, u->conf->read_timeout);
14721540
1473 #if 1
14741541 if (c->read->ready) {
1475
1476 /* post aio operation */
1477
1478 /*
1479 * TODO comment
1480 * although we can post aio operation just in the end
1481 * of ngx_http_upstream_connect() CHECK IT !!!
1482 * it's better to do here because we postpone header buffer allocation
1483 */
1484
14851542 ngx_http_upstream_process_header(r, u);
14861543 return;
14871544 }
1488 #endif
14891545
14901546 u->write_event_handler = ngx_http_upstream_dummy_handler;
14911547
16591715
16601716 /* rc == NGX_OK */
16611717
1662 if (u->headers_in.status_n > NGX_HTTP_SPECIAL_RESPONSE) {
1663
1664 if (r->subrequest_in_memory) {
1665 u->buffer.last = u->buffer.pos;
1666 }
1718 if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) {
16671719
16681720 if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
16691721 return;
16921744 }
16931745
16941746 if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
1695 ngx_http_upstream_finalize_request(r, u,
1696 NGX_HTTP_INTERNAL_SERVER_ERROR);
1747 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
16971748 return;
16981749 }
16991750
17001751 n = u->buffer.last - u->buffer.pos;
17011752
17021753 if (n) {
1703 u->buffer.last -= n;
1754 u->buffer.last = u->buffer.pos;
17041755
17051756 u->state->response_length += n;
17061757
17081759 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
17091760 return;
17101761 }
1711
1712 if (u->length == 0) {
1713 ngx_http_upstream_finalize_request(r, u, 0);
1714 return;
1715 }
1762 }
1763
1764 if (u->length == 0) {
1765 ngx_http_upstream_finalize_request(r, u, 0);
1766 return;
17161767 }
17171768
17181769 u->read_event_handler = ngx_http_upstream_process_body_in_memory;
17601811
17611812 #endif
17621813 }
1814
1815 #if (NGX_HTTP_CACHE)
1816
1817 if (status == NGX_HTTP_NOT_MODIFIED
1818 && u->cache_status == NGX_HTTP_CACHE_EXPIRED
1819 && u->conf->cache_revalidate)
1820 {
1821 time_t now, valid;
1822 ngx_int_t rc;
1823
1824 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1825 "http upstream not modified");
1826
1827 now = ngx_time();
1828 valid = r->cache->valid_sec;
1829
1830 rc = u->reinit_request(r);
1831
1832 if (rc != NGX_OK) {
1833 ngx_http_upstream_finalize_request(r, u, rc);
1834 return NGX_OK;
1835 }
1836
1837 u->cache_status = NGX_HTTP_CACHE_REVALIDATED;
1838 rc = ngx_http_upstream_cache_send(r, u);
1839
1840 if (valid == 0) {
1841 valid = r->cache->valid_sec;
1842 }
1843
1844 if (valid == 0) {
1845 valid = ngx_http_file_cache_valid(u->conf->cache_valid,
1846 u->headers_in.status_n);
1847 if (valid) {
1848 valid = now + valid;
1849 }
1850 }
1851
1852 if (valid) {
1853 r->cache->valid_sec = valid;
1854 r->cache->date = now;
1855
1856 ngx_http_file_cache_update_header(r);
1857 }
1858
1859 ngx_http_upstream_finalize_request(r, u, rc);
1860 return NGX_OK;
1861 }
1862
1863 #endif
17631864
17641865 return NGX_DECLINED;
17651866 }
18751976 if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
18761977 == -1)
18771978 {
1878 err = ngx_errno;
1979 err = ngx_socket_errno;
18791980 }
18801981
18811982 if (err) {
18921993 static ngx_int_t
18931994 ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
18941995 {
1895 ngx_str_t *uri, args;
1996 ngx_str_t uri, args;
18961997 ngx_uint_t i, flags;
18971998 ngx_list_part_t *part;
18981999 ngx_table_elt_t *h;
19332034 }
19342035 }
19352036
1936 uri = &u->headers_in.x_accel_redirect->value;
2037 uri = u->headers_in.x_accel_redirect->value;
19372038 ngx_str_null(&args);
19382039 flags = NGX_HTTP_LOG_UNSAFE;
19392040
1940 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
2041 if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
19412042 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
19422043 return NGX_DONE;
19432044 }
19462047 r->method = NGX_HTTP_GET;
19472048 }
19482049
1949 ngx_http_internal_redirect(r, uri, &args);
2050 ngx_http_internal_redirect(r, &uri, &args);
19502051 ngx_http_finalize_request(r, NGX_DONE);
19512052 return NGX_DONE;
19522053 }
20052106
20062107 r->headers_out.content_length_n = u->headers_in.content_length_n;
20072108
2008 u->length = u->headers_in.content_length_n;
2109 u->length = -1;
20092110
20102111 return NGX_OK;
20112112 }
20292130
20302131 if (rev->timedout) {
20312132 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2032 ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT);
2133 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
20332134 return;
20342135 }
20352136
21052206 return;
21062207 }
21072208
2209 u->header_sent = 1;
2210
21082211 if (u->upgrade) {
21092212 ngx_http_upstream_upgrade(r, u);
21102213 return;
21302233 return;
21312234 }
21322235 }
2133
2134 u->header_sent = 1;
21352236
21362237 if (r->request_body && r->request_body->temp_file) {
21372238 ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
21552256 r->limit_rate = 0;
21562257
21572258 if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
2158 ngx_http_upstream_finalize_request(r, u, 0);
2259 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
21592260 return;
21602261 }
21612262
21692270 {
21702271 ngx_connection_error(c, ngx_socket_errno,
21712272 "setsockopt(TCP_NODELAY) failed");
2172 ngx_http_upstream_finalize_request(r, u, 0);
2273 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
21732274 return;
21742275 }
21752276
21842285 u->state->response_length += n;
21852286
21862287 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2187 ngx_http_upstream_finalize_request(r, u, 0);
2288 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
21882289 return;
21892290 }
21902291
21952296 u->buffer.last = u->buffer.start;
21962297
21972298 if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
2198 ngx_http_upstream_finalize_request(r, u, 0);
2299 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
21992300 return;
22002301 }
22012302
22192320 switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
22202321
22212322 case NGX_ERROR:
2222 ngx_http_upstream_finalize_request(r, u, 0);
2323 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
22232324 return;
22242325
22252326 case NGX_DECLINED:
22352336 r->cache->file_cache = u->conf->cache->data;
22362337
22372338 if (ngx_http_file_cache_create(r) != NGX_OK) {
2238 ngx_http_upstream_finalize_request(r, u, 0);
2339 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
22392340 return;
22402341 }
22412342 }
22962397
22972398 p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
22982399 if (p->temp_file == NULL) {
2299 ngx_http_upstream_finalize_request(r, u, 0);
2400 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
23002401 return;
23012402 }
23022403
23192420
23202421 p->preread_bufs = ngx_alloc_chain_link(r->pool);
23212422 if (p->preread_bufs == NULL) {
2322 ngx_http_upstream_finalize_request(r, u, 0);
2423 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
23232424 return;
23242425 }
23252426
23332434
23342435 p->buf_to_file = ngx_calloc_buf(r->pool);
23352436 if (p->buf_to_file == NULL) {
2336 ngx_http_upstream_finalize_request(r, u, 0);
2437 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
23372438 return;
23382439 }
23392440
23812482 if (u->input_filter_init
23822483 && u->input_filter_init(p->input_ctx) != NGX_OK)
23832484 {
2384 ngx_http_upstream_finalize_request(r, u, 0);
2485 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
23852486 return;
23862487 }
23872488
24232524 {
24242525 ngx_connection_error(c, ngx_socket_errno,
24252526 "setsockopt(TCP_NODELAY) failed");
2426 ngx_http_upstream_finalize_request(r, u, 0);
2527 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
24272528 return;
24282529 }
24292530
24392540 {
24402541 ngx_connection_error(u->peer.connection, ngx_socket_errno,
24412542 "setsockopt(TCP_NODELAY) failed");
2442 ngx_http_upstream_finalize_request(r, u, 0);
2543 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
24432544 return;
24442545 }
24452546
24482549 }
24492550
24502551 if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
2451 ngx_http_upstream_finalize_request(r, u, 0);
2552 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
24522553 return;
24532554 }
24542555
25232624
25242625 if (upstream->read->timedout || upstream->write->timedout) {
25252626 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2526 ngx_http_upstream_finalize_request(r, u, 0);
2627 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
25272628 return;
25282629 }
25292630
25462647 if (b->start == NULL) {
25472648 b->start = ngx_palloc(r->pool, u->conf->buffer_size);
25482649 if (b->start == NULL) {
2549 ngx_http_upstream_finalize_request(r, u, 0);
2650 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
25502651 return;
25512652 }
25522653
25692670 n = dst->send(dst, b->pos, size);
25702671
25712672 if (n == NGX_ERROR) {
2572 ngx_http_upstream_finalize_request(r, u, 0);
2673 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
25732674 return;
25742675 }
25752676
26242725 if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
26252726 != NGX_OK)
26262727 {
2627 ngx_http_upstream_finalize_request(r, u, 0);
2728 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
26282729 return;
26292730 }
26302731
26362737 }
26372738
26382739 if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
2639 ngx_http_upstream_finalize_request(r, u, 0);
2740 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
26402741 return;
26412742 }
26422743
26502751 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
26512752 != NGX_OK)
26522753 {
2653 ngx_http_upstream_finalize_request(r, u, 0);
2754 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
26542755 return;
26552756 }
26562757
26572758 if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) {
2658 ngx_http_upstream_finalize_request(r, u, 0);
2759 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
26592760 return;
26602761 }
26612762
27102811
27112812 if (c->read->timedout) {
27122813 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2713 ngx_http_upstream_finalize_request(r, u, 0);
2814 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
27142815 return;
27152816 }
27162817
27462847 rc = ngx_http_output_filter(r, u->out_bufs);
27472848
27482849 if (rc == NGX_ERROR) {
2749 ngx_http_upstream_finalize_request(r, u, 0);
2850 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
27502851 return;
27512852 }
27522853
27572858 if (u->busy_bufs == NULL) {
27582859
27592860 if (u->length == 0
2760 || upstream->read->eof
2761 || upstream->read->error)
2861 || (upstream->read->eof && u->length == -1))
27622862 {
27632863 ngx_http_upstream_finalize_request(r, u, 0);
27642864 return;
27652865 }
27662866
2867 if (upstream->read->eof) {
2868 ngx_log_error(NGX_LOG_ERR, upstream->log, 0,
2869 "upstream prematurely closed connection");
2870
2871 ngx_http_upstream_finalize_request(r, u,
2872 NGX_HTTP_BAD_GATEWAY);
2873 return;
2874 }
2875
2876 if (upstream->read->error) {
2877 ngx_http_upstream_finalize_request(r, u,
2878 NGX_HTTP_BAD_GATEWAY);
2879 return;
2880 }
2881
27672882 b->pos = b->start;
27682883 b->last = b->start;
27692884 }
27832898 u->state->response_length += n;
27842899
27852900 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2786 ngx_http_upstream_finalize_request(r, u, 0);
2901 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
27872902 return;
27882903 }
27892904 }
28022917 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
28032918 != NGX_OK)
28042919 {
2805 ngx_http_upstream_finalize_request(r, u, 0);
2920 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
28062921 return;
28072922 }
28082923 }
28152930 }
28162931
28172932 if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
2818 ngx_http_upstream_finalize_request(r, u, 0);
2933 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
28192934 return;
28202935 }
28212936
29063021 ngx_add_timer(wev, p->send_timeout);
29073022
29083023 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
2909 ngx_http_upstream_finalize_request(r, u, 0);
3024 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
29103025 }
29113026
29123027 return;
29133028 }
29143029
29153030 if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
2916 ngx_http_upstream_finalize_request(r, u, 0);
3031 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
29173032 return;
29183033 }
29193034
29313046 "http downstream delayed");
29323047
29333048 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
2934 ngx_http_upstream_finalize_request(r, u, 0);
3049 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
29353050 }
29363051
29373052 return;
29383053 }
29393054
29403055 if (ngx_event_pipe(p, 1) == NGX_ABORT) {
2941 ngx_http_upstream_finalize_request(r, u, 0);
3056 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
29423057 return;
29433058 }
29443059 }
29663081
29673082 } else {
29683083 if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
2969 ngx_http_upstream_finalize_request(r, u, 0);
3084 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
29703085 return;
29713086 }
29723087 }
29913106
29923107 if (p->upstream_eof || p->upstream_done) {
29933108
2994 tf = u->pipe->temp_file;
3109 tf = p->temp_file;
29953110
29963111 if (u->headers_in.status_n == NGX_HTTP_OK
3112 && (p->upstream_done || p->length == -1)
29973113 && (u->headers_in.content_length_n == -1
2998 || (u->headers_in.content_length_n == tf->offset)))
3114 || u->headers_in.content_length_n == tf->offset))
29993115 {
30003116 ngx_http_upstream_store(r, u);
30013117 u->store = 0;
30083124 if (u->cacheable) {
30093125
30103126 if (p->upstream_done) {
3011 ngx_http_file_cache_update(r, u->pipe->temp_file);
3127 ngx_http_file_cache_update(r, p->temp_file);
30123128
30133129 } else if (p->upstream_eof) {
30143130
3015 tf = u->pipe->temp_file;
3016
3017 if (u->headers_in.content_length_n == -1
3018 || u->headers_in.content_length_n
3019 == tf->offset - (off_t) r->cache->body_start)
3131 tf = p->temp_file;
3132
3133 if (p->length == -1
3134 && (u->headers_in.content_length_n == -1
3135 || u->headers_in.content_length_n
3136 == tf->offset - (off_t) r->cache->body_start))
30203137 {
30213138 ngx_http_file_cache_update(r, tf);
30223139
30253142 }
30263143
30273144 } else if (p->upstream_error) {
3028 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
3145 ngx_http_file_cache_free(r->cache, p->temp_file);
30293146 }
30303147 }
30313148
30343151 if (p->upstream_done || p->upstream_eof || p->upstream_error) {
30353152 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
30363153 "http upstream exit: %p", p->out);
3037 #if 0
3038 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
3039 #endif
3040 ngx_http_upstream_finalize_request(r, u, 0);
3154
3155 if (p->upstream_done
3156 || (p->upstream_eof && p->length == -1))
3157 {
3158 ngx_http_upstream_finalize_request(r, u, 0);
3159 return;
3160 }
3161
3162 if (p->upstream_eof) {
3163 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
3164 "upstream prematurely closed connection");
3165 }
3166
3167 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
30413168 return;
30423169 }
30433170 }
30473174 "http upstream downstream error");
30483175
30493176 if (!u->cacheable && !u->store && u->peer.connection) {
3050 ngx_http_upstream_finalize_request(r, u, 0);
3177 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
30513178 }
30523179 }
30533180 }
31473274 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
31483275 "http next upstream, %xi", ft_type);
31493276
3150 #if 0
3151 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
3152 #endif
3153
31543277 if (u->peer.sockaddr) {
31553278
3156 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
3279 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403
3280 || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404)
3281 {
31573282 state = NGX_PEER_NEXT;
3283
31583284 } else {
31593285 state = NGX_PEER_FAILED;
31603286 }
31843310
31853311 case NGX_HTTP_UPSTREAM_FT_HTTP_500:
31863312 status = NGX_HTTP_INTERNAL_SERVER_ERROR;
3313 break;
3314
3315 case NGX_HTTP_UPSTREAM_FT_HTTP_403:
3316 status = NGX_HTTP_FORBIDDEN;
31873317 break;
31883318
31893319 case NGX_HTTP_UPSTREAM_FT_HTTP_404:
32573387 u->peer.connection = NULL;
32583388 }
32593389
3260 #if 0
3261 if (u->conf->busy_lock && !u->busy_locked) {
3262 ngx_http_upstream_busy_lock(p);
3263 return;
3264 }
3265 #endif
3266
32673390 ngx_http_upstream_connect(r, u);
32683391 }
32693392
32843407 ngx_http_upstream_finalize_request(ngx_http_request_t *r,
32853408 ngx_http_upstream_t *u, ngx_int_t rc)
32863409 {
3410 ngx_uint_t flush;
32873411 ngx_time_t *tp;
32883412
32893413 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
33903514
33913515 #endif
33923516
3393 if (u->header_sent
3394 && rc != NGX_HTTP_REQUEST_TIME_OUT
3395 && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
3517 if (r->subrequest_in_memory
3518 && u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE)
33963519 {
3397 rc = 0;
3520 u->buffer.last = u->buffer.pos;
33983521 }
33993522
34003523 if (rc == NGX_DECLINED) {
34033526
34043527 r->connection->log->action = "sending to client";
34053528
3406 if (rc == 0
3407 && !r->header_only
3408 #if (NGX_HTTP_CACHE)
3409 && !r->cached
3410 #endif
3411 )
3529 if (!u->header_sent
3530 || rc == NGX_HTTP_REQUEST_TIME_OUT
3531 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST)
34123532 {
3533 ngx_http_finalize_request(r, rc);
3534 return;
3535 }
3536
3537 flush = 0;
3538
3539 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
3540 rc = NGX_ERROR;
3541 flush = 1;
3542 }
3543
3544 if (r->header_only) {
3545 ngx_http_finalize_request(r, rc);
3546 return;
3547 }
3548
3549 if (rc == 0) {
34133550 rc = ngx_http_send_special(r, NGX_HTTP_LAST);
3551
3552 } else if (flush) {
3553 r->keepalive = 0;
3554 rc = ngx_http_send_special(r, NGX_HTTP_FLUSH);
34143555 }
34153556
34163557 ngx_http_finalize_request(r, rc);
35123653 return NGX_OK;
35133654 }
35143655
3515 if (r->cache->valid_sec != 0) {
3656 if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL) {
35163657 return NGX_OK;
35173658 }
35183659
40414182 if (r->cached) {
40424183 r->allow_ranges = 1;
40434184 return NGX_OK;
4044
4185 }
4186
4187 if (r->upstream->cacheable) {
4188 r->allow_ranges = 1;
4189 r->single_range = 1;
4190 return NGX_OK;
40454191 }
40464192
40474193 #endif
42734419 ms = (ngx_msec_int_t)
42744420 (state[i].response_sec * 1000 + state[i].response_msec);
42754421 ms = ngx_max(ms, 0);
4276 p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
4422 p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
42774423
42784424 } else {
42794425 *p++ = '-';
44014547 v->not_found = 0;
44024548 v->len = ngx_http_cache_status[n].len;
44034549 v->data = ngx_http_cache_status[n].data;
4550
4551 return NGX_OK;
4552 }
4553
4554
4555 static ngx_int_t
4556 ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
4557 ngx_http_variable_value_t *v, uintptr_t data)
4558 {
4559 u_char *p;
4560
4561 if (r->upstream == NULL
4562 || !r->upstream->conf->cache_revalidate
4563 || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED
4564 || r->cache->last_modified == -1)
4565 {
4566 v->not_found = 1;
4567 return NGX_OK;
4568 }
4569
4570 p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
4571 if (p == NULL) {
4572 return NGX_ERROR;
4573 }
4574
4575 v->len = ngx_http_time(p, r->cache->last_modified) - p;
4576 v->valid = 1;
4577 v->no_cacheable = 0;
4578 v->not_found = 0;
4579 v->data = p;
44044580
44054581 return NGX_OK;
44064582 }
46144790 continue;
46154791 }
46164792
4617 if (ngx_strncmp(value[i].data, "backup", 6) == 0) {
4793 if (ngx_strcmp(value[i].data, "backup") == 0) {
46184794
46194795 if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) {
46204796 goto invalid;
46254801 continue;
46264802 }
46274803
4628 if (ngx_strncmp(value[i].data, "down", 4) == 0) {
4804 if (ngx_strcmp(value[i].data, "down") == 0) {
46294805
46304806 if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
46314807 goto invalid;
2323 #define NGX_HTTP_UPSTREAM_FT_HTTP_502 0x00000020
2424 #define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000040
2525 #define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080
26 #define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000100
27 #define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000200
28 #define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000400
29 #define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00000800
26 #define NGX_HTTP_UPSTREAM_FT_HTTP_403 0x00000100
27 #define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000200
28 #define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000400
29 #define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000800
30 #define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00001000
3031 #define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000
3132 #define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000
3233
3435 |NGX_HTTP_UPSTREAM_FT_HTTP_502 \
3536 |NGX_HTTP_UPSTREAM_FT_HTTP_503 \
3637 |NGX_HTTP_UPSTREAM_FT_HTTP_504 \
38 |NGX_HTTP_UPSTREAM_FT_HTTP_403 \
3739 |NGX_HTTP_UPSTREAM_FT_HTTP_404)
3840
3941 #define NGX_HTTP_UPSTREAM_INVALID_HEADER 40
175177 ngx_flag_t cache_lock;
176178 ngx_msec_t cache_lock_timeout;
177179
180 ngx_flag_t cache_revalidate;
181
178182 ngx_array_t *cache_valid;
179183 ngx_array_t *cache_bypass;
180184 ngx_array_t *no_cache;
251255 ngx_uint_t no_port; /* unsigned no_port:1 */
252256
253257 ngx_uint_t naddrs;
254 in_addr_t *addrs;
258 ngx_addr_t *addrs;
255259
256260 struct sockaddr *sockaddr;
257261 socklen_t socklen;
7070 n = 0;
7171
7272 for (i = 0; i < us->servers->nelts; i++) {
73 if (server[i].backup) {
74 continue;
75 }
76
7377 for (j = 0; j < server[i].naddrs; j++) {
74 if (server[i].backup) {
75 continue;
76 }
77
7878 peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
7979 peers->peer[n].socklen = server[i].addrs[j].socklen;
8080 peers->peer[n].name = server[i].addrs[j].name;
81 peers->peer[n].weight = server[i].weight;
82 peers->peer[n].effective_weight = server[i].weight;
83 peers->peer[n].current_weight = 0;
8184 peers->peer[n].max_fails = server[i].max_fails;
8285 peers->peer[n].fail_timeout = server[i].fail_timeout;
8386 peers->peer[n].down = server[i].down;
84 peers->peer[n].weight = server[i].weight;
85 peers->peer[n].effective_weight = server[i].weight;
86 peers->peer[n].current_weight = 0;
8787 n++;
8888 }
8989 }
124124 n = 0;
125125
126126 for (i = 0; i < us->servers->nelts; i++) {
127 if (!server[i].backup) {
128 continue;
129 }
130
127131 for (j = 0; j < server[i].naddrs; j++) {
128 if (!server[i].backup) {
129 continue;
130 }
131
132132 backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
133133 backup->peer[n].socklen = server[i].addrs[j].socklen;
134134 backup->peer[n].name = server[i].addrs[j].name;
265265 {
266266 u_char *p;
267267 size_t len;
268 socklen_t socklen;
268269 ngx_uint_t i, n;
269 struct sockaddr_in *sin;
270 struct sockaddr *sockaddr;
270271 ngx_http_upstream_rr_peers_t *peers;
271272 ngx_http_upstream_rr_peer_data_t *rrp;
272273
305306
306307 for (i = 0; i < ur->naddrs; i++) {
307308
308 len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
309
310 p = ngx_pnalloc(r->pool, len);
309 socklen = ur->addrs[i].socklen;
310
311 sockaddr = ngx_palloc(r->pool, socklen);
312 if (sockaddr == NULL) {
313 return NGX_ERROR;
314 }
315
316 ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen);
317
318 switch (sockaddr->sa_family) {
319 #if (NGX_HAVE_INET6)
320 case AF_INET6:
321 ((struct sockaddr_in6 *) sockaddr)->sin6_port = htons(ur->port);
322 break;
323 #endif
324 default: /* AF_INET */
325 ((struct sockaddr_in *) sockaddr)->sin_port = htons(ur->port);
326 }
327
328 p = ngx_pnalloc(r->pool, NGX_SOCKADDR_STRLEN);
311329 if (p == NULL) {
312330 return NGX_ERROR;
313331 }
314332
315 len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN);
316 len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
317
318 sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
319 if (sin == NULL) {
320 return NGX_ERROR;
321 }
322
323 sin->sin_family = AF_INET;
324 sin->sin_port = htons(ur->port);
325 sin->sin_addr.s_addr = ur->addrs[i];
326
327 peers->peer[i].sockaddr = (struct sockaddr *) sin;
328 peers->peer[i].socklen = sizeof(struct sockaddr_in);
333 len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
334
335 peers->peer[i].sockaddr = sockaddr;
336 peers->peer[i].socklen = socklen;
329337 peers->peer[i].name.len = len;
330338 peers->peer[i].name.data = p;
331339 peers->peer[i].weight = 1;
5252 static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
5353 ngx_http_variable_value_t *v, uintptr_t data);
5454 static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
55 ngx_http_variable_value_t *v, uintptr_t data);
56 static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
5557 ngx_http_variable_value_t *v, uintptr_t data);
5658 static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
5759 ngx_http_variable_value_t *v, uintptr_t data);
182184
183185 { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
184186
187 { ngx_string("proxy_protocol_addr"), NULL,
188 ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
189
185190 { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
186191
187192 { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
486491
487492 if (cmcf->variables.nelts <= index) {
488493 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
489 "unknown variable index: %d", index);
494 "unknown variable index: %ui", index);
490495 return NULL;
491496 }
492497
11841189 break;
11851190 #endif
11861191
1192 #if (NGX_HAVE_UNIX_DOMAIN)
1193 case AF_UNIX:
1194 port = 0;
1195 break;
1196 #endif
1197
11871198 default: /* AF_INET */
11881199 sin = (struct sockaddr_in *) r->connection->sockaddr;
11891200 port = ntohs(sin->sin_port);
11931204 if (port > 0 && port < 65536) {
11941205 v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
11951206 }
1207
1208 return NGX_OK;
1209 }
1210
1211
1212 static ngx_int_t
1213 ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
1214 ngx_http_variable_value_t *v, uintptr_t data)
1215 {
1216 v->len = r->connection->proxy_protocol_addr.len;
1217 v->valid = 1;
1218 v->no_cacheable = 0;
1219 v->not_found = 0;
1220 v->data = r->connection->proxy_protocol_addr.data;
11961221
11971222 return NGX_OK;
11981223 }
12621287 break;
12631288 #endif
12641289
1290 #if (NGX_HAVE_UNIX_DOMAIN)
1291 case AF_UNIX:
1292 port = 0;
1293 break;
1294 #endif
1295
12651296 default: /* AF_INET */
12661297 sin = (struct sockaddr_in *) r->connection->local_sockaddr;
12671298 port = ntohs(sin->sin_port);
13731404 return NGX_ERROR;
13741405 }
13751406
1376 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
1407 if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
1408 != NGX_OK)
1409 {
13771410 return NGX_ERROR;
13781411 }
13791412
14151448
14161449 path.data[path.len - 1] = '\0';
14171450
1418 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
1451 if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
1452 != NGX_OK)
1453 {
14191454 return NGX_ERROR;
14201455 }
14211456 }
17391774 }
17401775
17411776 if (r->headers_out.last_modified_time >= 0) {
1742 p = ngx_pnalloc(r->pool,
1743 sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
1777 p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
17441778 if (p == NULL) {
17451779 return NGX_ERROR;
17461780 }
22562290
22572291 re->regex = rc->regex;
22582292 re->ncaptures = rc->captures;
2293 re->name = rc->pattern;
22592294
22602295 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
22612296 cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
22732308
22742309 re->variables = rv;
22752310 re->nvariables = n;
2276 re->name = rc->pattern;
22772311
22782312 size = rc->name_size;
22792313 p = rc->names;
183183 return NGX_AGAIN;
184184 }
185185
186 if (size == 0 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)) {
186 if (size == 0
187 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
188 && !(last && c->need_last_buf))
189 {
187190 if (last || flush) {
188191 for (cl = r->out; cl; /* void */) {
189192 ln = cl;
206209 }
207210
208211 if (r->limit_rate) {
212 if (r->limit_rate_after == 0) {
213 r->limit_rate_after = clcf->limit_rate_after;
214 }
215
209216 limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1)
210 - (c->sent - clcf->limit_rate_after);
217 - (c->sent - r->limit_rate_after);
211218
212219 if (limit <= 0) {
213220 c->write->delayed = 1;
248255
249256 nsent = c->sent;
250257
251 if (clcf->limit_rate_after) {
252
253 sent -= clcf->limit_rate_after;
258 if (r->limit_rate_after) {
259
260 sent -= r->limit_rate_after;
254261 if (sent < 0) {
255262 sent = 0;
256263 }
257264
258 nsent -= clcf->limit_rate_after;
265 nsent -= r->limit_rate_after;
259266 if (nsent < 0) {
260267 nsent = 0;
261268 }
464464 addrs[i].conf.ssl = addr[i].ssl;
465465 #endif
466466
467 len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
467 len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf,
468 NGX_SOCKADDR_STRLEN, 1);
468469
469470 p = ngx_pnalloc(cf->pool, len);
470471 if (p == NULL) {
512513 addrs6[i].conf.ssl = addr[i].ssl;
513514 #endif
514515
515 len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
516 len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf,
517 NGX_SOCKADDR_STRLEN, 1);
516518
517519 p = ngx_pnalloc(cf->pool, len);
518520 if (p == NULL) {
233233 ngx_str_t smtp_from;
234234 ngx_str_t smtp_to;
235235
236 ngx_str_t cmd;
237
236238 ngx_uint_t command;
237239 ngx_array_t args;
238240
698698
699699 p = ngx_pnalloc(s->connection->pool, ctx->err.len);
700700 if (p == NULL) {
701 ngx_close_connection(ctx->peer.connection);
702701 ngx_destroy_pool(ctx->pool);
703702 ngx_mail_session_internal_server_error(s);
704703 return;
438438 ls->bind = 1;
439439
440440 } else {
441 len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1);
441 len = ngx_sock_ntop(sa, ls->socklen, buf,
442 NGX_SOCKADDR_STRLEN, 1);
442443
443444 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
444445 "ipv6only is not supported "
126126 c->data = s;
127127 s->connection = c;
128128
129 ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V",
129 ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %V connected to %V",
130130 c->number, &c->addr_text, s->addr_text);
131131
132132 ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t));
558558 n = c->send(c, s->out.data, s->out.len);
559559
560560 if (n > 0) {
561 s->out.data += n;
561562 s->out.len -= n;
563
564 if (s->out.len != 0) {
565 goto again;
566 }
562567
563568 if (wev->timer_set) {
564569 ngx_del_timer(wev);
582587 }
583588
584589 /* n == NGX_AGAIN */
590
591 again:
585592
586593 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
587594
619626 return NGX_ERROR;
620627 }
621628
622 return NGX_AGAIN;
629 if (s->buffer->pos == s->buffer->last) {
630 return NGX_AGAIN;
631 }
623632 }
624633
625634 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
660669 ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c)
661670 {
662671 s->args.nelts = 0;
663 s->buffer->pos = s->buffer->start;
664 s->buffer->last = s->buffer->start;
672
673 if (s->buffer->pos == s->buffer->last) {
674 s->buffer->pos = s->buffer->start;
675 s->buffer->last = s->buffer->start;
676 }
677
665678 s->state = 0;
666679
667680 if (c->read->timer_set) {
625625 ngx_str_t *arg;
626626 enum {
627627 sw_start = 0,
628 sw_command,
629 sw_invalid,
628630 sw_spaces_before_argument,
629631 sw_argument,
630632 sw_almost_done
639641
640642 /* SMTP command */
641643 case sw_start:
644 s->cmd_start = p;
645 state = sw_command;
646
647 /* fall through */
648
649 case sw_command:
642650 if (ch == ' ' || ch == CR || ch == LF) {
643 c = s->buffer->start;
651 c = s->cmd_start;
644652
645653 if (p - c == 4) {
646654
718726 goto invalid;
719727 }
720728
729 s->cmd.data = s->cmd_start;
730 s->cmd.len = p - s->cmd_start;
731
721732 switch (ch) {
722733 case ' ':
723734 state = sw_spaces_before_argument;
736747 }
737748
738749 break;
750
751 case sw_invalid:
752 goto invalid;
739753
740754 case sw_spaces_before_argument:
741755 switch (ch) {
823837
824838 invalid:
825839
826 s->state = sw_start;
840 s->state = sw_invalid;
827841 s->arg_start = NULL;
842
843 /* skip invalid command till LF */
844
845 for (p = s->buffer->pos; p < s->buffer->last; p++) {
846 if (*p == LF) {
847 s->state = sw_start;
848 p++;
849 break;
850 }
851 }
852
853 s->buffer->pos = p;
828854
829855 return NGX_MAIL_PARSE_INVALID_COMMAND;
830856 }
841867 }
842868 #endif
843869
870 if (s->args.nelts == 0) {
871 return NGX_MAIL_PARSE_INVALID_COMMAND;
872 }
873
844874 arg = s->args.elts;
845875
846876 if (arg[0].len == 5) {
541541 CRLF) - 1
542542 + s->connection->addr_text.len + s->login.len + s->host.len;
543543
544 #if (NGX_HAVE_INET6)
545 if (s->connection->sockaddr->sa_family == AF_INET6) {
546 line.len += sizeof("IPV6:") - 1;
547 }
548 #endif
549
544550 line.data = ngx_pnalloc(c->pool, line.len);
545551 if (line.data == NULL) {
546552 ngx_mail_proxy_internal_server_error(s);
547553 return;
548554 }
549555
550 line.len = ngx_sprintf(line.data,
551 "XCLIENT ADDR=%V%s%V NAME=%V" CRLF,
552 &s->connection->addr_text,
553 (s->login.len ? " LOGIN=" : ""), &s->login, &s->host)
554 - line.data;
556 p = ngx_cpymem(line.data, "XCLIENT ADDR=", sizeof("XCLIENT ADDR=") - 1);
557
558 #if (NGX_HAVE_INET6)
559 if (s->connection->sockaddr->sa_family == AF_INET6) {
560 p = ngx_cpymem(p, "IPV6:", sizeof("IPV6:") - 1);
561 }
562 #endif
563
564 p = ngx_copy(p, s->connection->addr_text.data,
565 s->connection->addr_text.len);
566
567 if (s->login.len) {
568 p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1);
569 p = ngx_copy(p, s->login.data, s->login.len);
570 }
571
572 p = ngx_cpymem(p, " NAME=", sizeof(" NAME=") - 1);
573 p = ngx_copy(p, s->host.data, s->host.len);
574
575 *p++ = CR; *p++ = LF;
576
577 line.len = p - line.data;
555578
556579 if (s->smtp_helo.len) {
557580 s->mail_state = ngx_smtp_xclient_helo;
656679 c->log->action = NULL;
657680 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
658681
659 ngx_mail_proxy_handler(s->connection->write);
682 if (s->buffer->pos == s->buffer->last) {
683 ngx_mail_proxy_handler(s->connection->write);
684
685 } else {
686 ngx_mail_proxy_handler(c->write);
687 }
660688
661689 return;
662690
701729 static ngx_int_t
702730 ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state)
703731 {
704 u_char *p;
732 u_char *p, *m;
705733 ssize_t n;
706734 ngx_buf_t *b;
707735 ngx_mail_proxy_conf_t *pcf;
778806 break;
779807
780808 default: /* NGX_MAIL_SMTP_PROTOCOL */
809
810 if (p[3] == '-') {
811 /* multiline reply, check if we got last line */
812
813 m = b->last - (sizeof(CRLF "200" CRLF) - 1);
814
815 while (m > p) {
816 if (m[0] == CR && m[1] == LF) {
817 break;
818 }
819
820 m--;
821 }
822
823 if (m <= p || m[5] == '-') {
824 return NGX_AGAIN;
825 }
826 }
827
781828 switch (state) {
782829
783830 case ngx_smtp_start:
5454 void
5555 ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
5656 {
57 struct sockaddr_in *sin;
5857 ngx_resolver_ctx_t *ctx;
5958 ngx_mail_core_srv_conf_t *cscf;
6059
6665 return;
6766 }
6867
69 if (c->sockaddr->sa_family != AF_INET) {
68 #if (NGX_HAVE_UNIX_DOMAIN)
69 if (c->sockaddr->sa_family == AF_UNIX) {
7070 s->host = smtp_tempunavail;
7171 ngx_mail_smtp_greeting(s, c);
7272 return;
7373 }
74 #endif
7475
7576 c->log->action = "in resolving client address";
7677
8081 return;
8182 }
8283
83 /* AF_INET only */
84
85 sin = (struct sockaddr_in *) c->sockaddr;
86
87 ctx->addr = sin->sin_addr.s_addr;
84 ctx->addr.sockaddr = c->sockaddr;
85 ctx->addr.socklen = c->socklen;
8886 ctx->handler = ngx_mail_smtp_resolve_addr_handler;
8987 ctx->data = s;
9088 ctx->timeout = cscf->resolver_timeout;
166164 }
167165
168166 ctx->name = s->host;
169 ctx->type = NGX_RESOLVE_A;
170167 ctx->handler = ngx_mail_smtp_resolve_name_handler;
171168 ctx->data = s;
172169 ctx->timeout = cscf->resolver_timeout;
180177 static void
181178 ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
182179 {
183 in_addr_t addr;
184180 ngx_uint_t i;
185181 ngx_connection_t *c;
186 struct sockaddr_in *sin;
187182 ngx_mail_session_t *s;
188183
189184 s = ctx->data;
204199
205200 } else {
206201
207 /* AF_INET only */
208
209 sin = (struct sockaddr_in *) c->sockaddr;
202 #if (NGX_DEBUG)
203 {
204 u_char text[NGX_SOCKADDR_STRLEN];
205 ngx_str_t addr;
206
207 addr.data = text;
210208
211209 for (i = 0; i < ctx->naddrs; i++) {
212
213 addr = ctx->addrs[i];
214
215 ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
216 "name was resolved to %ud.%ud.%ud.%ud",
217 (ntohl(addr) >> 24) & 0xff,
218 (ntohl(addr) >> 16) & 0xff,
219 (ntohl(addr) >> 8) & 0xff,
220 ntohl(addr) & 0xff);
221
222 if (addr == sin->sin_addr.s_addr) {
210 addr.len = ngx_sock_ntop(ctx->addrs[i].sockaddr,
211 ctx->addrs[i].socklen,
212 text, NGX_SOCKADDR_STRLEN, 0);
213
214 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
215 "name was resolved to %V", &addr);
216 }
217 }
218 #endif
219
220 for (i = 0; i < ctx->naddrs; i++) {
221 if (ngx_cmp_sockaddr(ctx->addrs[i].sockaddr, ctx->addrs[i].socklen,
222 c->sockaddr, c->socklen, 0)
223 == NGX_OK)
224 {
223225 goto found;
224226 }
225227 }
320322 }
321323
322324 ngx_str_set(&s->out, smtp_invalid_pipelining);
325 s->quit = 1;
323326 }
324327
325328 ngx_mail_send(c->write);
484487 }
485488 }
486489
490 if (s->buffer->pos < s->buffer->last) {
491 s->blocked = 1;
492 }
493
487494 switch (rc) {
488495
489496 case NGX_DONE:
503510
504511 case NGX_OK:
505512 s->args.nelts = 0;
506 s->buffer->pos = s->buffer->start;
507 s->buffer->last = s->buffer->start;
513
514 if (s->buffer->pos == s->buffer->last) {
515 s->buffer->pos = s->buffer->start;
516 s->buffer->last = s->buffer->start;
517 }
508518
509519 if (s->state) {
510 s->arg_start = s->buffer->start;
520 s->arg_start = s->buffer->pos;
511521 }
512522
513523 ngx_mail_send(c->write);
650660 static ngx_int_t
651661 ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
652662 {
653 u_char ch;
654 ngx_str_t l;
655 ngx_uint_t i;
663 ngx_str_t *arg, cmd;
656664 ngx_mail_smtp_srv_conf_t *sscf;
657665
658666 sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
670678 return NGX_OK;
671679 }
672680
673 l.len = s->buffer->last - s->buffer->start;
674 l.data = s->buffer->start;
675
676 for (i = 0; i < l.len; i++) {
677 ch = l.data[i];
678
679 if (ch != CR && ch != LF) {
680 continue;
681 }
682
683 l.data[i] = ' ';
684 }
685
686 while (i) {
687 if (l.data[i - 1] != ' ') {
688 break;
689 }
690
691 i--;
692 }
693
694 l.len = i;
695
696 s->smtp_from.len = l.len;
697
698 s->smtp_from.data = ngx_pnalloc(c->pool, l.len);
681 arg = s->args.elts;
682 arg += s->args.nelts - 1;
683
684 cmd.len = arg->data + arg->len - s->cmd.data;
685 cmd.data = s->cmd.data;
686
687 s->smtp_from.len = cmd.len;
688
689 s->smtp_from.data = ngx_pnalloc(c->pool, cmd.len);
699690 if (s->smtp_from.data == NULL) {
700691 return NGX_ERROR;
701692 }
702693
703 ngx_memcpy(s->smtp_from.data, l.data, l.len);
694 ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len);
704695
705696 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
706697 "smtp mail from:\"%V\"", &s->smtp_from);
714705 static ngx_int_t
715706 ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c)
716707 {
717 u_char ch;
718 ngx_str_t l;
719 ngx_uint_t i;
708 ngx_str_t *arg, cmd;
720709
721710 if (s->smtp_from.len == 0) {
722711 ngx_str_set(&s->out, smtp_bad_sequence);
723712 return NGX_OK;
724713 }
725714
726 l.len = s->buffer->last - s->buffer->start;
727 l.data = s->buffer->start;
728
729 for (i = 0; i < l.len; i++) {
730 ch = l.data[i];
731
732 if (ch != CR && ch != LF) {
733 continue;
734 }
735
736 l.data[i] = ' ';
737 }
738
739 while (i) {
740 if (l.data[i - 1] != ' ') {
741 break;
742 }
743
744 i--;
745 }
746
747 l.len = i;
748
749 s->smtp_to.len = l.len;
750
751 s->smtp_to.data = ngx_pnalloc(c->pool, l.len);
715 arg = s->args.elts;
716 arg += s->args.nelts - 1;
717
718 cmd.len = arg->data + arg->len - s->cmd.data;
719 cmd.data = s->cmd.data;
720
721 s->smtp_to.len = cmd.len;
722
723 s->smtp_to.data = ngx_pnalloc(c->pool, cmd.len);
752724 if (s->smtp_to.data == NULL) {
753725 return NGX_ERROR;
754726 }
755727
756 ngx_memcpy(s->smtp_to.data, l.data, l.len);
728 ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len);
757729
758730 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
759731 "smtp rcpt to:\"%V\"", &s->smtp_to);
2424 void *conf);
2525
2626
27 static ngx_conf_enum_t ngx_http_starttls_state[] = {
27 static ngx_conf_enum_t ngx_mail_starttls_state[] = {
2828 { ngx_string("off"), NGX_MAIL_STARTTLS_OFF },
2929 { ngx_string("on"), NGX_MAIL_STARTTLS_ON },
3030 { ngx_string("only"), NGX_MAIL_STARTTLS_ONLY },
5757 ngx_mail_ssl_starttls,
5858 NGX_MAIL_SRV_CONF_OFFSET,
5959 offsetof(ngx_mail_ssl_conf_t, starttls),
60 ngx_http_starttls_state },
60 ngx_mail_starttls_state },
6161
6262 { ngx_string("ssl_certificate"),
6363 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
113113 ngx_mail_ssl_session_cache,
114114 NGX_MAIL_SRV_CONF_OFFSET,
115115 0,
116 NULL },
117
118 { ngx_string("ssl_session_tickets"),
119 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
120 ngx_conf_set_flag_slot,
121 NGX_MAIL_SRV_CONF_OFFSET,
122 offsetof(ngx_mail_ssl_conf_t, session_tickets),
123 NULL },
124
125 { ngx_string("ssl_session_ticket_key"),
126 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
127 ngx_conf_set_str_array_slot,
128 NGX_MAIL_SRV_CONF_OFFSET,
129 offsetof(ngx_mail_ssl_conf_t, session_ticket_keys),
116130 NULL },
117131
118132 { ngx_string("ssl_session_timeout"),
183197 scf->prefer_server_ciphers = NGX_CONF_UNSET;
184198 scf->builtin_session_cache = NGX_CONF_UNSET;
185199 scf->session_timeout = NGX_CONF_UNSET;
200 scf->session_tickets = NGX_CONF_UNSET;
201 scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
186202
187203 return scf;
188204 }
291307 return NGX_CONF_ERROR;
292308 }
293309
294 if (conf->ciphers.len) {
295 if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
296 (const char *) conf->ciphers.data)
297 == 0)
298 {
299 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
300 "SSL_CTX_set_cipher_list(\"%V\") failed",
301 &conf->ciphers);
302 }
310 if (SSL_CTX_set_cipher_list(conf->ssl.ctx,
311 (const char *) conf->ciphers.data)
312 == 0)
313 {
314 ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
315 "SSL_CTX_set_cipher_list(\"%V\") failed",
316 &conf->ciphers);
317 return NGX_CONF_ERROR;
303318 }
304319
305320 if (conf->prefer_server_ciphers) {
309324 SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback);
310325
311326 if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
327 return NGX_CONF_ERROR;
328 }
329
330 if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
312331 return NGX_CONF_ERROR;
313332 }
314333
322341 if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx,
323342 conf->builtin_session_cache,
324343 conf->shm_zone, conf->session_timeout)
344 != NGX_OK)
345 {
346 return NGX_CONF_ERROR;
347 }
348
349 ngx_conf_merge_value(conf->session_tickets,
350 prev->session_tickets, 1);
351
352 #ifdef SSL_OP_NO_TICKET
353 if (!conf->session_tickets) {
354 SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
355 }
356 #endif
357
358 ngx_conf_merge_ptr_value(conf->session_ticket_keys,
359 prev->session_ticket_keys, NULL);
360
361 if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
325362 != NGX_OK)
326363 {
327364 return NGX_CONF_ERROR;
4040
4141 ngx_shm_zone_t *shm_zone;
4242
43 ngx_flag_t session_tickets;
44 ngx_array_t *session_ticket_keys;
45
4346 u_char *file;
4447 ngx_uint_t line;
4548 } ngx_mail_ssl_conf_t;
3232 } else {
3333 msg.msg_control = (caddr_t) &cmsg;
3434 msg.msg_controllen = sizeof(cmsg);
35
36 ngx_memzero(&cmsg, sizeof(cmsg));
3537
3638 cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
3739 cmsg.cm.cmsg_level = SOL_SOCKET;
141143
142144 if ((size_t) n < sizeof(ngx_channel_t)) {
143145 ngx_log_error(NGX_LOG_ALERT, log, 0,
144 "recvmsg() returned not enough data: %uz", n);
146 "recvmsg() returned not enough data: %z", n);
145147 return NGX_ERROR;
146148 }
147149
1919 #include <stddef.h> /* offsetof() */
2020 #include <stdio.h>
2121 #include <stdlib.h>
22 #include <ctype.h>
2223 #include <errno.h>
2324 #include <string.h>
2425 #include <signal.h>
5858
5959
6060 void
61 ngx_debug_init()
61 ngx_debug_init(void)
6262 {
6363 #if (NGX_DEBUG_MALLOC)
6464
316316
317317 c->sent += sent;
318318
319 for (cl = in; cl; cl = cl->next) {
320
321 if (ngx_buf_special(cl->buf)) {
319 for ( /* void */ ; in; in = in->next) {
320
321 if (ngx_buf_special(in->buf)) {
322322 continue;
323323 }
324324
326326 break;
327327 }
328328
329 size = ngx_buf_size(cl->buf);
329 size = ngx_buf_size(in->buf);
330330
331331 if (sent >= size) {
332332 sent -= size;
333333
334 if (ngx_buf_in_memory(cl->buf)) {
335 cl->buf->pos = cl->buf->last;
336 }
337
338 if (cl->buf->in_file) {
339 cl->buf->file_pos = cl->buf->file_last;
334 if (ngx_buf_in_memory(in->buf)) {
335 in->buf->pos = in->buf->last;
336 }
337
338 if (in->buf->in_file) {
339 in->buf->file_pos = in->buf->file_last;
340340 }
341341
342342 continue;
343343 }
344344
345 if (ngx_buf_in_memory(cl->buf)) {
346 cl->buf->pos += (size_t) sent;
347 }
348
349 if (cl->buf->in_file) {
350 cl->buf->file_pos += sent;
345 if (ngx_buf_in_memory(in->buf)) {
346 in->buf->pos += (size_t) sent;
347 }
348
349 if (in->buf->in_file) {
350 in->buf->file_pos += sent;
351351 }
352352
353353 break;
359359
360360 if (!complete) {
361361 wev->ready = 0;
362 return cl;
363 }
364
365 if (send >= limit || cl == NULL) {
366 return cl;
367 }
368
369 in = cl;
362 return in;
363 }
364
365 if (send >= limit || in == NULL) {
366 return in;
367 }
370368 }
371369 }
3333 #define NGX_ENOSPC ENOSPC
3434 #define NGX_EPIPE EPIPE
3535 #define NGX_EINPROGRESS EINPROGRESS
36 #define NGX_ENOPROTOOPT ENOPROTOOPT
37 #define NGX_EOPNOTSUPP EOPNOTSUPP
3638 #define NGX_EADDRINUSE EADDRINUSE
3739 #define NGX_ECONNABORTED ECONNABORTED
3840 #define NGX_ECONNRESET ECONNRESET
4951 #define NGX_EILSEQ EILSEQ
5052 #define NGX_ENOMOREFILES 0
5153 #define NGX_ELOOP ELOOP
54 #define NGX_EBADF EBADF
5255
5356 #if (NGX_HAVE_OPENAT)
5457 #define NGX_EMLINK EMLINK
5252
5353 #ifdef __CYGWIN__
5454
55 #ifndef NGX_HAVE_CASELESS_FILESYSTEM
5556 #define NGX_HAVE_CASELESS_FILESYSTEM 1
57 #endif
5658
5759 #define ngx_open_file(name, mode, create, access) \
5860 open((const char *) name, mode|create|O_BINARY, access)
7173 #define NGX_FILE_RDWR O_RDWR
7274 #define NGX_FILE_CREATE_OR_OPEN O_CREAT
7375 #define NGX_FILE_OPEN 0
74 #define NGX_FILE_TRUNCATE O_CREAT|O_TRUNC
75 #define NGX_FILE_APPEND O_WRONLY|O_APPEND
76 #define NGX_FILE_TRUNCATE (O_CREAT|O_TRUNC)
77 #define NGX_FILE_APPEND (O_WRONLY|O_APPEND)
7678 #define NGX_FILE_NONBLOCK O_NONBLOCK
7779
7880 #if (NGX_HAVE_OPENAT)
8587 #endif
8688
8789 #if defined(O_SEARCH)
88 #define NGX_FILE_SEARCH O_SEARCH|NGX_FILE_DIRECTORY
90 #define NGX_FILE_SEARCH (O_SEARCH|NGX_FILE_DIRECTORY)
8991
9092 #elif defined(O_EXEC)
91 #define NGX_FILE_SEARCH O_EXEC|NGX_FILE_DIRECTORY
92
93 #else
94 #define NGX_FILE_SEARCH O_RDONLY|NGX_FILE_DIRECTORY
93 #define NGX_FILE_SEARCH (O_EXEC|NGX_FILE_DIRECTORY)
94
95 #elif (NGX_HAVE_O_PATH)
96 #define NGX_FILE_SEARCH (O_PATH|O_RDONLY|NGX_FILE_DIRECTORY)
97
98 #else
99 #define NGX_FILE_SEARCH (O_RDONLY|NGX_FILE_DIRECTORY)
95100 #endif
96101
97102 #endif /* NGX_HAVE_OPENAT */
188193 void ngx_close_file_mapping(ngx_file_mapping_t *fm);
189194
190195
191 #if (NGX_HAVE_CASELESS_FILESYSTEM)
192
193 #define ngx_filename_cmp(s1, s2, n) strncasecmp((char *) s1, (char *) s2, n)
194
195 #else
196
197 #define ngx_filename_cmp ngx_memcmp
198
199 #endif
200
201
202196 #define ngx_realpath(p, r) (u_char *) realpath((char *) p, (char *) r)
203197 #define ngx_realpath_n "realpath()"
204198 #define ngx_getcwd(buf, size) (getcwd((char *) buf, size) != NULL)
1515 #include <stddef.h> /* offsetof() */
1616 #include <stdio.h>
1717 #include <stdlib.h>
18 #include <ctype.h>
1819 #include <errno.h>
1920 #include <string.h>
2021 #include <signal.h>
9394 #define NGX_LISTEN_BACKLOG -1
9495
9596
97 #ifdef __DragonFly__
98 #define NGX_KEEPALIVE_FACTOR 1000
99 #endif
100
101
96102 #if (__FreeBSD_version < 430000 || __FreeBSD_version < 500012)
97103
98104 pid_t rfork_thread(int flags, void *stack, int (*func)(void *arg), void *arg);
7171
7272
7373 void
74 ngx_debug_init()
74 ngx_debug_init(void)
7575 {
7676 #if (NGX_DEBUG_MALLOC)
7777
270270
271271
272272 ngx_tid_t
273 ngx_thread_self()
273 ngx_thread_self(void)
274274 {
275275 ngx_int_t tid;
276276
5656
5757
5858 static ngx_inline ngx_int_t
59 ngx_gettid()
59 ngx_gettid(void)
6060 {
6161 char *sp;
6262
8282 }
8383
8484
85 ngx_tid_t ngx_thread_self();
85 ngx_tid_t ngx_thread_self(void);
8686
8787
8888 typedef ngx_uint_t ngx_tls_key_t;
230230 && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET)
231231 {
232232 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
233 err = ngx_errno;
233 err = ngx_socket_errno;
234234
235235 /*
236236 * there is a tiny chance to be interrupted, however,
367367
368368 c->sent += sent;
369369
370 for (cl = in; cl; cl = cl->next) {
371
372 if (ngx_buf_special(cl->buf)) {
370 for ( /* void */ ; in; in = in->next) {
371
372 if (ngx_buf_special(in->buf)) {
373373 continue;
374374 }
375375
377377 break;
378378 }
379379
380 size = ngx_buf_size(cl->buf);
380 size = ngx_buf_size(in->buf);
381381
382382 if (sent >= size) {
383383 sent -= size;
384384
385 if (ngx_buf_in_memory(cl->buf)) {
386 cl->buf->pos = cl->buf->last;
387 }
388
389 if (cl->buf->in_file) {
390 cl->buf->file_pos = cl->buf->file_last;
385 if (ngx_buf_in_memory(in->buf)) {
386 in->buf->pos = in->buf->last;
387 }
388
389 if (in->buf->in_file) {
390 in->buf->file_pos = in->buf->file_last;
391391 }
392392
393393 continue;
394394 }
395395
396 if (ngx_buf_in_memory(cl->buf)) {
397 cl->buf->pos += (size_t) sent;
398 }
399
400 if (cl->buf->in_file) {
401 cl->buf->file_pos += sent;
396 if (ngx_buf_in_memory(in->buf)) {
397 in->buf->pos += (size_t) sent;
398 }
399
400 if (in->buf->in_file) {
401 in->buf->file_pos += sent;
402402 }
403403
404404 break;
406406
407407 #if (NGX_HAVE_AIO_SENDFILE)
408408 if (c->busy_sendfile) {
409 return cl;
409 return in;
410410 }
411411 #endif
412412
420420 */
421421
422422 wev->ready = 0;
423 return cl;
423 return in;
424424 }
425425
426426 if (eintr) {
429429
430430 if (!complete) {
431431 wev->ready = 0;
432 return cl;
433 }
434
435 if (send >= limit || cl == NULL) {
436 return cl;
437 }
438
439 in = cl;
432 return in;
433 }
434
435 if (send >= limit || in == NULL) {
436 return in;
437 }
440438 }
441439 }
2121 #include <stddef.h> /* offsetof() */
2222 #include <stdio.h>
2323 #include <stdlib.h>
24 #include <ctype.h>
2425 #include <errno.h>
2526 #include <string.h>
2627 #include <signal.h>
5051 #include <malloc.h> /* memalign() */
5152 #include <limits.h> /* IOV_MAX */
5253 #include <sys/ioctl.h>
53 #include <sys/sysctl.h>
5454 #include <crypt.h>
5555 #include <sys/utsname.h> /* uname() */
5656
7676 #endif
7777
7878
79 #if (NGX_HAVE_POLL || NGX_HAVE_RTSIG)
79 #if (NGX_HAVE_POLL)
8080 #include <poll.h>
81 #endif
82
83
84 #if (NGX_HAVE_RTSIG)
85 #include <poll.h>
86 #include <sys/sysctl.h>
8187 #endif
8288
8389
2323 * so we limit it to 2G-1 bytes.
2424 */
2525
26 #define NGX_SENDFILE_LIMIT 2147483647L
26 #define NGX_SENDFILE_MAXSIZE 2147483647L
2727
2828
2929 #if (IOV_MAX > 64)
6262
6363 /* the maximum limit size is 2G-1 - the page size */
6464
65 if (limit == 0 || limit > (off_t) (NGX_SENDFILE_LIMIT - ngx_pagesize)) {
66 limit = NGX_SENDFILE_LIMIT - ngx_pagesize;
65 if (limit == 0 || limit > (off_t) (NGX_SENDFILE_MAXSIZE - ngx_pagesize)) {
66 limit = NGX_SENDFILE_MAXSIZE - ngx_pagesize;
6767 }
6868
6969
162162 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
163163 (const void *) &tcp_nodelay, sizeof(int)) == -1)
164164 {
165 err = ngx_errno;
165 err = ngx_socket_errno;
166166
167167 /*
168168 * there is a tiny chance to be interrupted, however,
180180 } else {
181181 c->tcp_nodelay = NGX_TCP_NODELAY_UNSET;
182182
183 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
183 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
184184 "no tcp_nodelay");
185185 }
186186 }
188188 if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
189189
190190 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
191 err = ngx_errno;
191 err = ngx_socket_errno;
192192
193193 /*
194194 * there is a tiny chance to be interrupted, however,
324324
325325 c->sent += sent;
326326
327 for (cl = in; cl; cl = cl->next) {
328
329 if (ngx_buf_special(cl->buf)) {
327 for ( /* void */ ; in; in = in->next) {
328
329 if (ngx_buf_special(in->buf)) {
330330 continue;
331331 }
332332
334334 break;
335335 }
336336
337 size = ngx_buf_size(cl->buf);
337 size = ngx_buf_size(in->buf);
338338
339339 if (sent >= size) {
340340 sent -= size;
341341
342 if (ngx_buf_in_memory(cl->buf)) {
343 cl->buf->pos = cl->buf->last;
344 }
345
346 if (cl->buf->in_file) {
347 cl->buf->file_pos = cl->buf->file_last;
342 if (ngx_buf_in_memory(in->buf)) {
343 in->buf->pos = in->buf->last;
344 }
345
346 if (in->buf->in_file) {
347 in->buf->file_pos = in->buf->file_last;
348348 }
349349
350350 continue;
351351 }
352352
353 if (ngx_buf_in_memory(cl->buf)) {
354 cl->buf->pos += (size_t) sent;
355 }
356
357 if (cl->buf->in_file) {
358 cl->buf->file_pos += sent;
353 if (ngx_buf_in_memory(in->buf)) {
354 in->buf->pos += (size_t) sent;
355 }
356
357 if (in->buf->in_file) {
358 in->buf->file_pos += sent;
359359 }
360360
361361 break;
367367
368368 if (!complete) {
369369 wev->ready = 0;
370 return cl;
371 }
372
373 if (send >= limit || cl == NULL) {
374 return cl;
375 }
376
377 in = cl;
370 return in;
371 }
372
373 if (send >= limit || in == NULL) {
374 return in;
375 }
378376 }
379377 }
3838 #include <stddef.h> /* offsetof() */
3939 #include <stdio.h>
4040 #include <stdlib.h>
41 #include <ctype.h>
4142 #include <errno.h>
4243 #include <string.h>
4344 #include <signal.h>
290290 sa.sa_handler = sig->handler;
291291 sigemptyset(&sa.sa_mask);
292292 if (sigaction(sig->signo, &sa, NULL) == -1) {
293 #if (NGX_VALGRIND)
294 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
295 "sigaction(%s) failed, ignored", sig->signame);
296 #else
293297 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
294298 "sigaction(%s) failed", sig->signame);
295299 return NGX_ERROR;
300 #endif
296301 }
297302 }
298303
354354
355355 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
356356
357 ngx_memzero(&ch, sizeof(ngx_channel_t));
358
357359 ch.command = NGX_CMD_OPEN_CHANNEL;
358360
359361 for (i = 0; i < n; i++) {
399401 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
400402 &ngx_cache_manager_ctx, "cache manager process",
401403 respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
404
405 ngx_memzero(&ch, sizeof(ngx_channel_t));
402406
403407 ch.command = NGX_CMD_OPEN_CHANNEL;
404408 ch.pid = ngx_processes[ngx_process_slot].pid;
458462 ngx_int_t i;
459463 ngx_err_t err;
460464 ngx_channel_t ch;
465
466 ngx_memzero(&ch, sizeof(ngx_channel_t));
461467
462468 #if (NGX_BROKEN_SCM_RIGHTS)
463469
529535 }
530536
531537 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
532 "kill (%P, %d)" , ngx_processes[i].pid, signo);
538 "kill (%P, %d)", ngx_processes[i].pid, signo);
533539
534540 if (kill(ngx_processes[i].pid, signo) == -1) {
535541 err = ngx_errno;
559565 ngx_uint_t live;
560566 ngx_channel_t ch;
561567 ngx_core_conf_t *ccf;
568
569 ngx_memzero(&ch, sizeof(ngx_channel_t));
562570
563571 ch.command = NGX_CMD_CLOSE_CHANNEL;
564572 ch.fd = -1;
705713
706714 ngx_exit_log = *ngx_cycle->log;
707715 ngx_exit_log.file = &ngx_exit_log_file;
716 ngx_exit_log.next = NULL;
708717
709718 ngx_exit_cycle.log = &ngx_exit_log;
710719 ngx_exit_cycle.files = ngx_cycle->files;
948957 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
949958 "sigprocmask() failed");
950959 }
960
961 srandom((ngx_pid << 16) ^ ngx_time());
951962
952963 /*
953964 * disable deleting previous events for the listening sockets because
10341045 && !c[i].read->resolver)
10351046 {
10361047 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
1037 "open socket #%d left in connection %ui",
1038 c[i].fd, i);
1048 "*%uA open socket #%d left in connection %ui",
1049 c[i].number, c[i].fd, i);
10391050 ngx_debug_quit = 1;
10401051 }
10411052 }
10571068
10581069 ngx_exit_log = *ngx_cycle->log;
10591070 ngx_exit_log.file = &ngx_exit_log_file;
1071 ngx_exit_log.next = NULL;
10601072
10611073 ngx_exit_cycle.log = &ngx_exit_log;
10621074 ngx_exit_cycle.files = ngx_cycle->files;
128128 "%d available bytes", rev->available);
129129 #endif
130130
131 rev->ready = 0;
131132 rev->eof = 1;
132133 rev->available = 0;
133134 }
135136 return n;
136137 }
137138
138 if (n < size) {
139 if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) {
139140 rev->ready = 0;
140141 }
141142
7979 * even if kqueue reported about available data
8080 */
8181
82 rev->ready = 0;
8283 rev->eof = 1;
8384 rev->available = 0;
8485 }
8687 return n;
8788 }
8889
89 if ((size_t) n < size) {
90 if ((size_t) n < size
91 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
92 {
9093 rev->ready = 0;
9194 }
9295
2121 #include <stddef.h> /* offsetof() */
2222 #include <stdio.h>
2323 #include <stdlib.h>
24 #include <ctype.h>
2425 #include <errno.h>
2526 #include <string.h>
2627 #include <signal.h>
206206
207207 c->sent += sent;
208208
209 for (cl = in; cl; cl = cl->next) {
210
211 if (ngx_buf_special(cl->buf)) {
209 for ( /* void */ ; in; in = in->next) {
210
211 if (ngx_buf_special(in->buf)) {
212212 continue;
213213 }
214214
216216 break;
217217 }
218218
219 size = ngx_buf_size(cl->buf);
219 size = ngx_buf_size(in->buf);
220220
221221 if ((off_t) sent >= size) {
222222 sent = (size_t) ((off_t) sent - size);
223223
224 if (ngx_buf_in_memory(cl->buf)) {
225 cl->buf->pos = cl->buf->last;
226 }
227
228 if (cl->buf->in_file) {
229 cl->buf->file_pos = cl->buf->file_last;
224 if (ngx_buf_in_memory(in->buf)) {
225 in->buf->pos = in->buf->last;
226 }
227
228 if (in->buf->in_file) {
229 in->buf->file_pos = in->buf->file_last;
230230 }
231231
232232 continue;
233233 }
234234
235 if (ngx_buf_in_memory(cl->buf)) {
236 cl->buf->pos += sent;
237 }
238
239 if (cl->buf->in_file) {
240 cl->buf->file_pos += sent;
235 if (ngx_buf_in_memory(in->buf)) {
236 in->buf->pos += sent;
237 }
238
239 if (in->buf->in_file) {
240 in->buf->file_pos += sent;
241241 }
242242
243243 break;
249249
250250 if (!complete) {
251251 wev->ready = 0;
252 return cl;
253 }
254
255 if (send >= limit || cl == NULL) {
256 return cl;
257 }
258
259 in = cl;
252 return in;
253 }
254
255 if (send >= limit || in == NULL) {
256 return in;
257 }
260258 }
261259 }