upstream 0.7.33
[nginx.git] / nginx / src / core / ngx_connection.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10
11
12 ngx_os_io_t  ngx_io;
13
14
15 ngx_listening_t *
16 ngx_listening_inet_stream_socket(ngx_conf_t *cf, in_addr_t addr, in_port_t port)
17 {
18     size_t               len;
19     ngx_listening_t     *ls;
20     struct sockaddr_in  *sin;
21
22     ls = ngx_array_push(&cf->cycle->listening);
23     if (ls == NULL) {
24         return NULL;
25     }
26
27     ngx_memzero(ls, sizeof(ngx_listening_t));
28
29     sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
30     if (sin == NULL) {
31         return NULL;
32     }
33
34     sin->sin_family = AF_INET;
35     sin->sin_addr.s_addr = addr;
36     sin->sin_port = htons(port);
37
38
39     ls->addr_text.data = ngx_pnalloc(cf->pool,
40                                     NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1);
41     if (ls->addr_text.data == NULL) {
42         return NULL;
43     }
44
45     len = ngx_inet_ntop(AF_INET, &addr, ls->addr_text.data,
46                         NGX_INET_ADDRSTRLEN);
47
48     ls->addr_text.len = ngx_sprintf(ls->addr_text.data + len, ":%d", port)
49                         - ls->addr_text.data;
50
51     ls->fd = (ngx_socket_t) -1;
52     ls->type = SOCK_STREAM;
53     ls->sockaddr = (struct sockaddr *) sin;
54     ls->socklen = sizeof(struct sockaddr_in);
55     ls->addr = offsetof(struct sockaddr_in, sin_addr);
56     ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
57
58     return ls;
59 }
60
61
62 ngx_int_t
63 ngx_set_inherited_sockets(ngx_cycle_t *cycle)
64 {
65     size_t                     len;
66     ngx_uint_t                 i;
67     ngx_listening_t           *ls;
68     struct sockaddr_in        *sin;
69     socklen_t                  olen;
70 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
71     ngx_err_t                  err;
72     struct accept_filter_arg   af;
73 #endif
74 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
75     int                        timeout;
76 #endif
77
78     ls = cycle->listening.elts;
79     for (i = 0; i < cycle->listening.nelts; i++) {
80
81         /* AF_INET only */
82
83         ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(struct sockaddr_in));
84         if (ls[i].sockaddr == NULL) {
85             return NGX_ERROR;
86         }
87
88         ls[i].socklen = sizeof(struct sockaddr_in);
89         if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
90             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
91                           "getsockname() of the inherited "
92                           "socket #%d failed", ls[i].fd);
93             ls[i].ignore = 1;
94             continue;
95         }
96
97         sin = (struct sockaddr_in *) ls[i].sockaddr;
98
99         if (sin->sin_family != AF_INET) {
100             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
101                           "the inherited socket #%d has "
102                           "unsupported family", ls[i].fd);
103             ls[i].ignore = 1;
104             continue;
105         }
106
107         ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
108
109         ls[i].addr_text.data = ngx_pnalloc(cycle->pool,
110                                    NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1);
111         if (ls[i].addr_text.data == NULL) {
112             return NGX_ERROR;
113         }
114
115         len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data,
116                             NGX_INET_ADDRSTRLEN);
117         if (len == 0) {
118             return NGX_ERROR;
119         }
120
121         ls[i].addr_text.len = ngx_sprintf(ls[i].addr_text.data + len, ":%d",
122                                           ntohs(sin->sin_port))
123                               - ls[i].addr_text.data;
124
125         ls[i].backlog = NGX_LISTEN_BACKLOG;
126
127         olen = sizeof(int);
128
129         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
130                        &olen)
131             == -1)
132         {
133             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
134                           "getsockopt(SO_RCVBUF) %V failed, ignored",
135                           &ls[i].addr_text);
136
137             ls[i].rcvbuf = -1;
138         }
139
140         olen = sizeof(int);
141
142         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
143                        &olen)
144             == -1)
145         {
146             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
147                           "getsockopt(SO_SNDBUF) %V failed, ignored",
148                           &ls[i].addr_text);
149
150             ls[i].sndbuf = -1;
151         }
152
153 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
154
155         ngx_memzero(&af, sizeof(struct accept_filter_arg));
156         olen = sizeof(struct accept_filter_arg);
157
158         if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
159             == -1)
160         {
161             err = ngx_errno;
162
163             if (err == NGX_EINVAL) {
164                 continue;
165             }
166
167             ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
168                           "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
169                           &ls[i].addr_text);
170             continue;
171         }
172
173         if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
174             continue;
175         }
176
177         ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
178         if (ls[i].accept_filter == NULL) {
179             return NGX_ERROR;
180         }
181
182         (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
183                            (u_char *) af.af_name, 16);
184 #endif
185
186 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
187
188         timeout = 0;
189         olen = sizeof(int);
190
191         if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
192             == -1)
193         {
194             ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
195                           "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
196                           &ls[i].addr_text);
197             continue;
198         }
199
200         if (olen < sizeof(int) || timeout == 0) {
201             continue;
202         }
203
204         ls[i].deferred_accept = 1;
205 #endif
206     }
207
208     return NGX_OK;
209 }
210
211
212 ngx_int_t
213 ngx_open_listening_sockets(ngx_cycle_t *cycle)
214 {
215     int               reuseaddr;
216     ngx_uint_t        i, tries, failed;
217     ngx_err_t         err;
218     ngx_log_t        *log;
219     ngx_socket_t      s;
220     ngx_listening_t  *ls;
221
222     reuseaddr = 1;
223 #if (NGX_SUPPRESS_WARN)
224     failed = 0;
225 #endif
226
227     log = cycle->log;
228
229     /* TODO: configurable try number */
230
231     for (tries = 5; tries; tries--) {
232         failed = 0;
233
234         /* for each listening socket */
235
236         ls = cycle->listening.elts;
237         for (i = 0; i < cycle->listening.nelts; i++) {
238
239             if (ls[i].ignore) {
240                 continue;
241             }
242
243             if (ls[i].fd != -1) {
244                 continue;
245             }
246
247             if (ls[i].inherited) {
248
249                 /* TODO: close on exit */
250                 /* TODO: nonblocking */
251                 /* TODO: deferred accept */
252
253                 continue;
254             }
255
256             s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
257
258             if (s == -1) {
259                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
260                               ngx_socket_n " %V failed", &ls[i].addr_text);
261                 return NGX_ERROR;
262             }
263
264             if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
265                            (const void *) &reuseaddr, sizeof(int))
266                 == -1)
267             {
268                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
269                               "setsockopt(SO_REUSEADDR) %V failed",
270                               &ls[i].addr_text);
271
272                 if (ngx_close_socket(s) == -1) {
273                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
274                                   ngx_close_socket_n " %V failed",
275                                   &ls[i].addr_text);
276                 }
277
278                 return NGX_ERROR;
279             }
280
281             /* TODO: close on exit */
282
283             if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
284                 if (ngx_nonblocking(s) == -1) {
285                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
286                                   ngx_nonblocking_n " %V failed",
287                                   &ls[i].addr_text);
288
289                     if (ngx_close_socket(s) == -1) {
290                         ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
291                                       ngx_close_socket_n " %V failed",
292                                       &ls[i].addr_text);
293                     }
294
295                     return NGX_ERROR;
296                 }
297             }
298
299             ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
300                            "bind() %V #%d ", &ls[i].addr_text, s);
301
302             if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
303                 err = ngx_socket_errno;
304
305                 if (err == NGX_EADDRINUSE && ngx_test_config) {
306                     continue;
307                 }
308
309                 ngx_log_error(NGX_LOG_EMERG, log, err,
310                               "bind() to %V failed", &ls[i].addr_text);
311
312                 if (ngx_close_socket(s) == -1) {
313                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
314                                   ngx_close_socket_n " %V failed",
315                                   &ls[i].addr_text);
316                 }
317
318                 if (err != NGX_EADDRINUSE) {
319                     return NGX_ERROR;
320                 }
321
322                 failed = 1;
323
324                 continue;
325             }
326
327             if (listen(s, ls[i].backlog) == -1) {
328                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
329                               "listen() to %V, backlog %d failed",
330                               &ls[i].addr_text, ls[i].backlog);
331
332                 if (ngx_close_socket(s) == -1) {
333                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
334                                   ngx_close_socket_n " %V failed",
335                                   &ls[i].addr_text);
336                 }
337
338                 return NGX_ERROR;
339             }
340
341             ls[i].listen = 1;
342
343             ls[i].fd = s;
344         }
345
346         if (!failed) {
347             break;
348         }
349
350         /* TODO: delay configurable */
351
352         ngx_log_error(NGX_LOG_NOTICE, log, 0,
353                       "try again to bind() after 500ms");
354
355         ngx_msleep(500);
356     }
357
358     if (failed) {
359         ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
360         return NGX_ERROR;
361     }
362
363     return NGX_OK;
364 }
365
366
367 void
368 ngx_configure_listening_socket(ngx_cycle_t *cycle)
369 {
370     ngx_uint_t                 i;
371     ngx_listening_t           *ls;
372
373 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
374     struct accept_filter_arg   af;
375 #endif
376 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
377     int                        timeout;
378 #endif
379
380     ls = cycle->listening.elts;
381     for (i = 0; i < cycle->listening.nelts; i++) {
382
383         if (ls[i].rcvbuf != -1) {
384             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
385                            (const void *) &ls[i].rcvbuf, sizeof(int))
386                 == -1)
387             {
388                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
389                               "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
390                               ls[i].rcvbuf, &ls[i].addr_text);
391             }
392         }
393
394         if (ls[i].sndbuf != -1) {
395             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
396                            (const void *) &ls[i].sndbuf, sizeof(int))
397                 == -1)
398             {
399                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
400                               "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
401                               ls[i].sndbuf, &ls[i].addr_text);
402             }
403         }
404
405 #if 0
406         if (1) {
407             int tcp_nodelay = 1;
408
409             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
410                        (const void *) &tcp_nodelay, sizeof(int))
411                 == -1)
412             {
413                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
414                               "setsockopt(TCP_NODELAY) %V failed, ignored",
415                               &ls[i].addr_text);
416             }
417         }
418 #endif
419
420         if (ls[i].listen) {
421
422             /* change backlog via listen() */
423
424             if (listen(ls[i].fd, ls[i].backlog) == -1) {
425                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
426                               "listen() to %V, backlog %d failed, ignored",
427                               &ls[i].addr_text, ls[i].backlog);
428             }
429         }
430
431         /*
432          * setting deferred mode should be last operation on socket,
433          * because code may prematurely continue cycle on failure
434          */
435
436 #if (NGX_HAVE_DEFERRED_ACCEPT)
437
438 #ifdef SO_ACCEPTFILTER
439
440         if (ls[i].delete_deferred) {
441             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
442                 == -1)
443             {
444                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
445                               "setsockopt(SO_ACCEPTFILTER, NULL) "
446                               "for %V failed, ignored",
447                               &ls[i].addr_text);
448
449                 if (ls[i].accept_filter) {
450                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
451                                   "could not change the accept filter "
452                                   "to \"%s\" for %V, ignored",
453                                   ls[i].accept_filter, &ls[i].addr_text);
454                 }
455
456                 continue;
457             }
458
459             ls[i].deferred_accept = 0;
460         }
461
462         if (ls[i].add_deferred) {
463             ngx_memzero(&af, sizeof(struct accept_filter_arg));
464             (void) ngx_cpystrn((u_char *) af.af_name,
465                                (u_char *) ls[i].accept_filter, 16);
466
467             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
468                            &af, sizeof(struct accept_filter_arg))
469                 == -1)
470             {
471                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
472                               "setsockopt(SO_ACCEPTFILTER, \"%s\") "
473                               " for %V failed, ignored",
474                               ls[i].accept_filter, &ls[i].addr_text);
475                 continue;
476             }
477
478             ls[i].deferred_accept = 1;
479         }
480
481 #endif
482
483 #ifdef TCP_DEFER_ACCEPT
484
485         if (ls[i].add_deferred || ls[i].delete_deferred) {
486
487             if (ls[i].add_deferred) {
488                 timeout = (int) (ls[i].post_accept_timeout / 1000);
489
490             } else {
491                 timeout = 0;
492             }
493
494             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
495                            &timeout, sizeof(int))
496                 == -1)
497             {
498                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
499                               "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
500                               "ignored",
501                               timeout, &ls[i].addr_text);
502
503                 continue;
504             }
505         }
506
507         if (ls[i].add_deferred) {
508             ls[i].deferred_accept = 1;
509         }
510
511 #endif
512
513 #endif /* NGX_HAVE_DEFERRED_ACCEPT */
514     }
515
516     return;
517 }
518
519
520 void
521 ngx_close_listening_sockets(ngx_cycle_t *cycle)
522 {
523     ngx_uint_t         i;
524     ngx_listening_t   *ls;
525     ngx_connection_t  *c;
526
527     if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
528         return;
529     }
530
531     ngx_accept_mutex_held = 0;
532     ngx_use_accept_mutex = 0;
533
534     ls = cycle->listening.elts;
535     for (i = 0; i < cycle->listening.nelts; i++) {
536
537         c = ls[i].connection;
538
539         if (c->read->active) {
540             if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
541                 ngx_del_conn(c, NGX_CLOSE_EVENT);
542
543             } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
544
545                 /*
546                  * it seems that Linux-2.6.x OpenVZ sends events
547                  * for closed shared listening sockets unless
548                  * the events was explicity deleted
549                  */
550
551                 ngx_del_event(c->read, NGX_READ_EVENT, 0);
552
553             } else {
554                 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
555             }
556         }
557
558         ngx_free_connection(c);
559
560         c->fd = (ngx_socket_t) -1;
561
562         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
563                        "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
564
565         if (ngx_close_socket(ls[i].fd) == -1) {
566             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
567                           ngx_close_socket_n " %V failed", &ls[i].addr_text);
568         }
569     }
570 }
571
572
573 ngx_connection_t *
574 ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
575 {
576     ngx_uint_t         instance;
577     ngx_event_t       *rev, *wev;
578     ngx_connection_t  *c;
579
580     /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
581
582     if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
583         ngx_log_error(NGX_LOG_ALERT, log, 0,
584                       "the new socket has number %d, "
585                       "but only %ui files are available",
586                       s, ngx_cycle->files_n);
587         return NULL;
588     }
589
590     /* ngx_mutex_lock */
591
592     c = ngx_cycle->free_connections;
593
594     if (c == NULL) {
595         ngx_log_error(NGX_LOG_ALERT, log, 0,
596                       "%ui worker_connections are not enough",
597                       ngx_cycle->connection_n);
598
599         /* ngx_mutex_unlock */
600
601         return NULL;
602     }
603
604     ngx_cycle->free_connections = c->data;
605     ngx_cycle->free_connection_n--;
606
607     /* ngx_mutex_unlock */
608
609     if (ngx_cycle->files) {
610         ngx_cycle->files[s] = c;
611     }
612
613     rev = c->read;
614     wev = c->write;
615
616     ngx_memzero(c, sizeof(ngx_connection_t));
617
618     c->read = rev;
619     c->write = wev;
620     c->fd = s;
621     c->log = log;
622
623     instance = rev->instance;
624
625     ngx_memzero(rev, sizeof(ngx_event_t));
626     ngx_memzero(wev, sizeof(ngx_event_t));
627
628     rev->instance = !instance;
629     wev->instance = !instance;
630
631     rev->index = NGX_INVALID_INDEX;
632     wev->index = NGX_INVALID_INDEX;
633
634     rev->data = c;
635     wev->data = c;
636
637     wev->write = 1;
638
639     return c;
640 }
641
642
643 void
644 ngx_free_connection(ngx_connection_t *c)
645 {
646     /* ngx_mutex_lock */
647
648     c->data = ngx_cycle->free_connections;
649     ngx_cycle->free_connections = c;
650     ngx_cycle->free_connection_n++;
651
652     /* ngx_mutex_unlock */
653
654     if (ngx_cycle->files) {
655         ngx_cycle->files[c->fd] = NULL;
656     }
657 }
658
659
660 void
661 ngx_close_connection(ngx_connection_t *c)
662 {
663     ngx_err_t     err;
664     ngx_uint_t    log_error, level;
665     ngx_socket_t  fd;
666
667     if (c->fd == -1) {
668         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
669         return;
670     }
671
672     if (c->read->timer_set) {
673         ngx_del_timer(c->read);
674     }
675
676     if (c->write->timer_set) {
677         ngx_del_timer(c->write);
678     }
679
680     if (ngx_del_conn) {
681         ngx_del_conn(c, NGX_CLOSE_EVENT);
682
683     } else {
684         if (c->read->active || c->read->disabled) {
685             ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
686         }
687
688         if (c->write->active || c->write->disabled) {
689             ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
690         }
691     }
692
693 #if (NGX_THREADS)
694
695     /*
696      * we have to clean the connection information before the closing
697      * because another thread may reopen the same file descriptor
698      * before we clean the connection
699      */
700
701     ngx_mutex_lock(ngx_posted_events_mutex);
702
703     if (c->read->prev) {
704         ngx_delete_posted_event(c->read);
705     }
706
707     if (c->write->prev) {
708         ngx_delete_posted_event(c->write);
709     }
710
711     c->read->closed = 1;
712     c->write->closed = 1;
713
714     if (c->single_connection) {
715         ngx_unlock(&c->lock);
716         c->read->locked = 0;
717         c->write->locked = 0;
718     }
719
720     ngx_mutex_unlock(ngx_posted_events_mutex);
721
722 #else
723
724     if (c->read->prev) {
725         ngx_delete_posted_event(c->read);
726     }
727
728     if (c->write->prev) {
729         ngx_delete_posted_event(c->write);
730     }
731
732     c->read->closed = 1;
733     c->write->closed = 1;
734
735 #endif
736
737     log_error = c->log_error;
738
739     ngx_free_connection(c);
740
741     fd = c->fd;
742     c->fd = (ngx_socket_t) -1;
743
744     if (ngx_close_socket(fd) == -1) {
745
746         err = ngx_socket_errno;
747
748         if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
749
750             switch (log_error) {
751
752             case NGX_ERROR_INFO:
753                 level = NGX_LOG_INFO;
754                 break;
755
756             case NGX_ERROR_ERR:
757                 level = NGX_LOG_ERR;
758                 break;
759
760             default:
761                 level = NGX_LOG_CRIT;
762             }
763
764         } else {
765             level = NGX_LOG_CRIT;
766         }
767
768         /* we use ngx_cycle->log because c->log was in c->pool */
769
770         ngx_log_error(level, ngx_cycle->log, err,
771                       ngx_close_socket_n " %d failed", fd);
772     }
773 }
774
775
776 ngx_int_t
777 ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
778 {
779     ngx_uint_t  level;
780
781     if (err == NGX_ECONNRESET
782         && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
783     {
784         return 0;
785     }
786
787     if (err == 0
788         || err == NGX_ECONNRESET
789 #if !(NGX_WIN32)
790         || err == NGX_EPIPE
791 #endif
792         || err == NGX_ENOTCONN
793         || err == NGX_ETIMEDOUT
794         || err == NGX_ECONNREFUSED
795         || err == NGX_ENETDOWN
796         || err == NGX_ENETUNREACH
797         || err == NGX_EHOSTDOWN
798         || err == NGX_EHOSTUNREACH)
799     {
800         switch (c->log_error) {
801
802         case NGX_ERROR_IGNORE_ECONNRESET:
803         case NGX_ERROR_INFO:
804             level = NGX_LOG_INFO;
805             break;
806
807         case NGX_ERROR_ERR:
808             level = NGX_LOG_ERR;
809             break;
810
811         default:
812             level = NGX_LOG_ALERT;
813         }
814
815     } else {
816         level = NGX_LOG_ALERT;
817     }
818
819     ngx_log_error(level, c->log, err, text);
820
821     return NGX_ERROR;
822 }