blob: 4d1aa0d1b0ee09ea3d443fa49e5afd9d41c998fe [file] [log] [blame]
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoevd90282d2004-09-28 08:34:51 +00005 */
6
7
Igor Sysoev3c3ca172004-01-05 20:55:48 +00008#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_event.h>
Igor Sysoev3c3ca172004-01-05 20:55:48 +000011
12
Igor Sysoevd8e1f072004-01-22 06:47:28 +000013ngx_os_io_t ngx_io;
Igor Sysoev3c3ca172004-01-05 20:55:48 +000014
15
Igor Sysoev4956ac52011-04-04 12:26:53 +000016static void ngx_drain_connections(void);
17
18
Igor Sysoevee4be032009-05-05 17:33:26 +000019ngx_listening_t *
20ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
21{
Igor Sysoevbaf8e402009-10-26 11:43:32 +000022 size_t len;
Igor Sysoevee4be032009-05-05 17:33:26 +000023 ngx_listening_t *ls;
24 struct sockaddr *sa;
25 u_char text[NGX_SOCKADDR_STRLEN];
26
27 ls = ngx_array_push(&cf->cycle->listening);
28 if (ls == NULL) {
29 return NULL;
30 }
31
32 ngx_memzero(ls, sizeof(ngx_listening_t));
33
34 sa = ngx_palloc(cf->pool, socklen);
35 if (sa == NULL) {
36 return NULL;
37 }
38
39 ngx_memcpy(sa, sockaddr, socklen);
40
41 ls->sockaddr = sa;
42 ls->socklen = socklen;
43
Igor Sysoevbaf8e402009-10-26 11:43:32 +000044 len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
45 ls->addr_text.len = len;
Igor Sysoevee4be032009-05-05 17:33:26 +000046
47 switch (ls->sockaddr->sa_family) {
48#if (NGX_HAVE_INET6)
49 case AF_INET6:
50 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
51 break;
52#endif
Igor Sysoevbaf8e402009-10-26 11:43:32 +000053#if (NGX_HAVE_UNIX_DOMAIN)
54 case AF_UNIX:
55 ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
56 len++;
57 break;
58#endif
Igor Sysoevee4be032009-05-05 17:33:26 +000059 case AF_INET:
60 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
61 break;
62 default:
63 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
64 break;
65 }
66
Igor Sysoevbaf8e402009-10-26 11:43:32 +000067 ls->addr_text.data = ngx_pnalloc(cf->pool, len);
68 if (ls->addr_text.data == NULL) {
69 return NULL;
70 }
71
72 ngx_memcpy(ls->addr_text.data, text, len);
73
74 ls->fd = (ngx_socket_t) -1;
75 ls->type = SOCK_STREAM;
76
Igor Sysoevee4be032009-05-05 17:33:26 +000077 ls->backlog = NGX_LISTEN_BACKLOG;
78 ls->rcvbuf = -1;
79 ls->sndbuf = -1;
80
Igor Sysoev0bd7a7d2010-07-05 13:49:16 +000081#if (NGX_HAVE_SETFIB)
82 ls->setfib = -1;
83#endif
84
Igor Sysoevee4be032009-05-05 17:33:26 +000085 return ls;
86}
87
88
Igor Sysoev7b190b42005-06-07 15:56:31 +000089ngx_int_t
90ngx_set_inherited_sockets(ngx_cycle_t *cycle)
Igor Sysoev3c3ca172004-01-05 20:55:48 +000091{
Igor Sysoevb145b062005-06-15 18:33:41 +000092 size_t len;
93 ngx_uint_t i;
94 ngx_listening_t *ls;
Igor Sysoevc2068d02005-10-19 12:33:58 +000095 socklen_t olen;
Igor Sysoevb145b062005-06-15 18:33:41 +000096#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
Igor Sysoeve5733802005-09-08 14:36:09 +000097 ngx_err_t err;
Igor Sysoevb145b062005-06-15 18:33:41 +000098 struct accept_filter_arg af;
99#endif
100#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
Igor Sysoevb145b062005-06-15 18:33:41 +0000101 int timeout;
102#endif
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000103
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000104 ls = cycle->listening.elts;
105 for (i = 0; i < cycle->listening.nelts; i++) {
106
Igor Sysoev23f904e2010-05-31 14:49:11 +0000107 ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN);
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000108 if (ls[i].sockaddr == NULL) {
109 return NGX_ERROR;
110 }
111
Igor Sysoev23f904e2010-05-31 14:49:11 +0000112 ls[i].socklen = NGX_SOCKADDRLEN;
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000113 if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
114 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
115 "getsockname() of the inherited "
116 "socket #%d failed", ls[i].fd);
117 ls[i].ignore = 1;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000118 continue;
119 }
120
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000121 switch (ls[i].sockaddr->sa_family) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000122
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000123#if (NGX_HAVE_INET6)
124 case AF_INET6:
125 ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
Igor Sysoevbcc44e22009-11-04 18:36:43 +0000126 len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
127 break;
128#endif
129
130#if (NGX_HAVE_UNIX_DOMAIN)
131 case AF_UNIX:
132 ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
133 len = NGX_UNIX_ADDRSTRLEN;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000134 break;
135#endif
136
137 case AF_INET:
138 ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
Igor Sysoevbcc44e22009-11-04 18:36:43 +0000139 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000140 break;
141
142 default:
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000143 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
144 "the inherited socket #%d has "
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000145 "an unsupported protocol family", ls[i].fd);
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000146 ls[i].ignore = 1;
147 continue;
148 }
Igor Sysoev1b735832004-11-11 14:07:14 +0000149
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000150 ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000151 if (ls[i].addr_text.data == NULL) {
152 return NGX_ERROR;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000153 }
154
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000155 len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data, len, 1);
Igor Sysoev1b735832004-11-11 14:07:14 +0000156 if (len == 0) {
Igor Sysoeva9030eb2004-01-06 16:49:34 +0000157 return NGX_ERROR;
158 }
Igor Sysoev1b735832004-11-11 14:07:14 +0000159
Igor Sysoeva35eacc2009-02-21 07:02:02 +0000160 ls[i].addr_text.len = len;
Igor Sysoevb145b062005-06-15 18:33:41 +0000161
Igor Sysoev031a6e22007-08-09 13:32:21 +0000162 ls[i].backlog = NGX_LISTEN_BACKLOG;
Igor Sysoeve5035392005-08-30 10:55:07 +0000163
Igor Sysoevc2068d02005-10-19 12:33:58 +0000164 olen = sizeof(int);
165
166 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
167 &olen)
168 == -1)
169 {
170 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
171 "getsockopt(SO_RCVBUF) %V failed, ignored",
172 &ls[i].addr_text);
173
174 ls[i].rcvbuf = -1;
175 }
176
177 olen = sizeof(int);
178
179 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
180 &olen)
181 == -1)
182 {
183 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
184 "getsockopt(SO_SNDBUF) %V failed, ignored",
185 &ls[i].addr_text);
186
187 ls[i].sndbuf = -1;
188 }
189
Igor Sysoev0bd7a7d2010-07-05 13:49:16 +0000190#if 0
191 /* SO_SETFIB is currently a set only option */
192
193#if (NGX_HAVE_SETFIB)
194
195 if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB,
196 (void *) &ls[i].setfib, &olen)
197 == -1)
198 {
199 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
200 "getsockopt(SO_SETFIB) %V failed, ignored",
201 &ls[i].addr_text);
202
203 ls[i].setfib = -1;
204 }
205
206#endif
207#endif
208
Igor Sysoevb145b062005-06-15 18:33:41 +0000209#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
210
211 ngx_memzero(&af, sizeof(struct accept_filter_arg));
Igor Sysoevc2068d02005-10-19 12:33:58 +0000212 olen = sizeof(struct accept_filter_arg);
Igor Sysoevb145b062005-06-15 18:33:41 +0000213
Igor Sysoevc2068d02005-10-19 12:33:58 +0000214 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
Igor Sysoevb145b062005-06-15 18:33:41 +0000215 == -1)
216 {
Igor Sysoeve5733802005-09-08 14:36:09 +0000217 err = ngx_errno;
218
219 if (err == NGX_EINVAL) {
220 continue;
221 }
222
223 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
Igor Sysoevb145b062005-06-15 18:33:41 +0000224 "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
225 &ls[i].addr_text);
226 continue;
227 }
228
Igor Sysoevc2068d02005-10-19 12:33:58 +0000229 if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
Igor Sysoevb145b062005-06-15 18:33:41 +0000230 continue;
231 }
232
233 ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
234 if (ls[i].accept_filter == NULL) {
235 return NGX_ERROR;
236 }
237
238 (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
239 (u_char *) af.af_name, 16);
240#endif
241
242#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
243
244 timeout = 0;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000245 olen = sizeof(int);
Igor Sysoevb145b062005-06-15 18:33:41 +0000246
Igor Sysoevc2068d02005-10-19 12:33:58 +0000247 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
Igor Sysoevb145b062005-06-15 18:33:41 +0000248 == -1)
249 {
250 ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
251 "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
252 &ls[i].addr_text);
253 continue;
254 }
255
Igor Sysoeve173cea2005-10-19 13:34:28 +0000256 if (olen < sizeof(int) || timeout == 0) {
Igor Sysoevb145b062005-06-15 18:33:41 +0000257 continue;
258 }
259
260 ls[i].deferred_accept = 1;
261#endif
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000262 }
263
264 return NGX_OK;
265}
266
267
Igor Sysoev7b190b42005-06-07 15:56:31 +0000268ngx_int_t
269ngx_open_listening_sockets(ngx_cycle_t *cycle)
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000270{
Igor Sysoevc2068d02005-10-19 12:33:58 +0000271 int reuseaddr;
272 ngx_uint_t i, tries, failed;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000273 ngx_err_t err;
274 ngx_log_t *log;
275 ngx_socket_t s;
276 ngx_listening_t *ls;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000277
278 reuseaddr = 1;
279#if (NGX_SUPPRESS_WARN)
280 failed = 0;
281#endif
282
283 log = cycle->log;
284
Igor Sysoevc2068d02005-10-19 12:33:58 +0000285 /* TODO: configurable try number */
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000286
Igor Sysoev3b304762008-05-22 12:09:41 +0000287 for (tries = 5; tries; tries--) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000288 failed = 0;
289
290 /* for each listening socket */
291
292 ls = cycle->listening.elts;
293 for (i = 0; i < cycle->listening.nelts; i++) {
294
295 if (ls[i].ignore) {
296 continue;
297 }
298
299 if (ls[i].fd != -1) {
300 continue;
301 }
302
303 if (ls[i].inherited) {
304
305 /* TODO: close on exit */
306 /* TODO: nonblocking */
307 /* TODO: deferred accept */
308
309 continue;
310 }
311
Igor Sysoevc5849a62008-08-21 19:24:07 +0000312 s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000313
314 if (s == -1) {
315 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +0000316 ngx_socket_n " %V failed", &ls[i].addr_text);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000317 return NGX_ERROR;
318 }
319
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000320 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
Igor Sysoevc2068d02005-10-19 12:33:58 +0000321 (const void *) &reuseaddr, sizeof(int))
322 == -1)
323 {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000324 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +0000325 "setsockopt(SO_REUSEADDR) %V failed",
326 &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000327
Igor Sysoev9dd99aa2007-05-30 12:28:37 +0000328 if (ngx_close_socket(s) == -1) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000329 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
330 ngx_close_socket_n " %V failed",
331 &ls[i].addr_text);
Igor Sysoev9dd99aa2007-05-30 12:28:37 +0000332 }
Igor Sysoevc2068d02005-10-19 12:33:58 +0000333
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000334 return NGX_ERROR;
335 }
336
Igor Sysoev6d94b512009-03-13 14:20:34 +0000337#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
338
339 if (ls[i].sockaddr->sa_family == AF_INET6 && ls[i].ipv6only) {
340 int ipv6only;
341
342 ipv6only = (ls[i].ipv6only == 1);
343
344 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
345 (const void *) &ipv6only, sizeof(int))
346 == -1)
347 {
Igor Sysoev682414f2009-05-05 13:05:42 +0000348 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
Igor Sysoev6d94b512009-03-13 14:20:34 +0000349 "setsockopt(IPV6_V6ONLY) %V failed, ignored",
350 &ls[i].addr_text);
351 }
352 }
353#endif
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000354 /* TODO: close on exit */
355
356 if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
357 if (ngx_nonblocking(s) == -1) {
358 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +0000359 ngx_nonblocking_n " %V failed",
360 &ls[i].addr_text);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000361
Igor Sysoev9dd99aa2007-05-30 12:28:37 +0000362 if (ngx_close_socket(s) == -1) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000363 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
364 ngx_close_socket_n " %V failed",
365 &ls[i].addr_text);
Igor Sysoev9dd99aa2007-05-30 12:28:37 +0000366 }
Igor Sysoevc2068d02005-10-19 12:33:58 +0000367
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000368 return NGX_ERROR;
369 }
370 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000371
Igor Sysoev682414f2009-05-05 13:05:42 +0000372 ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
Igor Sysoev305a9d82005-12-26 17:07:48 +0000373 "bind() %V #%d ", &ls[i].addr_text, s);
374
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000375 if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
376 err = ngx_socket_errno;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000377
378 if (err == NGX_EADDRINUSE && ngx_test_config) {
379 continue;
380 }
381
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000382 ngx_log_error(NGX_LOG_EMERG, log, err,
Igor Sysoev1b735832004-11-11 14:07:14 +0000383 "bind() to %V failed", &ls[i].addr_text);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000384
Igor Sysoev9dd99aa2007-05-30 12:28:37 +0000385 if (ngx_close_socket(s) == -1) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000386 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +0000387 ngx_close_socket_n " %V failed",
388 &ls[i].addr_text);
Igor Sysoev9dd99aa2007-05-30 12:28:37 +0000389 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000390
Igor Sysoevc2068d02005-10-19 12:33:58 +0000391 if (err != NGX_EADDRINUSE) {
392 return NGX_ERROR;
393 }
394
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000395 failed = 1;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000396
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000397 continue;
398 }
399
Igor Sysoev633c1782009-10-30 19:16:50 +0000400#if (NGX_HAVE_UNIX_DOMAIN)
401
Igor Sysoeva734e332009-11-30 11:26:24 +0000402 if (ls[i].sockaddr->sa_family == AF_UNIX) {
403 mode_t mode;
404 u_char *name;
Igor Sysoev633c1782009-10-30 19:16:50 +0000405
Igor Sysoeva734e332009-11-30 11:26:24 +0000406 name = ls[i].addr_text.data + sizeof("unix:") - 1;
407 mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
408
409 if (chmod((char *) name, mode) == -1) {
410 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
411 "chmod() \"%s\" failed", name);
412 }
413
414 if (ngx_test_config) {
415 if (ngx_delete_file(name) == -1) {
416 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
417 ngx_delete_file_n " %s failed", name);
418 }
Igor Sysoev633c1782009-10-30 19:16:50 +0000419 }
420 }
421#endif
422
Igor Sysoevd4aa5722007-05-30 13:23:48 +0000423 if (listen(s, ls[i].backlog) == -1) {
424 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
425 "listen() to %V, backlog %d failed",
426 &ls[i].addr_text, ls[i].backlog);
427
428 if (ngx_close_socket(s) == -1) {
429 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
430 ngx_close_socket_n " %V failed",
431 &ls[i].addr_text);
432 }
433
434 return NGX_ERROR;
435 }
436
Igor Sysoevc2068d02005-10-19 12:33:58 +0000437 ls[i].listen = 1;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000438
439 ls[i].fd = s;
440 }
441
Igor Sysoevc2068d02005-10-19 12:33:58 +0000442 if (!failed) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000443 break;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000444 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000445
446 /* TODO: delay configurable */
447
448 ngx_log_error(NGX_LOG_NOTICE, log, 0,
449 "try again to bind() after 500ms");
Igor Sysoevc2068d02005-10-19 12:33:58 +0000450
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000451 ngx_msleep(500);
452 }
453
454 if (failed) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000455 ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000456 return NGX_ERROR;
457 }
458
459 return NGX_OK;
460}
461
462
Igor Sysoev7b190b42005-06-07 15:56:31 +0000463void
Igor Sysoev00bd1372009-05-05 13:12:59 +0000464ngx_configure_listening_sockets(ngx_cycle_t *cycle)
Igor Sysoevc2068d02005-10-19 12:33:58 +0000465{
Valentin Bartenev92edf472011-12-05 08:06:15 +0000466 int keepalive;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000467 ngx_uint_t i;
468 ngx_listening_t *ls;
469
470#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
471 struct accept_filter_arg af;
472#endif
473#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
474 int timeout;
475#endif
476
477 ls = cycle->listening.elts;
478 for (i = 0; i < cycle->listening.nelts; i++) {
479
Igor Sysoevd4a71fb2009-05-05 13:16:29 +0000480 ls[i].log = *ls[i].logp;
481
Igor Sysoevc2068d02005-10-19 12:33:58 +0000482 if (ls[i].rcvbuf != -1) {
483 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
484 (const void *) &ls[i].rcvbuf, sizeof(int))
485 == -1)
486 {
487 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000488 "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
489 ls[i].rcvbuf, &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000490 }
491 }
492
493 if (ls[i].sndbuf != -1) {
494 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
495 (const void *) &ls[i].sndbuf, sizeof(int))
496 == -1)
497 {
498 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000499 "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
500 ls[i].sndbuf, &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000501 }
502 }
503
Valentin Bartenev92edf472011-12-05 08:06:15 +0000504 if (ls[i].keepalive) {
505 keepalive = (ls[i].keepalive == 1) ? 1 : 0;
506
507 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
508 (const void *) &keepalive, sizeof(int))
509 == -1)
510 {
511 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
512 "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
513 keepalive, &ls[i].addr_text);
514 }
515 }
516
Maxim Douninee187432012-03-05 18:09:06 +0000517#if (NGX_HAVE_KEEPALIVE_TUNABLE)
Valentin Bartenev92edf472011-12-05 08:06:15 +0000518
519 if (ls[i].keepidle) {
520 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
521 (const void *) &ls[i].keepidle, sizeof(int))
522 == -1)
523 {
524 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
525 "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
526 ls[i].keepidle, &ls[i].addr_text);
527 }
528 }
529
530 if (ls[i].keepintvl) {
531 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
532 (const void *) &ls[i].keepintvl, sizeof(int))
533 == -1)
534 {
535 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
536 "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
537 ls[i].keepintvl, &ls[i].addr_text);
538 }
539 }
540
541 if (ls[i].keepcnt) {
542 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
543 (const void *) &ls[i].keepcnt, sizeof(int))
544 == -1)
545 {
546 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
547 "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
548 ls[i].keepcnt, &ls[i].addr_text);
549 }
550 }
551
552#endif
553
Igor Sysoev0bd7a7d2010-07-05 13:49:16 +0000554#if (NGX_HAVE_SETFIB)
555 if (ls[i].setfib != -1) {
556 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
557 (const void *) &ls[i].setfib, sizeof(int))
558 == -1)
559 {
560 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
561 "setsockopt(SO_SETFIB, %d) %V failed, ignored",
562 ls[i].setfib, &ls[i].addr_text);
563 }
564 }
565#endif
566
Igor Sysoevcdf609a2006-04-17 19:55:41 +0000567#if 0
568 if (1) {
569 int tcp_nodelay = 1;
570
571 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
572 (const void *) &tcp_nodelay, sizeof(int))
573 == -1)
574 {
575 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
576 "setsockopt(TCP_NODELAY) %V failed, ignored",
577 &ls[i].addr_text);
578 }
579 }
580#endif
581
Igor Sysoevc2068d02005-10-19 12:33:58 +0000582 if (ls[i].listen) {
Igor Sysoevb1c6c432007-05-30 13:24:50 +0000583
584 /* change backlog via listen() */
585
Igor Sysoevc2068d02005-10-19 12:33:58 +0000586 if (listen(ls[i].fd, ls[i].backlog) == -1) {
587 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
Igor Sysoevc1417932007-05-29 19:43:18 +0000588 "listen() to %V, backlog %d failed, ignored",
589 &ls[i].addr_text, ls[i].backlog);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000590 }
591 }
592
593 /*
594 * setting deferred mode should be last operation on socket,
595 * because code may prematurely continue cycle on failure
596 */
597
598#if (NGX_HAVE_DEFERRED_ACCEPT)
599
600#ifdef SO_ACCEPTFILTER
601
Igor Sysoev6275f562006-03-28 12:24:47 +0000602 if (ls[i].delete_deferred) {
603 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
604 == -1)
Igor Sysoevc2068d02005-10-19 12:33:58 +0000605 {
606 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
607 "setsockopt(SO_ACCEPTFILTER, NULL) "
608 "for %V failed, ignored",
Igor Sysoev6275f562006-03-28 12:24:47 +0000609 &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000610
Igor Sysoev6275f562006-03-28 12:24:47 +0000611 if (ls[i].accept_filter) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000612 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
613 "could not change the accept filter "
614 "to \"%s\" for %V, ignored",
Igor Sysoev6275f562006-03-28 12:24:47 +0000615 ls[i].accept_filter, &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000616 }
617
618 continue;
619 }
620
Igor Sysoev6275f562006-03-28 12:24:47 +0000621 ls[i].deferred_accept = 0;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000622 }
623
Igor Sysoev6275f562006-03-28 12:24:47 +0000624 if (ls[i].add_deferred) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000625 ngx_memzero(&af, sizeof(struct accept_filter_arg));
626 (void) ngx_cpystrn((u_char *) af.af_name,
Igor Sysoev6275f562006-03-28 12:24:47 +0000627 (u_char *) ls[i].accept_filter, 16);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000628
Igor Sysoev6275f562006-03-28 12:24:47 +0000629 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
Igor Sysoevc2068d02005-10-19 12:33:58 +0000630 &af, sizeof(struct accept_filter_arg))
631 == -1)
632 {
633 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
634 "setsockopt(SO_ACCEPTFILTER, \"%s\") "
Maxim Douninec8186c2011-08-21 11:37:37 +0000635 "for %V failed, ignored",
Igor Sysoev6275f562006-03-28 12:24:47 +0000636 ls[i].accept_filter, &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000637 continue;
638 }
639
Igor Sysoev6275f562006-03-28 12:24:47 +0000640 ls[i].deferred_accept = 1;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000641 }
642
643#endif
644
645#ifdef TCP_DEFER_ACCEPT
646
Igor Sysoev6275f562006-03-28 12:24:47 +0000647 if (ls[i].add_deferred || ls[i].delete_deferred) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000648
Igor Sysoev6275f562006-03-28 12:24:47 +0000649 if (ls[i].add_deferred) {
650 timeout = (int) (ls[i].post_accept_timeout / 1000);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000651
652 } else {
653 timeout = 0;
654 }
655
Igor Sysoev6275f562006-03-28 12:24:47 +0000656 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
Igor Sysoevc2068d02005-10-19 12:33:58 +0000657 &timeout, sizeof(int))
658 == -1)
659 {
660 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
661 "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
662 "ignored",
Igor Sysoev6275f562006-03-28 12:24:47 +0000663 timeout, &ls[i].addr_text);
Igor Sysoevc2068d02005-10-19 12:33:58 +0000664
665 continue;
666 }
667 }
668
Igor Sysoev6275f562006-03-28 12:24:47 +0000669 if (ls[i].add_deferred) {
670 ls[i].deferred_accept = 1;
Igor Sysoevc2068d02005-10-19 12:33:58 +0000671 }
672
673#endif
674
675#endif /* NGX_HAVE_DEFERRED_ACCEPT */
676 }
677
678 return;
679}
680
681
682void
Igor Sysoev7b190b42005-06-07 15:56:31 +0000683ngx_close_listening_sockets(ngx_cycle_t *cycle)
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000684{
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000685 ngx_uint_t i;
686 ngx_listening_t *ls;
687 ngx_connection_t *c;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000688
689 if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
690 return;
691 }
692
Igor Sysoevdbb27762004-04-01 16:20:53 +0000693 ngx_accept_mutex_held = 0;
Igor Sysoevffe71442006-02-08 15:33:12 +0000694 ngx_use_accept_mutex = 0;
Igor Sysoevdbb27762004-04-01 16:20:53 +0000695
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000696 ls = cycle->listening.elts;
697 for (i = 0; i < cycle->listening.nelts; i++) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000698
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000699 c = ls[i].connection;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000700
Igor Sysoevbd919992009-04-20 06:08:47 +0000701 if (c) {
702 if (c->read->active) {
703 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
704 ngx_del_conn(c, NGX_CLOSE_EVENT);
Igor Sysoev68df19d2004-04-15 15:34:36 +0000705
Igor Sysoevbd919992009-04-20 06:08:47 +0000706 } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
Igor Sysoev0008ebe2008-01-08 11:31:50 +0000707
Igor Sysoevbd919992009-04-20 06:08:47 +0000708 /*
709 * it seems that Linux-2.6.x OpenVZ sends events
710 * for closed shared listening sockets unless
711 * the events was explicity deleted
712 */
Igor Sysoev0008ebe2008-01-08 11:31:50 +0000713
Igor Sysoevbd919992009-04-20 06:08:47 +0000714 ngx_del_event(c->read, NGX_READ_EVENT, 0);
Igor Sysoev0008ebe2008-01-08 11:31:50 +0000715
Igor Sysoevbd919992009-04-20 06:08:47 +0000716 } else {
717 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
718 }
Igor Sysoev68df19d2004-04-15 15:34:36 +0000719 }
Igor Sysoevbd919992009-04-20 06:08:47 +0000720
721 ngx_free_connection(c);
722
723 c->fd = (ngx_socket_t) -1;
Igor Sysoev68df19d2004-04-15 15:34:36 +0000724 }
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000725
Igor Sysoevc2068d02005-10-19 12:33:58 +0000726 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
727 "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
728
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000729 if (ngx_close_socket(ls[i].fd) == -1) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000730 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +0000731 ngx_close_socket_n " %V failed", &ls[i].addr_text);
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000732 }
Igor Sysoev2d650782009-06-07 18:22:58 +0000733
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000734#if (NGX_HAVE_UNIX_DOMAIN)
735
736 if (ls[i].sockaddr->sa_family == AF_UNIX
Igor Sysoev72db7602009-11-23 15:46:21 +0000737 && ngx_process <= NGX_PROCESS_MASTER
Igor Sysoev9f179fe2009-10-30 19:18:21 +0000738 && ngx_new_binary == 0)
Igor Sysoevbaf8e402009-10-26 11:43:32 +0000739 {
740 u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
741
742 if (ngx_delete_file(name) == -1) {
743 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
744 ngx_delete_file_n " %s failed", name);
745 }
746 }
747
748#endif
749
Igor Sysoev2d650782009-06-07 18:22:58 +0000750 ls[i].fd = (ngx_socket_t) -1;
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000751 }
752}
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000753
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000754
755ngx_connection_t *
756ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
757{
Igor Sysoev78452232005-10-12 13:50:36 +0000758 ngx_uint_t instance;
759 ngx_event_t *rev, *wev;
760 ngx_connection_t *c;
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000761
762 /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
763
764 if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
765 ngx_log_error(NGX_LOG_ALERT, log, 0,
766 "the new socket has number %d, "
767 "but only %ui files are available",
768 s, ngx_cycle->files_n);
769 return NULL;
770 }
771
772 /* ngx_mutex_lock */
773
774 c = ngx_cycle->free_connections;
775
776 if (c == NULL) {
Igor Sysoev4956ac52011-04-04 12:26:53 +0000777 ngx_drain_connections();
778 c = ngx_cycle->free_connections;
779 }
780
781 if (c == NULL) {
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000782 ngx_log_error(NGX_LOG_ALERT, log, 0,
Igor Sysoevc9ff5b62008-09-17 08:03:58 +0000783 "%ui worker_connections are not enough",
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000784 ngx_cycle->connection_n);
785
786 /* ngx_mutex_unlock */
787
788 return NULL;
789 }
790
791 ngx_cycle->free_connections = c->data;
792 ngx_cycle->free_connection_n--;
793
794 /* ngx_mutex_unlock */
795
796 if (ngx_cycle->files) {
797 ngx_cycle->files[s] = c;
798 }
799
Igor Sysoev78452232005-10-12 13:50:36 +0000800 rev = c->read;
801 wev = c->write;
802
803 ngx_memzero(c, sizeof(ngx_connection_t));
804
805 c->read = rev;
806 c->write = wev;
807 c->fd = s;
808 c->log = log;
809
810 instance = rev->instance;
811
812 ngx_memzero(rev, sizeof(ngx_event_t));
813 ngx_memzero(wev, sizeof(ngx_event_t));
814
815 rev->instance = !instance;
816 wev->instance = !instance;
817
818 rev->index = NGX_INVALID_INDEX;
819 wev->index = NGX_INVALID_INDEX;
820
821 rev->data = c;
822 wev->data = c;
823
824 wev->write = 1;
825
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000826 return c;
827}
828
829
830void
831ngx_free_connection(ngx_connection_t *c)
832{
833 /* ngx_mutex_lock */
834
835 c->data = ngx_cycle->free_connections;
836 ngx_cycle->free_connections = c;
837 ngx_cycle->free_connection_n++;
838
839 /* ngx_mutex_unlock */
840
841 if (ngx_cycle->files) {
842 ngx_cycle->files[c->fd] = NULL;
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000843 }
844}
Igor Sysoev7af6b162004-02-09 07:46:43 +0000845
846
Igor Sysoev7b190b42005-06-07 15:56:31 +0000847void
848ngx_close_connection(ngx_connection_t *c)
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000849{
Igor Sysoeva4d00f12008-03-05 21:21:26 +0000850 ngx_err_t err;
851 ngx_uint_t log_error, level;
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000852 ngx_socket_t fd;
853
Igor Sysoev02025fd2005-01-18 13:03:58 +0000854 if (c->fd == -1) {
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000855 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
856 return;
857 }
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000858
859 if (c->read->timer_set) {
860 ngx_del_timer(c->read);
861 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000862
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000863 if (c->write->timer_set) {
864 ngx_del_timer(c->write);
865 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000866
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000867 if (ngx_del_conn) {
868 ngx_del_conn(c, NGX_CLOSE_EVENT);
869
870 } else {
871 if (c->read->active || c->read->disabled) {
872 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
873 }
874
875 if (c->write->active || c->write->disabled) {
876 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
877 }
878 }
879
880#if (NGX_THREADS)
881
882 /*
883 * we have to clean the connection information before the closing
884 * because another thread may reopen the same file descriptor
885 * before we clean the connection
886 */
887
Igor Sysoevc2068d02005-10-19 12:33:58 +0000888 ngx_mutex_lock(ngx_posted_events_mutex);
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000889
Igor Sysoevc2068d02005-10-19 12:33:58 +0000890 if (c->read->prev) {
891 ngx_delete_posted_event(c->read);
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000892 }
893
Igor Sysoevc2068d02005-10-19 12:33:58 +0000894 if (c->write->prev) {
895 ngx_delete_posted_event(c->write);
896 }
897
898 c->read->closed = 1;
899 c->write->closed = 1;
900
901 if (c->single_connection) {
902 ngx_unlock(&c->lock);
903 c->read->locked = 0;
904 c->write->locked = 0;
905 }
906
907 ngx_mutex_unlock(ngx_posted_events_mutex);
908
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000909#else
910
911 if (c->read->prev) {
912 ngx_delete_posted_event(c->read);
913 }
914
915 if (c->write->prev) {
916 ngx_delete_posted_event(c->write);
917 }
918
919 c->read->closed = 1;
920 c->write->closed = 1;
921
922#endif
923
Igor Sysoev4956ac52011-04-04 12:26:53 +0000924 ngx_reusable_connection(c, 0);
925
Igor Sysoeva4d00f12008-03-05 21:21:26 +0000926 log_error = c->log_error;
927
Igor Sysoev31eb8c02005-09-23 11:02:22 +0000928 ngx_free_connection(c);
929
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000930 fd = c->fd;
931 c->fd = (ngx_socket_t) -1;
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000932
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000933 if (ngx_close_socket(fd) == -1) {
934
Igor Sysoeva4d00f12008-03-05 21:21:26 +0000935 err = ngx_socket_errno;
936
937 if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
938
939 switch (log_error) {
940
941 case NGX_ERROR_INFO:
942 level = NGX_LOG_INFO;
943 break;
944
945 case NGX_ERROR_ERR:
946 level = NGX_LOG_ERR;
947 break;
948
949 default:
950 level = NGX_LOG_CRIT;
951 }
952
953 } else {
954 level = NGX_LOG_CRIT;
955 }
956
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000957 /* we use ngx_cycle->log because c->log was in c->pool */
958
Igor Sysoeva4d00f12008-03-05 21:21:26 +0000959 ngx_log_error(level, ngx_cycle->log, err,
Igor Sysoevd8d0e0b2007-08-29 15:33:59 +0000960 ngx_close_socket_n " %d failed", fd);
Igor Sysoev59cf56c2004-09-07 15:29:22 +0000961 }
962}
963
964
Igor Sysoev4956ac52011-04-04 12:26:53 +0000965void
966ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
967{
968 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
969 "reusable connection: %ui", reusable);
970
971 if (c->reusable) {
972 ngx_queue_remove(&c->queue);
973 }
974
975 c->reusable = reusable;
976
977 if (reusable) {
978 /* need cast as ngx_cycle is volatile */
979
980 ngx_queue_insert_head(
981 (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
982 }
983}
984
985
986static void
987ngx_drain_connections(void)
988{
989 ngx_int_t i;
990 ngx_queue_t *q;
991 ngx_connection_t *c;
992
993 for (i = 0; i < 32; i++) {
994 if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) {
995 break;
996 }
997
998 q = ngx_queue_last(&ngx_cycle->reusable_connections_queue);
999 c = ngx_queue_data(q, ngx_connection_t, queue);
1000
1001 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
1002 "reusing connection");
1003
1004 c->close = 1;
1005 c->read->handler(c->read);
1006 }
1007}
1008
1009
Igor Sysoev7b190b42005-06-07 15:56:31 +00001010ngx_int_t
Igor Sysoevc985ee72009-05-18 12:12:06 +00001011ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
1012 ngx_uint_t port)
1013{
1014 socklen_t len;
1015 ngx_uint_t addr;
1016 u_char sa[NGX_SOCKADDRLEN];
1017 struct sockaddr_in *sin;
1018#if (NGX_HAVE_INET6)
1019 ngx_uint_t i;
1020 struct sockaddr_in6 *sin6;
1021#endif
1022
1023 switch (c->local_sockaddr->sa_family) {
1024
1025#if (NGX_HAVE_INET6)
1026 case AF_INET6:
1027 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
1028
1029 for (addr = 0, i = 0; addr == 0 && i < 16; i++) {
1030 addr |= sin6->sin6_addr.s6_addr[i];
1031 }
1032
1033 break;
1034#endif
1035
1036 default: /* AF_INET */
1037 sin = (struct sockaddr_in *) c->local_sockaddr;
1038 addr = sin->sin_addr.s_addr;
1039 break;
1040 }
1041
1042 if (addr == 0) {
1043
1044 len = NGX_SOCKADDRLEN;
1045
1046 if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) {
1047 ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1048 return NGX_ERROR;
1049 }
1050
1051 c->local_sockaddr = ngx_palloc(c->pool, len);
1052 if (c->local_sockaddr == NULL) {
1053 return NGX_ERROR;
1054 }
1055
Igor Sysoevc985ee72009-05-18 12:12:06 +00001056 ngx_memcpy(c->local_sockaddr, &sa, len);
1057 }
1058
1059 if (s == NULL) {
1060 return NGX_OK;
1061 }
1062
1063 s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, port);
1064
1065 return NGX_OK;
1066}
1067
1068
1069ngx_int_t
Igor Sysoev7b190b42005-06-07 15:56:31 +00001070ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
Igor Sysoev7af6b162004-02-09 07:46:43 +00001071{
Igor Sysoev54498db2004-02-11 17:08:49 +00001072 ngx_uint_t level;
Igor Sysoev7af6b162004-02-09 07:46:43 +00001073
Igor Sysoeva70d0862009-04-29 13:07:16 +00001074 /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
1075
1076 if ((err == NGX_ECONNRESET
Igor Sysoevdcc92052009-04-29 11:34:58 +00001077#if (NGX_WIN32)
Igor Sysoeva70d0862009-04-29 13:07:16 +00001078 || err == NGX_ECONNABORTED
Igor Sysoevdcc92052009-04-29 11:34:58 +00001079#endif
Igor Sysoeva70d0862009-04-29 13:07:16 +00001080 ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
Igor Sysoevdcc92052009-04-29 11:34:58 +00001081 {
Igor Sysoev7af6b162004-02-09 07:46:43 +00001082 return 0;
1083 }
1084
Igor Sysoev0bd7b002009-03-12 07:16:15 +00001085#if (NGX_SOLARIS)
1086 if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
1087 return 0;
1088 }
1089#endif
1090
Igor Sysoeve5035392005-08-30 10:55:07 +00001091 if (err == 0
1092 || err == NGX_ECONNRESET
Igor Sysoevdcc92052009-04-29 11:34:58 +00001093#if (NGX_WIN32)
1094 || err == NGX_ECONNABORTED
1095#else
Igor Sysoeva5362982004-03-04 07:04:55 +00001096 || err == NGX_EPIPE
1097#endif
Igor Sysoev3646a162004-03-14 20:46:25 +00001098 || err == NGX_ENOTCONN
Igor Sysoevcdc46302005-12-07 14:51:31 +00001099 || err == NGX_ETIMEDOUT
Igor Sysoev3646a162004-03-14 20:46:25 +00001100 || err == NGX_ECONNREFUSED
Igor Sysoev02d8e8e2008-01-25 14:57:35 +00001101 || err == NGX_ENETDOWN
1102 || err == NGX_ENETUNREACH
1103 || err == NGX_EHOSTDOWN
Igor Sysoev3646a162004-03-14 20:46:25 +00001104 || err == NGX_EHOSTUNREACH)
Igor Sysoeva5362982004-03-04 07:04:55 +00001105 {
Igor Sysoevc7a2f682004-02-10 16:23:38 +00001106 switch (c->log_error) {
Igor Sysoev7af6b162004-02-09 07:46:43 +00001107
Igor Sysoev0bd7b002009-03-12 07:16:15 +00001108 case NGX_ERROR_IGNORE_EINVAL:
Igor Sysoev54498db2004-02-11 17:08:49 +00001109 case NGX_ERROR_IGNORE_ECONNRESET:
Igor Sysoev7af6b162004-02-09 07:46:43 +00001110 case NGX_ERROR_INFO:
1111 level = NGX_LOG_INFO;
1112 break;
1113
Igor Sysoev7af6b162004-02-09 07:46:43 +00001114 default:
Igor Sysoeve5b2d3c2009-09-23 15:28:33 +00001115 level = NGX_LOG_ERR;
Igor Sysoev7af6b162004-02-09 07:46:43 +00001116 }
1117
1118 } else {
Igor Sysoeva4d00f12008-03-05 21:21:26 +00001119 level = NGX_LOG_ALERT;
Igor Sysoev7af6b162004-02-09 07:46:43 +00001120 }
1121
1122 ngx_log_error(level, c->log, err, text);
1123
1124 return NGX_ERROR;
1125}