upstream nginx-0.7.43
[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 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
286
287             if (ls[i].sockaddr->sa_family == AF_INET6 && ls[i].ipv6only) {
288                 int  ipv6only;
289
290                 ipv6only = (ls[i].ipv6only == 1);
291
292                 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
293                                (const void *) &ipv6only, sizeof(int))
294                     == -1)
295                 {
296                     ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
297                                   "setsockopt(IPV6_V6ONLY) %V failed, ignored",
298                                   &ls[i].addr_text);
299                 }
300             }
301 #endif
302             /* TODO: close on exit */
303
304             if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
305                 if (ngx_nonblocking(s) == -1) {
306                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
307                                   ngx_nonblocking_n " %V failed",
308                                   &ls[i].addr_text);
309
310                     if (ngx_close_socket(s) == -1) {
311                         ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
312                                       ngx_close_socket_n " %V failed",
313                                       &ls[i].addr_text);
314                     }
315
316                     return NGX_ERROR;
317                 }
318             }
319
320             ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
321                            "bind() %V #%d ", &ls[i].addr_text, s);
322
323             if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
324                 err = ngx_socket_errno;
325
326                 if (err == NGX_EADDRINUSE && ngx_test_config) {
327                     continue;
328                 }
329
330                 ngx_log_error(NGX_LOG_EMERG, log, err,
331                               "bind() to %V failed", &ls[i].addr_text);
332
333                 if (ngx_close_socket(s) == -1) {
334                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
335                                   ngx_close_socket_n " %V failed",
336                                   &ls[i].addr_text);
337                 }
338
339                 if (err != NGX_EADDRINUSE) {
340                     return NGX_ERROR;
341                 }
342
343                 failed = 1;
344
345                 continue;
346             }
347
348             if (listen(s, ls[i].backlog) == -1) {
349                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
350                               "listen() to %V, backlog %d failed",
351                               &ls[i].addr_text, ls[i].backlog);
352
353                 if (ngx_close_socket(s) == -1) {
354                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
355                                   ngx_close_socket_n " %V failed",
356                                   &ls[i].addr_text);
357                 }
358
359                 return NGX_ERROR;
360             }
361
362             ls[i].listen = 1;
363
364             ls[i].fd = s;
365         }
366
367         if (!failed) {
368             break;
369         }
370
371         /* TODO: delay configurable */
372
373         ngx_log_error(NGX_LOG_NOTICE, log, 0,
374                       "try again to bind() after 500ms");
375
376         ngx_msleep(500);
377     }
378
379     if (failed) {
380         ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
381         return NGX_ERROR;
382     }
383
384     return NGX_OK;
385 }
386
387
388 void
389 ngx_configure_listening_socket(ngx_cycle_t *cycle)
390 {
391     ngx_uint_t                 i;
392     ngx_listening_t           *ls;
393
394 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
395     struct accept_filter_arg   af;
396 #endif
397 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
398     int                        timeout;
399 #endif
400
401     ls = cycle->listening.elts;
402     for (i = 0; i < cycle->listening.nelts; i++) {
403
404         if (ls[i].rcvbuf != -1) {
405             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
406                            (const void *) &ls[i].rcvbuf, sizeof(int))
407                 == -1)
408             {
409                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
410                               "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
411                               ls[i].rcvbuf, &ls[i].addr_text);
412             }
413         }
414
415         if (ls[i].sndbuf != -1) {
416             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
417                            (const void *) &ls[i].sndbuf, sizeof(int))
418                 == -1)
419             {
420                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
421                               "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
422                               ls[i].sndbuf, &ls[i].addr_text);
423             }
424         }
425
426 #if 0
427         if (1) {
428             int tcp_nodelay = 1;
429
430             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
431                        (const void *) &tcp_nodelay, sizeof(int))
432                 == -1)
433             {
434                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
435                               "setsockopt(TCP_NODELAY) %V failed, ignored",
436                               &ls[i].addr_text);
437             }
438         }
439 #endif
440
441         if (ls[i].listen) {
442
443             /* change backlog via listen() */
444
445             if (listen(ls[i].fd, ls[i].backlog) == -1) {
446                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
447                               "listen() to %V, backlog %d failed, ignored",
448                               &ls[i].addr_text, ls[i].backlog);
449             }
450         }
451
452         /*
453          * setting deferred mode should be last operation on socket,
454          * because code may prematurely continue cycle on failure
455          */
456
457 #if (NGX_HAVE_DEFERRED_ACCEPT)
458
459 #ifdef SO_ACCEPTFILTER
460
461         if (ls[i].delete_deferred) {
462             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
463                 == -1)
464             {
465                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
466                               "setsockopt(SO_ACCEPTFILTER, NULL) "
467                               "for %V failed, ignored",
468                               &ls[i].addr_text);
469
470                 if (ls[i].accept_filter) {
471                     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
472                                   "could not change the accept filter "
473                                   "to \"%s\" for %V, ignored",
474                                   ls[i].accept_filter, &ls[i].addr_text);
475                 }
476
477                 continue;
478             }
479
480             ls[i].deferred_accept = 0;
481         }
482
483         if (ls[i].add_deferred) {
484             ngx_memzero(&af, sizeof(struct accept_filter_arg));
485             (void) ngx_cpystrn((u_char *) af.af_name,
486                                (u_char *) ls[i].accept_filter, 16);
487
488             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
489                            &af, sizeof(struct accept_filter_arg))
490                 == -1)
491             {
492                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
493                               "setsockopt(SO_ACCEPTFILTER, \"%s\") "
494                               " for %V failed, ignored",
495                               ls[i].accept_filter, &ls[i].addr_text);
496                 continue;
497             }
498
499             ls[i].deferred_accept = 1;
500         }
501
502 #endif
503
504 #ifdef TCP_DEFER_ACCEPT
505
506         if (ls[i].add_deferred || ls[i].delete_deferred) {
507
508             if (ls[i].add_deferred) {
509                 timeout = (int) (ls[i].post_accept_timeout / 1000);
510
511             } else {
512                 timeout = 0;
513             }
514
515             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
516                            &timeout, sizeof(int))
517                 == -1)
518             {
519                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
520                               "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
521                               "ignored",
522                               timeout, &ls[i].addr_text);
523
524                 continue;
525             }
526         }
527
528         if (ls[i].add_deferred) {
529             ls[i].deferred_accept = 1;
530         }
531
532 #endif
533
534 #endif /* NGX_HAVE_DEFERRED_ACCEPT */
535     }
536
537     return;
538 }
539
540
541 void
542 ngx_close_listening_sockets(ngx_cycle_t *cycle)
543 {
544     ngx_uint_t         i;
545     ngx_listening_t   *ls;
546     ngx_connection_t  *c;
547
548     if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
549         return;
550     }
551
552     ngx_accept_mutex_held = 0;
553     ngx_use_accept_mutex = 0;
554
555     ls = cycle->listening.elts;
556     for (i = 0; i < cycle->listening.nelts; i++) {
557
558         c = ls[i].connection;
559
560         if (c->read->active) {
561             if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
562                 ngx_del_conn(c, NGX_CLOSE_EVENT);
563
564             } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
565
566                 /*
567                  * it seems that Linux-2.6.x OpenVZ sends events
568                  * for closed shared listening sockets unless
569                  * the events was explicity deleted
570                  */
571
572                 ngx_del_event(c->read, NGX_READ_EVENT, 0);
573
574             } else {
575                 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
576             }
577         }
578
579         ngx_free_connection(c);
580
581         c->fd = (ngx_socket_t) -1;
582
583         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
584                        "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
585
586         if (ngx_close_socket(ls[i].fd) == -1) {
587             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
588                           ngx_close_socket_n " %V failed", &ls[i].addr_text);
589         }
590     }
591 }
592
593
594 ngx_connection_t *
595 ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
596 {
597     ngx_uint_t         instance;
598     ngx_event_t       *rev, *wev;
599     ngx_connection_t  *c;
600
601     /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
602
603     if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
604         ngx_log_error(NGX_LOG_ALERT, log, 0,
605                       "the new socket has number %d, "
606                       "but only %ui files are available",
607                       s, ngx_cycle->files_n);
608         return NULL;
609     }
610
611     /* ngx_mutex_lock */
612
613     c = ngx_cycle->free_connections;
614
615     if (c == NULL) {
616         ngx_log_error(NGX_LOG_ALERT, log, 0,
617                       "%ui worker_connections are not enough",
618                       ngx_cycle->connection_n);
619
620         /* ngx_mutex_unlock */
621
622         return NULL;
623     }
624
625     ngx_cycle->free_connections = c->data;
626     ngx_cycle->free_connection_n--;
627
628     /* ngx_mutex_unlock */
629
630     if (ngx_cycle->files) {
631         ngx_cycle->files[s] = c;
632     }
633
634     rev = c->read;
635     wev = c->write;
636
637     ngx_memzero(c, sizeof(ngx_connection_t));
638
639     c->read = rev;
640     c->write = wev;
641     c->fd = s;
642     c->log = log;
643
644     instance = rev->instance;
645
646     ngx_memzero(rev, sizeof(ngx_event_t));
647     ngx_memzero(wev, sizeof(ngx_event_t));
648
649     rev->instance = !instance;
650     wev->instance = !instance;
651
652     rev->index = NGX_INVALID_INDEX;
653     wev->index = NGX_INVALID_INDEX;
654
655     rev->data = c;
656     wev->data = c;
657
658     wev->write = 1;
659
660     return c;
661 }
662
663
664 void
665 ngx_free_connection(ngx_connection_t *c)
666 {
667     /* ngx_mutex_lock */
668
669     c->data = ngx_cycle->free_connections;
670     ngx_cycle->free_connections = c;
671     ngx_cycle->free_connection_n++;
672
673     /* ngx_mutex_unlock */
674
675     if (ngx_cycle->files) {
676         ngx_cycle->files[c->fd] = NULL;
677     }
678 }
679
680
681 void
682 ngx_close_connection(ngx_connection_t *c)
683 {
684     ngx_err_t     err;
685     ngx_uint_t    log_error, level;
686     ngx_socket_t  fd;
687
688     if (c->fd == -1) {
689         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
690         return;
691     }
692
693     if (c->read->timer_set) {
694         ngx_del_timer(c->read);
695     }
696
697     if (c->write->timer_set) {
698         ngx_del_timer(c->write);
699     }
700
701     if (ngx_del_conn) {
702         ngx_del_conn(c, NGX_CLOSE_EVENT);
703
704     } else {
705         if (c->read->active || c->read->disabled) {
706             ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
707         }
708
709         if (c->write->active || c->write->disabled) {
710             ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
711         }
712     }
713
714 #if (NGX_THREADS)
715
716     /*
717      * we have to clean the connection information before the closing
718      * because another thread may reopen the same file descriptor
719      * before we clean the connection
720      */
721
722     ngx_mutex_lock(ngx_posted_events_mutex);
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     if (c->single_connection) {
736         ngx_unlock(&c->lock);
737         c->read->locked = 0;
738         c->write->locked = 0;
739     }
740
741     ngx_mutex_unlock(ngx_posted_events_mutex);
742
743 #else
744
745     if (c->read->prev) {
746         ngx_delete_posted_event(c->read);
747     }
748
749     if (c->write->prev) {
750         ngx_delete_posted_event(c->write);
751     }
752
753     c->read->closed = 1;
754     c->write->closed = 1;
755
756 #endif
757
758     log_error = c->log_error;
759
760     ngx_free_connection(c);
761
762     fd = c->fd;
763     c->fd = (ngx_socket_t) -1;
764
765     if (ngx_close_socket(fd) == -1) {
766
767         err = ngx_socket_errno;
768
769         if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
770
771             switch (log_error) {
772
773             case NGX_ERROR_INFO:
774                 level = NGX_LOG_INFO;
775                 break;
776
777             case NGX_ERROR_ERR:
778                 level = NGX_LOG_ERR;
779                 break;
780
781             default:
782                 level = NGX_LOG_CRIT;
783             }
784
785         } else {
786             level = NGX_LOG_CRIT;
787         }
788
789         /* we use ngx_cycle->log because c->log was in c->pool */
790
791         ngx_log_error(level, ngx_cycle->log, err,
792                       ngx_close_socket_n " %d failed", fd);
793     }
794 }
795
796
797 ngx_int_t
798 ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
799 {
800     ngx_uint_t  level;
801
802     if (err == NGX_ECONNRESET && c->log_error == NGX_ERROR_IGNORE_ECONNRESET) {
803         return 0;
804     }
805
806 #if (NGX_SOLARIS)
807     if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
808         return 0;
809     }
810 #endif
811
812     if (err == 0
813         || err == NGX_ECONNRESET
814 #if !(NGX_WIN32)
815         || err == NGX_EPIPE
816 #endif
817         || err == NGX_ENOTCONN
818         || err == NGX_ETIMEDOUT
819         || err == NGX_ECONNREFUSED
820         || err == NGX_ENETDOWN
821         || err == NGX_ENETUNREACH
822         || err == NGX_EHOSTDOWN
823         || err == NGX_EHOSTUNREACH)
824     {
825         switch (c->log_error) {
826
827         case NGX_ERROR_IGNORE_EINVAL:
828         case NGX_ERROR_IGNORE_ECONNRESET:
829         case NGX_ERROR_INFO:
830             level = NGX_LOG_INFO;
831             break;
832
833         case NGX_ERROR_ERR:
834             level = NGX_LOG_ERR;
835             break;
836
837         default:
838             level = NGX_LOG_ALERT;
839         }
840
841     } else {
842         level = NGX_LOG_ALERT;
843     }
844
845     ngx_log_error(level, c->log, err, text);
846
847     return NGX_ERROR;
848 }