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