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