Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 ngx_os_io_t  ngx_io;
0014 
0015 
0016 static void ngx_drain_connections(ngx_cycle_t *cycle);
0017 
0018 
0019 ngx_listening_t *
0020 ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr,
0021     socklen_t socklen)
0022 {
0023     size_t            len;
0024     ngx_listening_t  *ls;
0025     struct sockaddr  *sa;
0026     u_char            text[NGX_SOCKADDR_STRLEN];
0027 
0028     ls = ngx_array_push(&cf->cycle->listening);
0029     if (ls == NULL) {
0030         return NULL;
0031     }
0032 
0033     ngx_memzero(ls, sizeof(ngx_listening_t));
0034 
0035     sa = ngx_palloc(cf->pool, socklen);
0036     if (sa == NULL) {
0037         return NULL;
0038     }
0039 
0040     ngx_memcpy(sa, sockaddr, socklen);
0041 
0042     ls->sockaddr = sa;
0043     ls->socklen = socklen;
0044 
0045     len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
0046     ls->addr_text.len = len;
0047 
0048     switch (ls->sockaddr->sa_family) {
0049 #if (NGX_HAVE_INET6)
0050     case AF_INET6:
0051         ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
0052         break;
0053 #endif
0054 #if (NGX_HAVE_UNIX_DOMAIN)
0055     case AF_UNIX:
0056         ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
0057         len++;
0058         break;
0059 #endif
0060     case AF_INET:
0061         ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
0062         break;
0063     default:
0064         ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
0065         break;
0066     }
0067 
0068     ls->addr_text.data = ngx_pnalloc(cf->pool, len);
0069     if (ls->addr_text.data == NULL) {
0070         return NULL;
0071     }
0072 
0073     ngx_memcpy(ls->addr_text.data, text, len);
0074 
0075 #if !(NGX_WIN32)
0076     ngx_rbtree_init(&ls->rbtree, &ls->sentinel, ngx_udp_rbtree_insert_value);
0077 #endif
0078 
0079     ls->fd = (ngx_socket_t) -1;
0080     ls->type = SOCK_STREAM;
0081 
0082     ls->backlog = NGX_LISTEN_BACKLOG;
0083     ls->rcvbuf = -1;
0084     ls->sndbuf = -1;
0085 
0086 #if (NGX_HAVE_SETFIB)
0087     ls->setfib = -1;
0088 #endif
0089 
0090 #if (NGX_HAVE_TCP_FASTOPEN)
0091     ls->fastopen = -1;
0092 #endif
0093 
0094     return ls;
0095 }
0096 
0097 
0098 ngx_int_t
0099 ngx_clone_listening(ngx_cycle_t *cycle, ngx_listening_t *ls)
0100 {
0101 #if (NGX_HAVE_REUSEPORT)
0102 
0103     ngx_int_t         n;
0104     ngx_core_conf_t  *ccf;
0105     ngx_listening_t   ols;
0106 
0107     if (!ls->reuseport || ls->worker != 0) {
0108         return NGX_OK;
0109     }
0110 
0111     ols = *ls;
0112 
0113     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
0114 
0115     for (n = 1; n < ccf->worker_processes; n++) {
0116 
0117         /* create a socket for each worker process */
0118 
0119         ls = ngx_array_push(&cycle->listening);
0120         if (ls == NULL) {
0121             return NGX_ERROR;
0122         }
0123 
0124         *ls = ols;
0125         ls->worker = n;
0126     }
0127 
0128 #endif
0129 
0130     return NGX_OK;
0131 }
0132 
0133 
0134 ngx_int_t
0135 ngx_set_inherited_sockets(ngx_cycle_t *cycle)
0136 {
0137     size_t                     len;
0138     ngx_uint_t                 i;
0139     ngx_listening_t           *ls;
0140     socklen_t                  olen;
0141 #if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
0142     ngx_err_t                  err;
0143 #endif
0144 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
0145     struct accept_filter_arg   af;
0146 #endif
0147 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
0148     int                        timeout;
0149 #endif
0150 #if (NGX_HAVE_REUSEPORT)
0151     int                        reuseport;
0152 #endif
0153 
0154     ls = cycle->listening.elts;
0155     for (i = 0; i < cycle->listening.nelts; i++) {
0156 
0157         ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t));
0158         if (ls[i].sockaddr == NULL) {
0159             return NGX_ERROR;
0160         }
0161 
0162         ls[i].socklen = sizeof(ngx_sockaddr_t);
0163         if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
0164             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
0165                           "getsockname() of the inherited "
0166                           "socket #%d failed", ls[i].fd);
0167             ls[i].ignore = 1;
0168             continue;
0169         }
0170 
0171         if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
0172             ls[i].socklen = sizeof(ngx_sockaddr_t);
0173         }
0174 
0175         switch (ls[i].sockaddr->sa_family) {
0176 
0177 #if (NGX_HAVE_INET6)
0178         case AF_INET6:
0179             ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
0180             len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
0181             break;
0182 #endif
0183 
0184 #if (NGX_HAVE_UNIX_DOMAIN)
0185         case AF_UNIX:
0186             ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
0187             len = NGX_UNIX_ADDRSTRLEN;
0188             break;
0189 #endif
0190 
0191         case AF_INET:
0192             ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
0193             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
0194             break;
0195 
0196         default:
0197             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
0198                           "the inherited socket #%d has "
0199                           "an unsupported protocol family", ls[i].fd);
0200             ls[i].ignore = 1;
0201             continue;
0202         }
0203 
0204         ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
0205         if (ls[i].addr_text.data == NULL) {
0206             return NGX_ERROR;
0207         }
0208 
0209         len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
0210                             ls[i].addr_text.data, len, 1);
0211         if (len == 0) {
0212             return NGX_ERROR;
0213         }
0214 
0215         ls[i].addr_text.len = len;
0216 
0217         ls[i].backlog = NGX_LISTEN_BACKLOG;
0218 
0219         olen = sizeof(int);
0220 
0221         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_TYPE, (void *) &ls[i].type,
0222                        &olen)
0223             == -1)
0224         {
0225             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
0226                           "getsockopt(SO_TYPE) %V failed", &ls[i].addr_text);
0227             ls[i].ignore = 1;
0228             continue;
0229         }
0230 
0231         olen = sizeof(int);
0232 
0233         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
0234                        &olen)
0235             == -1)
0236         {
0237             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0238                           "getsockopt(SO_RCVBUF) %V failed, ignored",
0239                           &ls[i].addr_text);
0240 
0241             ls[i].rcvbuf = -1;
0242         }
0243 
0244         olen = sizeof(int);
0245 
0246         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
0247                        &olen)
0248             == -1)
0249         {
0250             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0251                           "getsockopt(SO_SNDBUF) %V failed, ignored",
0252                           &ls[i].addr_text);
0253 
0254             ls[i].sndbuf = -1;
0255         }
0256 
0257 #if 0
0258         /* SO_SETFIB is currently a set only option */
0259 
0260 #if (NGX_HAVE_SETFIB)
0261 
0262         olen = sizeof(int);
0263 
0264         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
0265                        (void *) &ls[i].setfib, &olen)
0266             == -1)
0267         {
0268             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0269                           "getsockopt(SO_SETFIB) %V failed, ignored",
0270                           &ls[i].addr_text);
0271 
0272             ls[i].setfib = -1;
0273         }
0274 
0275 #endif
0276 #endif
0277 
0278 #if (NGX_HAVE_REUSEPORT)
0279 
0280         reuseport = 0;
0281         olen = sizeof(int);
0282 
0283 #ifdef SO_REUSEPORT_LB
0284 
0285         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT_LB,
0286                        (void *) &reuseport, &olen)
0287             == -1)
0288         {
0289             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0290                           "getsockopt(SO_REUSEPORT_LB) %V failed, ignored",
0291                           &ls[i].addr_text);
0292 
0293         } else {
0294             ls[i].reuseport = reuseport ? 1 : 0;
0295         }
0296 
0297 #else
0298 
0299         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
0300                        (void *) &reuseport, &olen)
0301             == -1)
0302         {
0303             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0304                           "getsockopt(SO_REUSEPORT) %V failed, ignored",
0305                           &ls[i].addr_text);
0306 
0307         } else {
0308             ls[i].reuseport = reuseport ? 1 : 0;
0309         }
0310 #endif
0311 
0312 #endif
0313 
0314         if (ls[i].type != SOCK_STREAM) {
0315             continue;
0316         }
0317 
0318 #if (NGX_HAVE_TCP_FASTOPEN)
0319 
0320         olen = sizeof(int);
0321 
0322         if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
0323                        (void *) &ls[i].fastopen, &olen)
0324             == -1)
0325         {
0326             err = ngx_socket_errno;
0327 
0328             if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT
0329                 && err != NGX_EINVAL)
0330             {
0331                 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
0332                               "getsockopt(TCP_FASTOPEN) %V failed, ignored",
0333                               &ls[i].addr_text);
0334             }
0335 
0336             ls[i].fastopen = -1;
0337         }
0338 
0339 #endif
0340 
0341 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
0342 
0343         ngx_memzero(&af, sizeof(struct accept_filter_arg));
0344         olen = sizeof(struct accept_filter_arg);
0345 
0346         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
0347             == -1)
0348         {
0349             err = ngx_socket_errno;
0350 
0351             if (err == NGX_EINVAL) {
0352                 continue;
0353             }
0354 
0355             ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
0356                           "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
0357                           &ls[i].addr_text);
0358             continue;
0359         }
0360 
0361         if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
0362             continue;
0363         }
0364 
0365         ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
0366         if (ls[i].accept_filter == NULL) {
0367             return NGX_ERROR;
0368         }
0369 
0370         (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
0371                            (u_char *) af.af_name, 16);
0372 #endif
0373 
0374 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
0375 
0376         timeout = 0;
0377         olen = sizeof(int);
0378 
0379         if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
0380             == -1)
0381         {
0382             err = ngx_socket_errno;
0383 
0384             if (err == NGX_EOPNOTSUPP) {
0385                 continue;
0386             }
0387 
0388             ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
0389                           "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
0390                           &ls[i].addr_text);
0391             continue;
0392         }
0393 
0394         if (olen < sizeof(int) || timeout == 0) {
0395             continue;
0396         }
0397 
0398         ls[i].deferred_accept = 1;
0399 #endif
0400     }
0401 
0402     return NGX_OK;
0403 }
0404 
0405 
0406 ngx_int_t
0407 ngx_open_listening_sockets(ngx_cycle_t *cycle)
0408 {
0409     int               reuseaddr;
0410     ngx_uint_t        i, tries, failed;
0411     ngx_err_t         err;
0412     ngx_log_t        *log;
0413     ngx_socket_t      s;
0414     ngx_listening_t  *ls;
0415 
0416     reuseaddr = 1;
0417 #if (NGX_SUPPRESS_WARN)
0418     failed = 0;
0419 #endif
0420 
0421     log = cycle->log;
0422 
0423     /* TODO: configurable try number */
0424 
0425     for (tries = 5; tries; tries--) {
0426         failed = 0;
0427 
0428         /* for each listening socket */
0429 
0430         ls = cycle->listening.elts;
0431         for (i = 0; i < cycle->listening.nelts; i++) {
0432 
0433             if (ls[i].ignore) {
0434                 continue;
0435             }
0436 
0437 #if (NGX_HAVE_REUSEPORT)
0438 
0439             if (ls[i].add_reuseport) {
0440 
0441                 /*
0442                  * to allow transition from a socket without SO_REUSEPORT
0443                  * to multiple sockets with SO_REUSEPORT, we have to set
0444                  * SO_REUSEPORT on the old socket before opening new ones
0445                  */
0446 
0447                 int  reuseport = 1;
0448 
0449 #ifdef SO_REUSEPORT_LB
0450 
0451                 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT_LB,
0452                                (const void *) &reuseport, sizeof(int))
0453                     == -1)
0454                 {
0455                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0456                                   "setsockopt(SO_REUSEPORT_LB) %V failed, "
0457                                   "ignored",
0458                                   &ls[i].addr_text);
0459                 }
0460 
0461 #else
0462 
0463                 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
0464                                (const void *) &reuseport, sizeof(int))
0465                     == -1)
0466                 {
0467                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0468                                   "setsockopt(SO_REUSEPORT) %V failed, ignored",
0469                                   &ls[i].addr_text);
0470                 }
0471 #endif
0472 
0473                 ls[i].add_reuseport = 0;
0474             }
0475 #endif
0476 
0477             if (ls[i].fd != (ngx_socket_t) -1) {
0478                 continue;
0479             }
0480 
0481             if (ls[i].inherited) {
0482 
0483                 /* TODO: close on exit */
0484                 /* TODO: nonblocking */
0485                 /* TODO: deferred accept */
0486 
0487                 continue;
0488             }
0489 
0490             s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
0491 
0492             if (s == (ngx_socket_t) -1) {
0493                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0494                               ngx_socket_n " %V failed", &ls[i].addr_text);
0495                 return NGX_ERROR;
0496             }
0497 
0498             if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
0499                            (const void *) &reuseaddr, sizeof(int))
0500                 == -1)
0501             {
0502                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0503                               "setsockopt(SO_REUSEADDR) %V failed",
0504                               &ls[i].addr_text);
0505 
0506                 if (ngx_close_socket(s) == -1) {
0507                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0508                                   ngx_close_socket_n " %V failed",
0509                                   &ls[i].addr_text);
0510                 }
0511 
0512                 return NGX_ERROR;
0513             }
0514 
0515 #if (NGX_HAVE_REUSEPORT)
0516 
0517             if (ls[i].reuseport && !ngx_test_config) {
0518                 int  reuseport;
0519 
0520                 reuseport = 1;
0521 
0522 #ifdef SO_REUSEPORT_LB
0523 
0524                 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB,
0525                                (const void *) &reuseport, sizeof(int))
0526                     == -1)
0527                 {
0528                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0529                                   "setsockopt(SO_REUSEPORT_LB) %V failed",
0530                                   &ls[i].addr_text);
0531 
0532                     if (ngx_close_socket(s) == -1) {
0533                         ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0534                                       ngx_close_socket_n " %V failed",
0535                                       &ls[i].addr_text);
0536                     }
0537 
0538                     return NGX_ERROR;
0539                 }
0540 
0541 #else
0542 
0543                 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
0544                                (const void *) &reuseport, sizeof(int))
0545                     == -1)
0546                 {
0547                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0548                                   "setsockopt(SO_REUSEPORT) %V failed",
0549                                   &ls[i].addr_text);
0550 
0551                     if (ngx_close_socket(s) == -1) {
0552                         ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0553                                       ngx_close_socket_n " %V failed",
0554                                       &ls[i].addr_text);
0555                     }
0556 
0557                     return NGX_ERROR;
0558                 }
0559 #endif
0560             }
0561 #endif
0562 
0563 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
0564 
0565             if (ls[i].sockaddr->sa_family == AF_INET6) {
0566                 int  ipv6only;
0567 
0568                 ipv6only = ls[i].ipv6only;
0569 
0570                 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
0571                                (const void *) &ipv6only, sizeof(int))
0572                     == -1)
0573                 {
0574                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0575                                   "setsockopt(IPV6_V6ONLY) %V failed, ignored",
0576                                   &ls[i].addr_text);
0577                 }
0578             }
0579 #endif
0580             /* TODO: close on exit */
0581 
0582             if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
0583                 if (ngx_nonblocking(s) == -1) {
0584                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0585                                   ngx_nonblocking_n " %V failed",
0586                                   &ls[i].addr_text);
0587 
0588                     if (ngx_close_socket(s) == -1) {
0589                         ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0590                                       ngx_close_socket_n " %V failed",
0591                                       &ls[i].addr_text);
0592                     }
0593 
0594                     return NGX_ERROR;
0595                 }
0596             }
0597 
0598             ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
0599                            "bind() %V #%d ", &ls[i].addr_text, s);
0600 
0601             if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
0602                 err = ngx_socket_errno;
0603 
0604                 if (err != NGX_EADDRINUSE || !ngx_test_config) {
0605                     ngx_log_error(NGX_LOG_EMERG, log, err,
0606                                   "bind() to %V failed", &ls[i].addr_text);
0607                 }
0608 
0609                 if (ngx_close_socket(s) == -1) {
0610                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0611                                   ngx_close_socket_n " %V failed",
0612                                   &ls[i].addr_text);
0613                 }
0614 
0615                 if (err != NGX_EADDRINUSE) {
0616                     return NGX_ERROR;
0617                 }
0618 
0619                 if (!ngx_test_config) {
0620                     failed = 1;
0621                 }
0622 
0623                 continue;
0624             }
0625 
0626 #if (NGX_HAVE_UNIX_DOMAIN)
0627 
0628             if (ls[i].sockaddr->sa_family == AF_UNIX) {
0629                 mode_t   mode;
0630                 u_char  *name;
0631 
0632                 name = ls[i].addr_text.data + sizeof("unix:") - 1;
0633                 mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
0634 
0635                 if (chmod((char *) name, mode) == -1) {
0636                     ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0637                                   "chmod() \"%s\" failed", name);
0638                 }
0639 
0640                 if (ngx_test_config) {
0641                     if (ngx_delete_file(name) == NGX_FILE_ERROR) {
0642                         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0643                                       ngx_delete_file_n " %s failed", name);
0644                     }
0645                 }
0646             }
0647 #endif
0648 
0649             if (ls[i].type != SOCK_STREAM) {
0650                 ls[i].fd = s;
0651                 continue;
0652             }
0653 
0654             if (listen(s, ls[i].backlog) == -1) {
0655                 err = ngx_socket_errno;
0656 
0657                 /*
0658                  * on OpenVZ after suspend/resume EADDRINUSE
0659                  * may be returned by listen() instead of bind(), see
0660                  * https://bugzilla.openvz.org/show_bug.cgi?id=2470
0661                  */
0662 
0663                 if (err != NGX_EADDRINUSE || !ngx_test_config) {
0664                     ngx_log_error(NGX_LOG_EMERG, log, err,
0665                                   "listen() to %V, backlog %d failed",
0666                                   &ls[i].addr_text, ls[i].backlog);
0667                 }
0668 
0669                 if (ngx_close_socket(s) == -1) {
0670                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
0671                                   ngx_close_socket_n " %V failed",
0672                                   &ls[i].addr_text);
0673                 }
0674 
0675                 if (err != NGX_EADDRINUSE) {
0676                     return NGX_ERROR;
0677                 }
0678 
0679                 if (!ngx_test_config) {
0680                     failed = 1;
0681                 }
0682 
0683                 continue;
0684             }
0685 
0686             ls[i].listen = 1;
0687 
0688             ls[i].fd = s;
0689         }
0690 
0691         if (!failed) {
0692             break;
0693         }
0694 
0695         /* TODO: delay configurable */
0696 
0697         ngx_log_error(NGX_LOG_NOTICE, log, 0,
0698                       "try again to bind() after 500ms");
0699 
0700         ngx_msleep(500);
0701     }
0702 
0703     if (failed) {
0704         ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
0705         return NGX_ERROR;
0706     }
0707 
0708     return NGX_OK;
0709 }
0710 
0711 
0712 void
0713 ngx_configure_listening_sockets(ngx_cycle_t *cycle)
0714 {
0715     int                        value;
0716     ngx_uint_t                 i;
0717     ngx_listening_t           *ls;
0718 
0719 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
0720     struct accept_filter_arg   af;
0721 #endif
0722 
0723     ls = cycle->listening.elts;
0724     for (i = 0; i < cycle->listening.nelts; i++) {
0725 
0726         ls[i].log = *ls[i].logp;
0727 
0728         if (ls[i].rcvbuf != -1) {
0729             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
0730                            (const void *) &ls[i].rcvbuf, sizeof(int))
0731                 == -1)
0732             {
0733                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0734                               "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
0735                               ls[i].rcvbuf, &ls[i].addr_text);
0736             }
0737         }
0738 
0739         if (ls[i].sndbuf != -1) {
0740             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
0741                            (const void *) &ls[i].sndbuf, sizeof(int))
0742                 == -1)
0743             {
0744                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0745                               "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
0746                               ls[i].sndbuf, &ls[i].addr_text);
0747             }
0748         }
0749 
0750         if (ls[i].keepalive) {
0751             value = (ls[i].keepalive == 1) ? 1 : 0;
0752 
0753             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
0754                            (const void *) &value, sizeof(int))
0755                 == -1)
0756             {
0757                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0758                               "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
0759                               value, &ls[i].addr_text);
0760             }
0761         }
0762 
0763 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0764 
0765         if (ls[i].keepidle) {
0766             value = ls[i].keepidle;
0767 
0768 #if (NGX_KEEPALIVE_FACTOR)
0769             value *= NGX_KEEPALIVE_FACTOR;
0770 #endif
0771 
0772             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
0773                            (const void *) &value, sizeof(int))
0774                 == -1)
0775             {
0776                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0777                               "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
0778                               value, &ls[i].addr_text);
0779             }
0780         }
0781 
0782         if (ls[i].keepintvl) {
0783             value = ls[i].keepintvl;
0784 
0785 #if (NGX_KEEPALIVE_FACTOR)
0786             value *= NGX_KEEPALIVE_FACTOR;
0787 #endif
0788 
0789             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
0790                            (const void *) &value, sizeof(int))
0791                 == -1)
0792             {
0793                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0794                              "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
0795                              value, &ls[i].addr_text);
0796             }
0797         }
0798 
0799         if (ls[i].keepcnt) {
0800             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
0801                            (const void *) &ls[i].keepcnt, sizeof(int))
0802                 == -1)
0803             {
0804                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0805                               "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
0806                               ls[i].keepcnt, &ls[i].addr_text);
0807             }
0808         }
0809 
0810 #endif
0811 
0812 #if (NGX_HAVE_SETFIB)
0813         if (ls[i].setfib != -1) {
0814             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
0815                            (const void *) &ls[i].setfib, sizeof(int))
0816                 == -1)
0817             {
0818                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0819                               "setsockopt(SO_SETFIB, %d) %V failed, ignored",
0820                               ls[i].setfib, &ls[i].addr_text);
0821             }
0822         }
0823 #endif
0824 
0825 #if (NGX_HAVE_TCP_FASTOPEN)
0826         if (ls[i].fastopen != -1) {
0827             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
0828                            (const void *) &ls[i].fastopen, sizeof(int))
0829                 == -1)
0830             {
0831                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0832                               "setsockopt(TCP_FASTOPEN, %d) %V failed, ignored",
0833                               ls[i].fastopen, &ls[i].addr_text);
0834             }
0835         }
0836 #endif
0837 
0838 #if 0
0839         if (1) {
0840             int tcp_nodelay = 1;
0841 
0842             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
0843                        (const void *) &tcp_nodelay, sizeof(int))
0844                 == -1)
0845             {
0846                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0847                               "setsockopt(TCP_NODELAY) %V failed, ignored",
0848                               &ls[i].addr_text);
0849             }
0850         }
0851 #endif
0852 
0853         if (ls[i].listen) {
0854 
0855             /* change backlog via listen() */
0856 
0857             if (listen(ls[i].fd, ls[i].backlog) == -1) {
0858                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0859                               "listen() to %V, backlog %d failed, ignored",
0860                               &ls[i].addr_text, ls[i].backlog);
0861             }
0862         }
0863 
0864         /*
0865          * setting deferred mode should be last operation on socket,
0866          * because code may prematurely continue cycle on failure
0867          */
0868 
0869 #if (NGX_HAVE_DEFERRED_ACCEPT)
0870 
0871 #ifdef SO_ACCEPTFILTER
0872 
0873         if (ls[i].delete_deferred) {
0874             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
0875                 == -1)
0876             {
0877                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0878                               "setsockopt(SO_ACCEPTFILTER, NULL) "
0879                               "for %V failed, ignored",
0880                               &ls[i].addr_text);
0881 
0882                 if (ls[i].accept_filter) {
0883                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0884                                   "could not change the accept filter "
0885                                   "to \"%s\" for %V, ignored",
0886                                   ls[i].accept_filter, &ls[i].addr_text);
0887                 }
0888 
0889                 continue;
0890             }
0891 
0892             ls[i].deferred_accept = 0;
0893         }
0894 
0895         if (ls[i].add_deferred) {
0896             ngx_memzero(&af, sizeof(struct accept_filter_arg));
0897             (void) ngx_cpystrn((u_char *) af.af_name,
0898                                (u_char *) ls[i].accept_filter, 16);
0899 
0900             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
0901                            &af, sizeof(struct accept_filter_arg))
0902                 == -1)
0903             {
0904                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0905                               "setsockopt(SO_ACCEPTFILTER, \"%s\") "
0906                               "for %V failed, ignored",
0907                               ls[i].accept_filter, &ls[i].addr_text);
0908                 continue;
0909             }
0910 
0911             ls[i].deferred_accept = 1;
0912         }
0913 
0914 #endif
0915 
0916 #ifdef TCP_DEFER_ACCEPT
0917 
0918         if (ls[i].add_deferred || ls[i].delete_deferred) {
0919 
0920             if (ls[i].add_deferred) {
0921                 /*
0922                  * There is no way to find out how long a connection was
0923                  * in queue (and a connection may bypass deferred queue at all
0924                  * if syncookies were used), hence we use 1 second timeout
0925                  * here.
0926                  */
0927                 value = 1;
0928 
0929             } else {
0930                 value = 0;
0931             }
0932 
0933             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
0934                            &value, sizeof(int))
0935                 == -1)
0936             {
0937                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0938                               "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
0939                               "ignored",
0940                               value, &ls[i].addr_text);
0941 
0942                 continue;
0943             }
0944         }
0945 
0946         if (ls[i].add_deferred) {
0947             ls[i].deferred_accept = 1;
0948         }
0949 
0950 #endif
0951 
0952 #endif /* NGX_HAVE_DEFERRED_ACCEPT */
0953 
0954 #if (NGX_HAVE_IP_RECVDSTADDR)
0955 
0956         if (ls[i].wildcard
0957             && ls[i].type == SOCK_DGRAM
0958             && ls[i].sockaddr->sa_family == AF_INET)
0959         {
0960             value = 1;
0961 
0962             if (setsockopt(ls[i].fd, IPPROTO_IP, IP_RECVDSTADDR,
0963                            (const void *) &value, sizeof(int))
0964                 == -1)
0965             {
0966                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0967                               "setsockopt(IP_RECVDSTADDR) "
0968                               "for %V failed, ignored",
0969                               &ls[i].addr_text);
0970             }
0971         }
0972 
0973 #elif (NGX_HAVE_IP_PKTINFO)
0974 
0975         if (ls[i].wildcard
0976             && ls[i].type == SOCK_DGRAM
0977             && ls[i].sockaddr->sa_family == AF_INET)
0978         {
0979             value = 1;
0980 
0981             if (setsockopt(ls[i].fd, IPPROTO_IP, IP_PKTINFO,
0982                            (const void *) &value, sizeof(int))
0983                 == -1)
0984             {
0985                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
0986                               "setsockopt(IP_PKTINFO) "
0987                               "for %V failed, ignored",
0988                               &ls[i].addr_text);
0989             }
0990         }
0991 
0992 #endif
0993 
0994 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
0995 
0996         if (ls[i].wildcard
0997             && ls[i].type == SOCK_DGRAM
0998             && ls[i].sockaddr->sa_family == AF_INET6)
0999         {
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
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         {
1075             u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
1076 
1077             if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1078                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1079                               ngx_delete_file_n " %s failed", name);
1080             }
1081         }
1082 
1083 #endif
1084 
1085         ls[i].fd = (ngx_socket_t) -1;
1086     }
1087 
1088     cycle->listening.nelts = 0;
1089 }
1090 
1091 
1092 ngx_connection_t *
1093 ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
1094 {
1095     ngx_uint_t         instance;
1096     ngx_event_t       *rev, *wev;
1097     ngx_connection_t  *c;
1098 
1099     /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
1100 
1101     if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
1102         ngx_log_error(NGX_LOG_ALERT, log, 0,
1103                       "the new socket has number %d, "
1104                       "but only %ui files are available",
1105                       s, ngx_cycle->files_n);
1106         return NULL;
1107     }
1108 
1109     c = ngx_cycle->free_connections;
1110 
1111     if (c == NULL) {
1112         ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
1113         c = ngx_cycle->free_connections;
1114     }
1115 
1116     if (c == NULL) {
1117         ngx_log_error(NGX_LOG_ALERT, log, 0,
1118                       "%ui worker_connections are not enough",
1119                       ngx_cycle->connection_n);
1120 
1121         return NULL;
1122     }
1123 
1124     ngx_cycle->free_connections = c->data;
1125     ngx_cycle->free_connection_n--;
1126 
1127     if (ngx_cycle->files && ngx_cycle->files[s] == NULL) {
1128         ngx_cycle->files[s] = c;
1129     }
1130 
1131     rev = c->read;
1132     wev = c->write;
1133 
1134     ngx_memzero(c, sizeof(ngx_connection_t));
1135 
1136     c->read = rev;
1137     c->write = wev;
1138     c->fd = s;
1139     c->log = log;
1140 
1141     instance = rev->instance;
1142 
1143     ngx_memzero(rev, sizeof(ngx_event_t));
1144     ngx_memzero(wev, sizeof(ngx_event_t));
1145 
1146     rev->instance = !instance;
1147     wev->instance = !instance;
1148 
1149     rev->index = NGX_INVALID_INDEX;
1150     wev->index = NGX_INVALID_INDEX;
1151 
1152     rev->data = c;
1153     wev->data = c;
1154 
1155     wev->write = 1;
1156 
1157     return c;
1158 }
1159 
1160 
1161 void
1162 ngx_free_connection(ngx_connection_t *c)
1163 {
1164     c->data = ngx_cycle->free_connections;
1165     ngx_cycle->free_connections = c;
1166     ngx_cycle->free_connection_n++;
1167 
1168     if (ngx_cycle->files && ngx_cycle->files[c->fd] == c) {
1169         ngx_cycle->files[c->fd] = NULL;
1170     }
1171 }
1172 
1173 
1174 void
1175 ngx_close_connection(ngx_connection_t *c)
1176 {
1177     ngx_err_t     err;
1178     ngx_uint_t    log_error, level;
1179     ngx_socket_t  fd;
1180 
1181     if (c->fd == (ngx_socket_t) -1) {
1182         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
1183         return;
1184     }
1185 
1186     if (c->read->timer_set) {
1187         ngx_del_timer(c->read);
1188     }
1189 
1190     if (c->write->timer_set) {
1191         ngx_del_timer(c->write);
1192     }
1193 
1194     if (!c->shared) {
1195         if (ngx_del_conn) {
1196             ngx_del_conn(c, NGX_CLOSE_EVENT);
1197 
1198         } else {
1199             if (c->read->active || c->read->disabled) {
1200                 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1201             }
1202 
1203             if (c->write->active || c->write->disabled) {
1204                 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
1205             }
1206         }
1207     }
1208 
1209     if (c->read->posted) {
1210         ngx_delete_posted_event(c->read);
1211     }
1212 
1213     if (c->write->posted) {
1214         ngx_delete_posted_event(c->write);
1215     }
1216 
1217     c->read->closed = 1;
1218     c->write->closed = 1;
1219 
1220     ngx_reusable_connection(c, 0);
1221 
1222     log_error = c->log_error;
1223 
1224     ngx_free_connection(c);
1225 
1226     fd = c->fd;
1227     c->fd = (ngx_socket_t) -1;
1228 
1229     if (c->shared) {
1230         return;
1231     }
1232 
1233     if (ngx_close_socket(fd) == -1) {
1234 
1235         err = ngx_socket_errno;
1236 
1237         if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
1238 
1239             switch (log_error) {
1240 
1241             case NGX_ERROR_INFO:
1242                 level = NGX_LOG_INFO;
1243                 break;
1244 
1245             case NGX_ERROR_ERR:
1246                 level = NGX_LOG_ERR;
1247                 break;
1248 
1249             default:
1250                 level = NGX_LOG_CRIT;
1251             }
1252 
1253         } else {
1254             level = NGX_LOG_CRIT;
1255         }
1256 
1257         ngx_log_error(level, c->log, err, ngx_close_socket_n " %d failed", fd);
1258     }
1259 }
1260 
1261 
1262 void
1263 ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
1264 {
1265     ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
1266                    "reusable connection: %ui", reusable);
1267 
1268     if (c->reusable) {
1269         ngx_queue_remove(&c->queue);
1270         ngx_cycle->reusable_connections_n--;
1271 
1272 #if (NGX_STAT_STUB)
1273         (void) ngx_atomic_fetch_add(ngx_stat_waiting, -1);
1274 #endif
1275     }
1276 
1277     c->reusable = reusable;
1278 
1279     if (reusable) {
1280         /* need cast as ngx_cycle is volatile */
1281 
1282         ngx_queue_insert_head(
1283             (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
1284         ngx_cycle->reusable_connections_n++;
1285 
1286 #if (NGX_STAT_STUB)
1287         (void) ngx_atomic_fetch_add(ngx_stat_waiting, 1);
1288 #endif
1289     }
1290 }
1291 
1292 
1293 static void
1294 ngx_drain_connections(ngx_cycle_t *cycle)
1295 {
1296     ngx_uint_t         i, n;
1297     ngx_queue_t       *q;
1298     ngx_connection_t  *c;
1299 
1300     n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
1301 
1302     for (i = 0; i < n; i++) {
1303         if (ngx_queue_empty(&cycle->reusable_connections_queue)) {
1304             break;
1305         }
1306 
1307         q = ngx_queue_last(&cycle->reusable_connections_queue);
1308         c = ngx_queue_data(q, ngx_connection_t, queue);
1309 
1310         ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
1311                        "reusing connection");
1312 
1313         c->close = 1;
1314         c->read->handler(c->read);
1315     }
1316 }
1317 
1318 
1319 void
1320 ngx_close_idle_connections(ngx_cycle_t *cycle)
1321 {
1322     ngx_uint_t         i;
1323     ngx_connection_t  *c;
1324 
1325     c = cycle->connections;
1326 
1327     for (i = 0; i < cycle->connection_n; i++) {
1328 
1329         /* THREAD: lock */
1330 
1331         if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
1332             c[i].close = 1;
1333             c[i].read->handler(c[i].read);
1334         }
1335     }
1336 }
1337 
1338 
1339 ngx_int_t
1340 ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
1341     ngx_uint_t port)
1342 {
1343     socklen_t             len;
1344     ngx_uint_t            addr;
1345     ngx_sockaddr_t        sa;
1346     struct sockaddr_in   *sin;
1347 #if (NGX_HAVE_INET6)
1348     ngx_uint_t            i;
1349     struct sockaddr_in6  *sin6;
1350 #endif
1351 
1352     addr = 0;
1353 
1354     if (c->local_socklen) {
1355         switch (c->local_sockaddr->sa_family) {
1356 
1357 #if (NGX_HAVE_INET6)
1358         case AF_INET6:
1359             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
1360 
1361             for (i = 0; addr == 0 && i < 16; i++) {
1362                 addr |= sin6->sin6_addr.s6_addr[i];
1363             }
1364 
1365             break;
1366 #endif
1367 
1368 #if (NGX_HAVE_UNIX_DOMAIN)
1369         case AF_UNIX:
1370             addr = 1;
1371             break;
1372 #endif
1373 
1374         default: /* AF_INET */
1375             sin = (struct sockaddr_in *) c->local_sockaddr;
1376             addr = sin->sin_addr.s_addr;
1377             break;
1378         }
1379     }
1380 
1381     if (addr == 0) {
1382 
1383         len = sizeof(ngx_sockaddr_t);
1384 
1385         if (getsockname(c->fd, &sa.sockaddr, &len) == -1) {
1386             ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1387             return NGX_ERROR;
1388         }
1389 
1390         c->local_sockaddr = ngx_palloc(c->pool, len);
1391         if (c->local_sockaddr == NULL) {
1392             return NGX_ERROR;
1393         }
1394 
1395         ngx_memcpy(c->local_sockaddr, &sa, len);
1396 
1397         c->local_socklen = len;
1398     }
1399 
1400     if (s == NULL) {
1401         return NGX_OK;
1402     }
1403 
1404     s->len = ngx_sock_ntop(c->local_sockaddr, c->local_socklen,
1405                            s->data, s->len, port);
1406 
1407     return NGX_OK;
1408 }
1409 
1410 
1411 ngx_int_t
1412 ngx_tcp_nodelay(ngx_connection_t *c)
1413 {
1414     int  tcp_nodelay;
1415 
1416     if (c->tcp_nodelay != NGX_TCP_NODELAY_UNSET) {
1417         return NGX_OK;
1418     }
1419 
1420     ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "tcp_nodelay");
1421 
1422     tcp_nodelay = 1;
1423 
1424     if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1425                    (const void *) &tcp_nodelay, sizeof(int))
1426         == -1)
1427     {
1428 #if (NGX_SOLARIS)
1429         if (c->log_error == NGX_ERROR_INFO) {
1430 
1431             /* Solaris returns EINVAL if a socket has been shut down */
1432             c->log_error = NGX_ERROR_IGNORE_EINVAL;
1433 
1434             ngx_connection_error(c, ngx_socket_errno,
1435                                  "setsockopt(TCP_NODELAY) failed");
1436 
1437             c->log_error = NGX_ERROR_INFO;
1438 
1439             return NGX_ERROR;
1440         }
1441 #endif
1442 
1443         ngx_connection_error(c, ngx_socket_errno,
1444                              "setsockopt(TCP_NODELAY) failed");
1445         return NGX_ERROR;
1446     }
1447 
1448     c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1449 
1450     return NGX_OK;
1451 }
1452 
1453 
1454 ngx_int_t
1455 ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
1456 {
1457     ngx_uint_t  level;
1458 
1459     /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
1460 
1461     if ((err == NGX_ECONNRESET
1462 #if (NGX_WIN32)
1463          || err == NGX_ECONNABORTED
1464 #endif
1465         ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
1466     {
1467         return 0;
1468     }
1469 
1470 #if (NGX_SOLARIS)
1471     if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
1472         return 0;
1473     }
1474 #endif
1475 
1476     if (err == 0
1477         || err == NGX_ECONNRESET
1478 #if (NGX_WIN32)
1479         || err == NGX_ECONNABORTED
1480 #else
1481         || err == NGX_EPIPE
1482 #endif
1483         || err == NGX_ENOTCONN
1484         || err == NGX_ETIMEDOUT
1485         || err == NGX_ECONNREFUSED
1486         || err == NGX_ENETDOWN
1487         || err == NGX_ENETUNREACH
1488         || err == NGX_EHOSTDOWN
1489         || err == NGX_EHOSTUNREACH)
1490     {
1491         switch (c->log_error) {
1492 
1493         case NGX_ERROR_IGNORE_EINVAL:
1494         case NGX_ERROR_IGNORE_ECONNRESET:
1495         case NGX_ERROR_INFO:
1496             level = NGX_LOG_INFO;
1497             break;
1498 
1499         default:
1500             level = NGX_LOG_ERR;
1501         }
1502 
1503     } else {
1504         level = NGX_LOG_ALERT;
1505     }
1506 
1507     ngx_log_error(level, c->log, err, text);
1508 
1509     return NGX_ERROR;
1510 }