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