1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11
12
13 ngx_os_io_t ngx_io;
14
15
16 static void ngx_drain_connections(ngx_cycle_t *cycle);
17
18
19 ngx_listening_t *
ngx_create_listening(ngx_conf_t * cf,struct sockaddr * sockaddr,socklen_t socklen)20 ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr,
21 socklen_t socklen)
22 {
23 size_t len;
24 ngx_listening_t *ls;
25 struct sockaddr *sa;
26 u_char text[NGX_SOCKADDR_STRLEN];
27
28 ls = ngx_array_push(&cf->cycle->listening);
29 if (ls == NULL) {
30 return NULL;
31 }
32
33 ngx_memzero(ls, sizeof(ngx_listening_t));
34
35 sa = ngx_palloc(cf->pool, socklen);
36 if (sa == NULL) {
37 return NULL;
38 }
39
40 ngx_memcpy(sa, sockaddr, socklen);
41
42 ls->sockaddr = sa;
43 ls->socklen = socklen;
44
45 len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
46 ls->addr_text.len = len;
47
48 switch (ls->sockaddr->sa_family) {
49 #if (NGX_HAVE_INET6)
50 case AF_INET6:
51 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
52 break;
53 #endif
54 #if (NGX_HAVE_UNIX_DOMAIN)
55 case AF_UNIX:
56 ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
57 len++;
58 break;
59 #endif
60 case AF_INET:
61 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
62 break;
63 default:
64 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
65 break;
66 }
67
68 ls->addr_text.data = ngx_pnalloc(cf->pool, len);
69 if (ls->addr_text.data == NULL) {
70 return NULL;
71 }
72
73 ngx_memcpy(ls->addr_text.data, text, len);
74
75 #if !(NGX_WIN32)
76 ngx_rbtree_init(&ls->rbtree, &ls->sentinel, ngx_udp_rbtree_insert_value);
77 #endif
78
79 ls->fd = (ngx_socket_t) -1;
80 ls->type = SOCK_STREAM;
81
82 ls->backlog = NGX_LISTEN_BACKLOG;
83 ls->rcvbuf = -1;
84 ls->sndbuf = -1;
85
86 #if (NGX_HAVE_SETFIB)
87 ls->setfib = -1;
88 #endif
89
90 #if (NGX_HAVE_TCP_FASTOPEN)
91 ls->fastopen = -1;
92 #endif
93
94 return ls;
95 }
96
97
98 ngx_int_t
ngx_clone_listening(ngx_cycle_t * cycle,ngx_listening_t * ls)99 ngx_clone_listening(ngx_cycle_t *cycle, ngx_listening_t *ls)
100 {
101 #if (NGX_HAVE_REUSEPORT)
102
103 ngx_int_t n;
104 ngx_core_conf_t *ccf;
105 ngx_listening_t ols;
106
107 if (!ls->reuseport || ls->worker != 0) {
108 return NGX_OK;
109 }
110
111 ols = *ls;
112
113 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
114
115 for (n = 1; n < ccf->worker_processes; n++) {
116
117 /* create a socket for each worker process */
118
119 ls = ngx_array_push(&cycle->listening);
120 if (ls == NULL) {
121 return NGX_ERROR;
122 }
123
124 *ls = ols;
125 ls->worker = n;
126 }
127
128 #endif
129
130 return NGX_OK;
131 }
132
133
134 ngx_int_t
ngx_set_inherited_sockets(ngx_cycle_t * cycle)135 ngx_set_inherited_sockets(ngx_cycle_t *cycle)
136 {
137 size_t len;
138 ngx_uint_t i;
139 ngx_listening_t *ls;
140 socklen_t olen;
141 #if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
142 ngx_err_t err;
143 #endif
144 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
145 struct accept_filter_arg af;
146 #endif
147 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
148 int timeout;
149 #endif
150 #if (NGX_HAVE_REUSEPORT)
151 int reuseport;
152 #endif
153
154 ls = cycle->listening.elts;
155 for (i = 0; i < cycle->listening.nelts; i++) {
156
157 ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t));
158 if (ls[i].sockaddr == NULL) {
159 return NGX_ERROR;
160 }
161
162 ls[i].socklen = sizeof(ngx_sockaddr_t);
163 if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
164 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
165 "getsockname() of the inherited "
166 "socket #%d failed", ls[i].fd);
167 ls[i].ignore = 1;
168 continue;
169 }
170
171 if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
172 ls[i].socklen = sizeof(ngx_sockaddr_t);
173 }
174
175 switch (ls[i].sockaddr->sa_family) {
176
177 #if (NGX_HAVE_INET6)
178 case AF_INET6:
179 ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
180 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
181 break;
182 #endif
183
184 #if (NGX_HAVE_UNIX_DOMAIN)
185 case AF_UNIX:
186 ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
187 len = NGX_UNIX_ADDRSTRLEN;
188 break;
189 #endif
190
191 case AF_INET:
192 ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
193 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
194 break;
195
196 default:
197 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
198 "the inherited socket #%d has "
199 "an unsupported protocol family", ls[i].fd);
200 ls[i].ignore = 1;
201 continue;
202 }
203
204 ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
205 if (ls[i].addr_text.data == NULL) {
206 return NGX_ERROR;
207 }
208
209 len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
210 ls[i].addr_text.data, len, 1);
211 if (len == 0) {
212 return NGX_ERROR;
213 }
214
215 ls[i].addr_text.len = len;
216
217 ls[i].backlog = NGX_LISTEN_BACKLOG;
218
219 olen = sizeof(int);
220
221 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_TYPE, (void *) &ls[i].type,
222 &olen)
223 == -1)
224 {
225 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
226 "getsockopt(SO_TYPE) %V failed", &ls[i].addr_text);
227 ls[i].ignore = 1;
228 continue;
229 }
230
231 olen = sizeof(int);
232
233 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
234 &olen)
235 == -1)
236 {
237 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
238 "getsockopt(SO_RCVBUF) %V failed, ignored",
239 &ls[i].addr_text);
240
241 ls[i].rcvbuf = -1;
242 }
243
244 olen = sizeof(int);
245
246 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
247 &olen)
248 == -1)
249 {
250 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
251 "getsockopt(SO_SNDBUF) %V failed, ignored",
252 &ls[i].addr_text);
253
254 ls[i].sndbuf = -1;
255 }
256
257 #if 0
258 /* SO_SETFIB is currently a set only option */
259
260 #if (NGX_HAVE_SETFIB)
261
262 olen = sizeof(int);
263
264 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
265 (void *) &ls[i].setfib, &olen)
266 == -1)
267 {
268 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
269 "getsockopt(SO_SETFIB) %V failed, ignored",
270 &ls[i].addr_text);
271
272 ls[i].setfib = -1;
273 }
274
275 #endif
276 #endif
277
278 #if (NGX_HAVE_REUSEPORT)
279
280 reuseport = 0;
281 olen = sizeof(int);
282
283 #ifdef SO_REUSEPORT_LB
284
285 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT_LB,
286 (void *) &reuseport, &olen)
287 == -1)
288 {
289 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
290 "getsockopt(SO_REUSEPORT_LB) %V failed, ignored",
291 &ls[i].addr_text);
292
293 } else {
294 ls[i].reuseport = reuseport ? 1 : 0;
295 }
296
297 #else
298
299 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
300 (void *) &reuseport, &olen)
301 == -1)
302 {
303 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
304 "getsockopt(SO_REUSEPORT) %V failed, ignored",
305 &ls[i].addr_text);
306
307 } else {
308 ls[i].reuseport = reuseport ? 1 : 0;
309 }
310 #endif
311
312 #endif
313
314 if (ls[i].type != SOCK_STREAM) {
315 continue;
316 }
317
318 #if (NGX_HAVE_TCP_FASTOPEN)
319
320 olen = sizeof(int);
321
322 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
323 (void *) &ls[i].fastopen, &olen)
324 == -1)
325 {
326 err = ngx_socket_errno;
327
328 if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT
329 && err != NGX_EINVAL)
330 {
331 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
332 "getsockopt(TCP_FASTOPEN) %V failed, ignored",
333 &ls[i].addr_text);
334 }
335
336 ls[i].fastopen = -1;
337 }
338
339 #endif
340
341 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
342
343 ngx_memzero(&af, sizeof(struct accept_filter_arg));
344 olen = sizeof(struct accept_filter_arg);
345
346 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
347 == -1)
348 {
349 err = ngx_socket_errno;
350
351 if (err == NGX_EINVAL) {
352 continue;
353 }
354
355 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
356 "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
357 &ls[i].addr_text);
358 continue;
359 }
360
361 if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
362 continue;
363 }
364
365 ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
366 if (ls[i].accept_filter == NULL) {
367 return NGX_ERROR;
368 }
369
370 (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
371 (u_char *) af.af_name, 16);
372 #endif
373
374 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
375
376 timeout = 0;
377 olen = sizeof(int);
378
379 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
380 == -1)
381 {
382 err = ngx_socket_errno;
383
384 if (err == NGX_EOPNOTSUPP) {
385 continue;
386 }
387
388 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
389 "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
390 &ls[i].addr_text);
391 continue;
392 }
393
394 if (olen < sizeof(int) || timeout == 0) {
395 continue;
396 }
397
398 ls[i].deferred_accept = 1;
399 #endif
400 }
401
402 return NGX_OK;
403 }
404
405
406 ngx_int_t
ngx_open_listening_sockets(ngx_cycle_t * cycle)407 ngx_open_listening_sockets(ngx_cycle_t *cycle)
408 {
409 int reuseaddr;
410 ngx_uint_t i, tries, failed;
411 ngx_err_t err;
412 ngx_log_t *log;
413 ngx_socket_t s;
414 ngx_listening_t *ls;
415
416 reuseaddr = 1;
417 #if (NGX_SUPPRESS_WARN)
418 failed = 0;
419 #endif
420
421 log = cycle->log;
422
423 /* TODO: configurable try number */
424
425 for (tries = 5; tries; tries--) {
426 failed = 0;
427
428 /* for each listening socket */
429
430 ls = cycle->listening.elts;
431 for (i = 0; i < cycle->listening.nelts; i++) {
432
433 if (ls[i].ignore) {
434 continue;
435 }
436
437 #if (NGX_HAVE_REUSEPORT)
438
439 if (ls[i].add_reuseport) {
440
441 /*
442 * to allow transition from a socket without SO_REUSEPORT
443 * to multiple sockets with SO_REUSEPORT, we have to set
444 * SO_REUSEPORT on the old socket before opening new ones
445 */
446
447 int reuseport = 1;
448
449 #ifdef SO_REUSEPORT_LB
450
451 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT_LB,
452 (const void *) &reuseport, sizeof(int))
453 == -1)
454 {
455 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
456 "setsockopt(SO_REUSEPORT_LB) %V failed, "
457 "ignored",
458 &ls[i].addr_text);
459 }
460
461 #else
462
463 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
464 (const void *) &reuseport, sizeof(int))
465 == -1)
466 {
467 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
468 "setsockopt(SO_REUSEPORT) %V failed, ignored",
469 &ls[i].addr_text);
470 }
471 #endif
472
473 ls[i].add_reuseport = 0;
474 }
475 #endif
476
477 if (ls[i].fd != (ngx_socket_t) -1) {
478 continue;
479 }
480
481 if (ls[i].inherited) {
482
483 /* TODO: close on exit */
484 /* TODO: nonblocking */
485 /* TODO: deferred accept */
486
487 continue;
488 }
489
490 s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
491
492 if (s == (ngx_socket_t) -1) {
493 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
494 ngx_socket_n " %V failed", &ls[i].addr_text);
495 return NGX_ERROR;
496 }
497
498 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
499 (const void *) &reuseaddr, sizeof(int))
500 == -1)
501 {
502 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
503 "setsockopt(SO_REUSEADDR) %V failed",
504 &ls[i].addr_text);
505
506 if (ngx_close_socket(s) == -1) {
507 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
508 ngx_close_socket_n " %V failed",
509 &ls[i].addr_text);
510 }
511
512 return NGX_ERROR;
513 }
514
515 #if (NGX_HAVE_REUSEPORT)
516
517 if (ls[i].reuseport && !ngx_test_config) {
518 int reuseport;
519
520 reuseport = 1;
521
522 #ifdef SO_REUSEPORT_LB
523
524 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB,
525 (const void *) &reuseport, sizeof(int))
526 == -1)
527 {
528 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
529 "setsockopt(SO_REUSEPORT_LB) %V failed",
530 &ls[i].addr_text);
531
532 if (ngx_close_socket(s) == -1) {
533 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
534 ngx_close_socket_n " %V failed",
535 &ls[i].addr_text);
536 }
537
538 return NGX_ERROR;
539 }
540
541 #else
542
543 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
544 (const void *) &reuseport, sizeof(int))
545 == -1)
546 {
547 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
548 "setsockopt(SO_REUSEPORT) %V failed",
549 &ls[i].addr_text);
550
551 if (ngx_close_socket(s) == -1) {
552 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
553 ngx_close_socket_n " %V failed",
554 &ls[i].addr_text);
555 }
556
557 return NGX_ERROR;
558 }
559 #endif
560 }
561 #endif
562
563 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
564
565 if (ls[i].sockaddr->sa_family == AF_INET6) {
566 int ipv6only;
567
568 ipv6only = ls[i].ipv6only;
569
570 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
571 (const void *) &ipv6only, sizeof(int))
572 == -1)
573 {
574 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
575 "setsockopt(IPV6_V6ONLY) %V failed, ignored",
576 &ls[i].addr_text);
577 }
578 }
579 #endif
580 /* TODO: close on exit */
581
582 if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
583 if (ngx_nonblocking(s) == -1) {
584 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
585 ngx_nonblocking_n " %V failed",
586 &ls[i].addr_text);
587
588 if (ngx_close_socket(s) == -1) {
589 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
590 ngx_close_socket_n " %V failed",
591 &ls[i].addr_text);
592 }
593
594 return NGX_ERROR;
595 }
596 }
597
598 ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
599 "bind() %V #%d ", &ls[i].addr_text, s);
600
601 if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
602 err = ngx_socket_errno;
603
604 if (err != NGX_EADDRINUSE || !ngx_test_config) {
605 ngx_log_error(NGX_LOG_EMERG, log, err,
606 "bind() to %V failed", &ls[i].addr_text);
607 }
608
609 if (ngx_close_socket(s) == -1) {
610 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
611 ngx_close_socket_n " %V failed",
612 &ls[i].addr_text);
613 }
614
615 if (err != NGX_EADDRINUSE) {
616 return NGX_ERROR;
617 }
618
619 if (!ngx_test_config) {
620 failed = 1;
621 }
622
623 continue;
624 }
625
626 #if (NGX_HAVE_UNIX_DOMAIN)
627
628 if (ls[i].sockaddr->sa_family == AF_UNIX) {
629 mode_t mode;
630 u_char *name;
631
632 name = ls[i].addr_text.data + sizeof("unix:") - 1;
633 mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
634
635 if (chmod((char *) name, mode) == -1) {
636 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
637 "chmod() \"%s\" failed", name);
638 }
639
640 if (ngx_test_config) {
641 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
642 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
643 ngx_delete_file_n " %s failed", name);
644 }
645 }
646 }
647 #endif
648
649 if (ls[i].type != SOCK_STREAM) {
650 ls[i].fd = s;
651 continue;
652 }
653
654 if (listen(s, ls[i].backlog) == -1) {
655 err = ngx_socket_errno;
656
657 /*
658 * on OpenVZ after suspend/resume EADDRINUSE
659 * may be returned by listen() instead of bind(), see
660 * https://bugzilla.openvz.org/show_bug.cgi?id=2470
661 */
662
663 if (err != NGX_EADDRINUSE || !ngx_test_config) {
664 ngx_log_error(NGX_LOG_EMERG, log, err,
665 "listen() to %V, backlog %d failed",
666 &ls[i].addr_text, ls[i].backlog);
667 }
668
669 if (ngx_close_socket(s) == -1) {
670 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
671 ngx_close_socket_n " %V failed",
672 &ls[i].addr_text);
673 }
674
675 if (err != NGX_EADDRINUSE) {
676 return NGX_ERROR;
677 }
678
679 if (!ngx_test_config) {
680 failed = 1;
681 }
682
683 continue;
684 }
685
686 ls[i].listen = 1;
687
688 ls[i].fd = s;
689 }
690
691 if (!failed) {
692 break;
693 }
694
695 /* TODO: delay configurable */
696
697 ngx_log_error(NGX_LOG_NOTICE, log, 0,
698 "try again to bind() after 500ms");
699
700 ngx_msleep(500);
701 }
702
703 if (failed) {
704 ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
705 return NGX_ERROR;
706 }
707
708 return NGX_OK;
709 }
710
711
712 void
ngx_configure_listening_sockets(ngx_cycle_t * cycle)713 ngx_configure_listening_sockets(ngx_cycle_t *cycle)
714 {
715 int value;
716 ngx_uint_t i;
717 ngx_listening_t *ls;
718
719 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
720 struct accept_filter_arg af;
721 #endif
722
723 ls = cycle->listening.elts;
724 for (i = 0; i < cycle->listening.nelts; i++) {
725
726 ls[i].log = *ls[i].logp;
727
728 if (ls[i].rcvbuf != -1) {
729 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
730 (const void *) &ls[i].rcvbuf, sizeof(int))
731 == -1)
732 {
733 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
734 "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
735 ls[i].rcvbuf, &ls[i].addr_text);
736 }
737 }
738
739 if (ls[i].sndbuf != -1) {
740 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
741 (const void *) &ls[i].sndbuf, sizeof(int))
742 == -1)
743 {
744 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
745 "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
746 ls[i].sndbuf, &ls[i].addr_text);
747 }
748 }
749
750 if (ls[i].keepalive) {
751 value = (ls[i].keepalive == 1) ? 1 : 0;
752
753 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
754 (const void *) &value, sizeof(int))
755 == -1)
756 {
757 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
758 "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
759 value, &ls[i].addr_text);
760 }
761 }
762
763 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
764
765 if (ls[i].keepidle) {
766 value = ls[i].keepidle;
767
768 #if (NGX_KEEPALIVE_FACTOR)
769 value *= NGX_KEEPALIVE_FACTOR;
770 #endif
771
772 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
773 (const void *) &value, sizeof(int))
774 == -1)
775 {
776 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
777 "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
778 value, &ls[i].addr_text);
779 }
780 }
781
782 if (ls[i].keepintvl) {
783 value = ls[i].keepintvl;
784
785 #if (NGX_KEEPALIVE_FACTOR)
786 value *= NGX_KEEPALIVE_FACTOR;
787 #endif
788
789 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
790 (const void *) &value, sizeof(int))
791 == -1)
792 {
793 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
794 "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
795 value, &ls[i].addr_text);
796 }
797 }
798
799 if (ls[i].keepcnt) {
800 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
801 (const void *) &ls[i].keepcnt, sizeof(int))
802 == -1)
803 {
804 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
805 "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
806 ls[i].keepcnt, &ls[i].addr_text);
807 }
808 }
809
810 #endif
811
812 #if (NGX_HAVE_SETFIB)
813 if (ls[i].setfib != -1) {
814 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
815 (const void *) &ls[i].setfib, sizeof(int))
816 == -1)
817 {
818 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
819 "setsockopt(SO_SETFIB, %d) %V failed, ignored",
820 ls[i].setfib, &ls[i].addr_text);
821 }
822 }
823 #endif
824
825 #if (NGX_HAVE_TCP_FASTOPEN)
826 if (ls[i].fastopen != -1) {
827 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
828 (const void *) &ls[i].fastopen, sizeof(int))
829 == -1)
830 {
831 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
832 "setsockopt(TCP_FASTOPEN, %d) %V failed, ignored",
833 ls[i].fastopen, &ls[i].addr_text);
834 }
835 }
836 #endif
837
838 #if 0
839 if (1) {
840 int tcp_nodelay = 1;
841
842 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
843 (const void *) &tcp_nodelay, sizeof(int))
844 == -1)
845 {
846 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
847 "setsockopt(TCP_NODELAY) %V failed, ignored",
848 &ls[i].addr_text);
849 }
850 }
851 #endif
852
853 if (ls[i].listen) {
854
855 /* change backlog via listen() */
856
857 if (listen(ls[i].fd, ls[i].backlog) == -1) {
858 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
859 "listen() to %V, backlog %d failed, ignored",
860 &ls[i].addr_text, ls[i].backlog);
861 }
862 }
863
864 /*
865 * setting deferred mode should be last operation on socket,
866 * because code may prematurely continue cycle on failure
867 */
868
869 #if (NGX_HAVE_DEFERRED_ACCEPT)
870
871 #ifdef SO_ACCEPTFILTER
872
873 if (ls[i].delete_deferred) {
874 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
875 == -1)
876 {
877 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
878 "setsockopt(SO_ACCEPTFILTER, NULL) "
879 "for %V failed, ignored",
880 &ls[i].addr_text);
881
882 if (ls[i].accept_filter) {
883 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
884 "could not change the accept filter "
885 "to \"%s\" for %V, ignored",
886 ls[i].accept_filter, &ls[i].addr_text);
887 }
888
889 continue;
890 }
891
892 ls[i].deferred_accept = 0;
893 }
894
895 if (ls[i].add_deferred) {
896 ngx_memzero(&af, sizeof(struct accept_filter_arg));
897 (void) ngx_cpystrn((u_char *) af.af_name,
898 (u_char *) ls[i].accept_filter, 16);
899
900 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
901 &af, sizeof(struct accept_filter_arg))
902 == -1)
903 {
904 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
905 "setsockopt(SO_ACCEPTFILTER, \"%s\") "
906 "for %V failed, ignored",
907 ls[i].accept_filter, &ls[i].addr_text);
908 continue;
909 }
910
911 ls[i].deferred_accept = 1;
912 }
913
914 #endif
915
916 #ifdef TCP_DEFER_ACCEPT
917
918 if (ls[i].add_deferred || ls[i].delete_deferred) {
919
920 if (ls[i].add_deferred) {
921 /*
922 * There is no way to find out how long a connection was
923 * in queue (and a connection may bypass deferred queue at all
924 * if syncookies were used), hence we use 1 second timeout
925 * here.
926 */
927 value = 1;
928
929 } else {
930 value = 0;
931 }
932
933 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
934 &value, sizeof(int))
935 == -1)
936 {
937 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
938 "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
939 "ignored",
940 value, &ls[i].addr_text);
941
942 continue;
943 }
944 }
945
946 if (ls[i].add_deferred) {
947 ls[i].deferred_accept = 1;
948 }
949
950 #endif
951
952 #endif /* NGX_HAVE_DEFERRED_ACCEPT */
953
954 #if (NGX_HAVE_IP_RECVDSTADDR)
955
956 if (ls[i].wildcard
957 && ls[i].type == SOCK_DGRAM
958 && ls[i].sockaddr->sa_family == AF_INET)
959 {
960 value = 1;
961
962 if (setsockopt(ls[i].fd, IPPROTO_IP, IP_RECVDSTADDR,
963 (const void *) &value, sizeof(int))
964 == -1)
965 {
966 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
967 "setsockopt(IP_RECVDSTADDR) "
968 "for %V failed, ignored",
969 &ls[i].addr_text);
970 }
971 }
972
973 #elif (NGX_HAVE_IP_PKTINFO)
974
975 if (ls[i].wildcard
976 && ls[i].type == SOCK_DGRAM
977 && ls[i].sockaddr->sa_family == AF_INET)
978 {
979 value = 1;
980
981 if (setsockopt(ls[i].fd, IPPROTO_IP, IP_PKTINFO,
982 (const void *) &value, sizeof(int))
983 == -1)
984 {
985 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
986 "setsockopt(IP_PKTINFO) "
987 "for %V failed, ignored",
988 &ls[i].addr_text);
989 }
990 }
991
992 #endif
993
994 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
995
996 if (ls[i].wildcard
997 && ls[i].type == SOCK_DGRAM
998 && ls[i].sockaddr->sa_family == AF_INET6)
999 {
1000 value = 1;
1001
1002 if (setsockopt(ls[i].fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
1003 (const void *) &value, sizeof(int))
1004 == -1)
1005 {
1006 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
1007 "setsockopt(IPV6_RECVPKTINFO) "
1008 "for %V failed, ignored",
1009 &ls[i].addr_text);
1010 }
1011 }
1012
1013 #endif
1014 }
1015
1016 return;
1017 }
1018
1019
1020 void
ngx_close_listening_sockets(ngx_cycle_t * cycle)1021 ngx_close_listening_sockets(ngx_cycle_t *cycle)
1022 {
1023 ngx_uint_t i;
1024 ngx_listening_t *ls;
1025 ngx_connection_t *c;
1026
1027 if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
1028 return;
1029 }
1030
1031 ngx_accept_mutex_held = 0;
1032 ngx_use_accept_mutex = 0;
1033
1034 ls = cycle->listening.elts;
1035 for (i = 0; i < cycle->listening.nelts; i++) {
1036
1037 c = ls[i].connection;
1038
1039 if (c) {
1040 if (c->read->active) {
1041 if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
1042
1043 /*
1044 * it seems that Linux-2.6.x OpenVZ sends events
1045 * for closed shared listening sockets unless
1046 * the events was explicitly deleted
1047 */
1048
1049 ngx_del_event(c->read, NGX_READ_EVENT, 0);
1050
1051 } else {
1052 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1053 }
1054 }
1055
1056 ngx_free_connection(c);
1057
1058 c->fd = (ngx_socket_t) -1;
1059 }
1060
1061 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
1062 "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
1063
1064 if (ngx_close_socket(ls[i].fd) == -1) {
1065 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1066 ngx_close_socket_n " %V failed", &ls[i].addr_text);
1067 }
1068
1069 #if (NGX_HAVE_UNIX_DOMAIN)
1070
1071 if (ls[i].sockaddr->sa_family == AF_UNIX
1072 && ngx_process <= NGX_PROCESS_MASTER
1073 && ngx_new_binary == 0
1074 && (!ls[i].inherited || ngx_getppid() != ngx_parent))
1075 {
1076 u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
1077
1078 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1079 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1080 ngx_delete_file_n " %s failed", name);
1081 }
1082 }
1083
1084 #endif
1085
1086 ls[i].fd = (ngx_socket_t) -1;
1087 }
1088
1089 cycle->listening.nelts = 0;
1090 }
1091
1092
1093 ngx_connection_t *
ngx_get_connection(ngx_socket_t s,ngx_log_t * log)1094 ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
1095 {
1096 ngx_uint_t instance;
1097 ngx_event_t *rev, *wev;
1098 ngx_connection_t *c;
1099
1100 /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
1101
1102 if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
1103 ngx_log_error(NGX_LOG_ALERT, log, 0,
1104 "the new socket has number %d, "
1105 "but only %ui files are available",
1106 s, ngx_cycle->files_n);
1107 return NULL;
1108 }
1109
1110 ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
1111
1112 c = ngx_cycle->free_connections;
1113
1114 if (c == NULL) {
1115 ngx_log_error(NGX_LOG_ALERT, log, 0,
1116 "%ui worker_connections are not enough",
1117 ngx_cycle->connection_n);
1118
1119 return NULL;
1120 }
1121
1122 ngx_cycle->free_connections = c->data;
1123 ngx_cycle->free_connection_n--;
1124
1125 if (ngx_cycle->files && ngx_cycle->files[s] == NULL) {
1126 ngx_cycle->files[s] = c;
1127 }
1128
1129 rev = c->read;
1130 wev = c->write;
1131
1132 ngx_memzero(c, sizeof(ngx_connection_t));
1133
1134 c->read = rev;
1135 c->write = wev;
1136 c->fd = s;
1137 c->log = log;
1138
1139 instance = rev->instance;
1140
1141 ngx_memzero(rev, sizeof(ngx_event_t));
1142 ngx_memzero(wev, sizeof(ngx_event_t));
1143
1144 rev->instance = !instance;
1145 wev->instance = !instance;
1146
1147 rev->index = NGX_INVALID_INDEX;
1148 wev->index = NGX_INVALID_INDEX;
1149
1150 rev->data = c;
1151 wev->data = c;
1152
1153 wev->write = 1;
1154
1155 return c;
1156 }
1157
1158
1159 void
ngx_free_connection(ngx_connection_t * c)1160 ngx_free_connection(ngx_connection_t *c)
1161 {
1162 c->data = ngx_cycle->free_connections;
1163 ngx_cycle->free_connections = c;
1164 ngx_cycle->free_connection_n++;
1165
1166 if (ngx_cycle->files && ngx_cycle->files[c->fd] == c) {
1167 ngx_cycle->files[c->fd] = NULL;
1168 }
1169 }
1170
1171
1172 void
ngx_close_connection(ngx_connection_t * c)1173 ngx_close_connection(ngx_connection_t *c)
1174 {
1175 ngx_err_t err;
1176 ngx_uint_t log_error, level;
1177 ngx_socket_t fd;
1178
1179 if (c->fd == (ngx_socket_t) -1) {
1180 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
1181 return;
1182 }
1183
1184 if (c->read->timer_set) {
1185 ngx_del_timer(c->read);
1186 }
1187
1188 if (c->write->timer_set) {
1189 ngx_del_timer(c->write);
1190 }
1191
1192 if (!c->shared) {
1193 if (ngx_del_conn) {
1194 ngx_del_conn(c, NGX_CLOSE_EVENT);
1195
1196 } else {
1197 if (c->read->active || c->read->disabled) {
1198 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1199 }
1200
1201 if (c->write->active || c->write->disabled) {
1202 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
1203 }
1204 }
1205 }
1206
1207 if (c->read->posted) {
1208 ngx_delete_posted_event(c->read);
1209 }
1210
1211 if (c->write->posted) {
1212 ngx_delete_posted_event(c->write);
1213 }
1214
1215 c->read->closed = 1;
1216 c->write->closed = 1;
1217
1218 ngx_reusable_connection(c, 0);
1219
1220 log_error = c->log_error;
1221
1222 ngx_free_connection(c);
1223
1224 fd = c->fd;
1225 c->fd = (ngx_socket_t) -1;
1226
1227 if (c->shared) {
1228 return;
1229 }
1230
1231 if (ngx_close_socket(fd) == -1) {
1232
1233 err = ngx_socket_errno;
1234
1235 if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
1236
1237 switch (log_error) {
1238
1239 case NGX_ERROR_INFO:
1240 level = NGX_LOG_INFO;
1241 break;
1242
1243 case NGX_ERROR_ERR:
1244 level = NGX_LOG_ERR;
1245 break;
1246
1247 default:
1248 level = NGX_LOG_CRIT;
1249 }
1250
1251 } else {
1252 level = NGX_LOG_CRIT;
1253 }
1254
1255 ngx_log_error(level, c->log, err, ngx_close_socket_n " %d failed", fd);
1256 }
1257 }
1258
1259
1260 void
ngx_reusable_connection(ngx_connection_t * c,ngx_uint_t reusable)1261 ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
1262 {
1263 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
1264 "reusable connection: %ui", reusable);
1265
1266 if (c->reusable) {
1267 ngx_queue_remove(&c->queue);
1268 ngx_cycle->reusable_connections_n--;
1269
1270 #if (NGX_STAT_STUB)
1271 (void) ngx_atomic_fetch_add(ngx_stat_waiting, -1);
1272 #endif
1273 }
1274
1275 c->reusable = reusable;
1276
1277 if (reusable) {
1278 /* need cast as ngx_cycle is volatile */
1279
1280 ngx_queue_insert_head(
1281 (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
1282 ngx_cycle->reusable_connections_n++;
1283
1284 #if (NGX_STAT_STUB)
1285 (void) ngx_atomic_fetch_add(ngx_stat_waiting, 1);
1286 #endif
1287 }
1288 }
1289
1290
1291 static void
ngx_drain_connections(ngx_cycle_t * cycle)1292 ngx_drain_connections(ngx_cycle_t *cycle)
1293 {
1294 ngx_uint_t i, n;
1295 ngx_queue_t *q;
1296 ngx_connection_t *c;
1297
1298 if (cycle->free_connection_n > cycle->connection_n / 16
1299 || cycle->reusable_connections_n == 0)
1300 {
1301 return;
1302 }
1303
1304 if (cycle->connections_reuse_time != ngx_time()) {
1305 cycle->connections_reuse_time = ngx_time();
1306
1307 ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
1308 "%ui worker_connections are not enough, "
1309 "reusing connections",
1310 cycle->connection_n);
1311 }
1312
1313 c = NULL;
1314 n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
1315
1316 for (i = 0; i < n; i++) {
1317 if (ngx_queue_empty(&cycle->reusable_connections_queue)) {
1318 break;
1319 }
1320
1321 q = ngx_queue_last(&cycle->reusable_connections_queue);
1322 c = ngx_queue_data(q, ngx_connection_t, queue);
1323
1324 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
1325 "reusing connection");
1326
1327 c->close = 1;
1328 c->read->handler(c->read);
1329 }
1330
1331 if (cycle->free_connection_n == 0 && c && c->reusable) {
1332
1333 /*
1334 * if no connections were freed, try to reuse the last
1335 * connection again: this should free it as long as
1336 * previous reuse moved it to lingering close
1337 */
1338
1339 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
1340 "reusing connection again");
1341
1342 c->close = 1;
1343 c->read->handler(c->read);
1344 }
1345 }
1346
1347
1348 void
ngx_close_idle_connections(ngx_cycle_t * cycle)1349 ngx_close_idle_connections(ngx_cycle_t *cycle)
1350 {
1351 ngx_uint_t i;
1352 ngx_connection_t *c;
1353
1354 c = cycle->connections;
1355
1356 for (i = 0; i < cycle->connection_n; i++) {
1357
1358 /* THREAD: lock */
1359
1360 if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
1361 c[i].close = 1;
1362 c[i].read->handler(c[i].read);
1363 }
1364 }
1365 }
1366
1367
1368 ngx_int_t
ngx_connection_local_sockaddr(ngx_connection_t * c,ngx_str_t * s,ngx_uint_t port)1369 ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
1370 ngx_uint_t port)
1371 {
1372 socklen_t len;
1373 ngx_uint_t addr;
1374 ngx_sockaddr_t sa;
1375 struct sockaddr_in *sin;
1376 #if (NGX_HAVE_INET6)
1377 ngx_uint_t i;
1378 struct sockaddr_in6 *sin6;
1379 #endif
1380
1381 addr = 0;
1382
1383 if (c->local_socklen) {
1384 switch (c->local_sockaddr->sa_family) {
1385
1386 #if (NGX_HAVE_INET6)
1387 case AF_INET6:
1388 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
1389
1390 for (i = 0; addr == 0 && i < 16; i++) {
1391 addr |= sin6->sin6_addr.s6_addr[i];
1392 }
1393
1394 break;
1395 #endif
1396
1397 #if (NGX_HAVE_UNIX_DOMAIN)
1398 case AF_UNIX:
1399 addr = 1;
1400 break;
1401 #endif
1402
1403 default: /* AF_INET */
1404 sin = (struct sockaddr_in *) c->local_sockaddr;
1405 addr = sin->sin_addr.s_addr;
1406 break;
1407 }
1408 }
1409
1410 if (addr == 0) {
1411
1412 len = sizeof(ngx_sockaddr_t);
1413
1414 if (getsockname(c->fd, &sa.sockaddr, &len) == -1) {
1415 ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1416 return NGX_ERROR;
1417 }
1418
1419 c->local_sockaddr = ngx_palloc(c->pool, len);
1420 if (c->local_sockaddr == NULL) {
1421 return NGX_ERROR;
1422 }
1423
1424 ngx_memcpy(c->local_sockaddr, &sa, len);
1425
1426 c->local_socklen = len;
1427 }
1428
1429 if (s == NULL) {
1430 return NGX_OK;
1431 }
1432
1433 s->len = ngx_sock_ntop(c->local_sockaddr, c->local_socklen,
1434 s->data, s->len, port);
1435
1436 return NGX_OK;
1437 }
1438
1439
1440 ngx_int_t
ngx_tcp_nodelay(ngx_connection_t * c)1441 ngx_tcp_nodelay(ngx_connection_t *c)
1442 {
1443 int tcp_nodelay;
1444
1445 if (c->tcp_nodelay != NGX_TCP_NODELAY_UNSET) {
1446 return NGX_OK;
1447 }
1448
1449 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "tcp_nodelay");
1450
1451 tcp_nodelay = 1;
1452
1453 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1454 (const void *) &tcp_nodelay, sizeof(int))
1455 == -1)
1456 {
1457 #if (NGX_SOLARIS)
1458 if (c->log_error == NGX_ERROR_INFO) {
1459
1460 /* Solaris returns EINVAL if a socket has been shut down */
1461 c->log_error = NGX_ERROR_IGNORE_EINVAL;
1462
1463 ngx_connection_error(c, ngx_socket_errno,
1464 "setsockopt(TCP_NODELAY) failed");
1465
1466 c->log_error = NGX_ERROR_INFO;
1467
1468 return NGX_ERROR;
1469 }
1470 #endif
1471
1472 ngx_connection_error(c, ngx_socket_errno,
1473 "setsockopt(TCP_NODELAY) failed");
1474 return NGX_ERROR;
1475 }
1476
1477 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1478
1479 return NGX_OK;
1480 }
1481
1482
1483 ngx_int_t
ngx_connection_error(ngx_connection_t * c,ngx_err_t err,char * text)1484 ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
1485 {
1486 ngx_uint_t level;
1487
1488 /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
1489
1490 if ((err == NGX_ECONNRESET
1491 #if (NGX_WIN32)
1492 || err == NGX_ECONNABORTED
1493 #endif
1494 ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
1495 {
1496 return 0;
1497 }
1498
1499 #if (NGX_SOLARIS)
1500 if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
1501 return 0;
1502 }
1503 #endif
1504
1505 if (err == 0
1506 || err == NGX_ECONNRESET
1507 #if (NGX_WIN32)
1508 || err == NGX_ECONNABORTED
1509 #else
1510 || err == NGX_EPIPE
1511 #endif
1512 || err == NGX_ENOTCONN
1513 || err == NGX_ETIMEDOUT
1514 || err == NGX_ECONNREFUSED
1515 || err == NGX_ENETDOWN
1516 || err == NGX_ENETUNREACH
1517 || err == NGX_EHOSTDOWN
1518 || err == NGX_EHOSTUNREACH)
1519 {
1520 switch (c->log_error) {
1521
1522 case NGX_ERROR_IGNORE_EINVAL:
1523 case NGX_ERROR_IGNORE_ECONNRESET:
1524 case NGX_ERROR_INFO:
1525 level = NGX_LOG_INFO;
1526 break;
1527
1528 default:
1529 level = NGX_LOG_ERR;
1530 }
1531
1532 } else {
1533 level = NGX_LOG_ALERT;
1534 }
1535
1536 ngx_log_error(level, c->log, err, text);
1537
1538 return NGX_ERROR;
1539 }
1540