1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11
12
13 #if (NGX_HAVE_FSTACK)
14 extern int fstack_territory(int domain, int type, int protocol);
15 extern int is_fstack_fd(int sockfd);
16
17 /*
18 * ngx_ff_skip_listening_socket() decides whether to skip `ls`.
19 * If the current process is NGX_PROCESS_WORKER and `ls` is belong to fstack,
20 * then `*type` will be ls->type|SOCK_FSTACK when `type` is not null.
21 */
22 static ngx_inline int
ngx_ff_skip_listening_socket(ngx_cycle_t * cycle,const ngx_listening_t * ls,int * type)23 ngx_ff_skip_listening_socket(ngx_cycle_t *cycle, const ngx_listening_t *ls, int *type)
24 {
25 if (ngx_ff_process == NGX_FF_PROCESS_NONE) {
26
27 /* process master, kernel network stack*/
28 if (!ls->belong_to_host) {
29 /* We should continue to process the listening socket,
30 if it is not supported by fstack. */
31 if (fstack_territory(ls->sockaddr->sa_family, ls->type, 0)) {
32 return 1;
33 }
34 }
35 } else {
36 /* process worker, fstack */
37 if (ls->belong_to_host) {
38 return 1;
39 }
40
41 if (!fstack_territory(ls->sockaddr->sa_family, ls->type, 0)) {
42 return 1;
43 }
44
45 if(type) {
46 *type |= SOCK_FSTACK;
47 }
48 }
49
50 return 0;
51 }
52 #endif
53
54
55 ngx_os_io_t ngx_io;
56
57
58 static void ngx_drain_connections(ngx_cycle_t *cycle);
59
60
61 ngx_listening_t *
ngx_create_listening(ngx_conf_t * cf,struct sockaddr * sockaddr,socklen_t socklen)62 ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr,
63 socklen_t socklen)
64 {
65 size_t len;
66 ngx_listening_t *ls;
67 struct sockaddr *sa;
68 u_char text[NGX_SOCKADDR_STRLEN];
69
70 ls = ngx_array_push(&cf->cycle->listening);
71 if (ls == NULL) {
72 return NULL;
73 }
74
75 ngx_memzero(ls, sizeof(ngx_listening_t));
76
77 sa = ngx_palloc(cf->pool, socklen);
78 if (sa == NULL) {
79 return NULL;
80 }
81
82 ngx_memcpy(sa, sockaddr, socklen);
83
84 ls->sockaddr = sa;
85 ls->socklen = socklen;
86
87 len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
88 ls->addr_text.len = len;
89
90 switch (ls->sockaddr->sa_family) {
91 #if (NGX_HAVE_INET6)
92 case AF_INET6:
93 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
94 break;
95 #endif
96 #if (NGX_HAVE_UNIX_DOMAIN)
97 case AF_UNIX:
98 ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
99 len++;
100 break;
101 #endif
102 case AF_INET:
103 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
104 break;
105 default:
106 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
107 break;
108 }
109
110 ls->addr_text.data = ngx_pnalloc(cf->pool, len);
111 if (ls->addr_text.data == NULL) {
112 return NULL;
113 }
114
115 ngx_memcpy(ls->addr_text.data, text, len);
116
117 #if !(NGX_WIN32)
118 ngx_rbtree_init(&ls->rbtree, &ls->sentinel, ngx_udp_rbtree_insert_value);
119 #endif
120
121 ls->fd = (ngx_socket_t) -1;
122 ls->type = SOCK_STREAM;
123
124 ls->backlog = NGX_LISTEN_BACKLOG;
125 ls->rcvbuf = -1;
126 ls->sndbuf = -1;
127
128 #if (NGX_HAVE_SETFIB)
129 ls->setfib = -1;
130 #endif
131
132 #if (NGX_HAVE_TCP_FASTOPEN)
133 ls->fastopen = -1;
134 #endif
135
136 return ls;
137 }
138
139
140 ngx_int_t
ngx_clone_listening(ngx_cycle_t * cycle,ngx_listening_t * ls)141 ngx_clone_listening(ngx_cycle_t *cycle, ngx_listening_t *ls)
142 {
143 #if (NGX_HAVE_REUSEPORT)
144
145 ngx_int_t n;
146 ngx_core_conf_t *ccf;
147 ngx_listening_t ols;
148
149 if (!ls->reuseport || ls->worker != 0) {
150 return NGX_OK;
151 }
152
153 ols = *ls;
154
155 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
156
157 for (n = 1; n < ccf->worker_processes; n++) {
158
159 /* create a socket for each worker process */
160
161 ls = ngx_array_push(&cycle->listening);
162 if (ls == NULL) {
163 return NGX_ERROR;
164 }
165
166 *ls = ols;
167 ls->worker = n;
168 }
169
170 #endif
171
172 return NGX_OK;
173 }
174
175
176 ngx_int_t
ngx_set_inherited_sockets(ngx_cycle_t * cycle)177 ngx_set_inherited_sockets(ngx_cycle_t *cycle)
178 {
179 size_t len;
180 ngx_uint_t i;
181 ngx_listening_t *ls;
182 socklen_t olen;
183 #if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
184 ngx_err_t err;
185 #endif
186 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
187 struct accept_filter_arg af;
188 #endif
189 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
190 int timeout;
191 #endif
192 #if (NGX_HAVE_REUSEPORT)
193 int reuseport;
194 #endif
195
196 ls = cycle->listening.elts;
197 for (i = 0; i < cycle->listening.nelts; i++) {
198
199 ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t));
200 if (ls[i].sockaddr == NULL) {
201 return NGX_ERROR;
202 }
203
204 ls[i].socklen = sizeof(ngx_sockaddr_t);
205 if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
206 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
207 "getsockname() of the inherited "
208 "socket #%d failed", ls[i].fd);
209 ls[i].ignore = 1;
210 continue;
211 }
212
213 if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
214 ls[i].socklen = sizeof(ngx_sockaddr_t);
215 }
216
217 switch (ls[i].sockaddr->sa_family) {
218
219 #if (NGX_HAVE_INET6)
220 case AF_INET6:
221 ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
222 len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
223 break;
224 #endif
225
226 #if (NGX_HAVE_UNIX_DOMAIN)
227 case AF_UNIX:
228 ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
229 len = NGX_UNIX_ADDRSTRLEN;
230 break;
231 #endif
232
233 case AF_INET:
234 ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
235 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
236 break;
237
238 default:
239 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
240 "the inherited socket #%d has "
241 "an unsupported protocol family", ls[i].fd);
242 ls[i].ignore = 1;
243 continue;
244 }
245
246 ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
247 if (ls[i].addr_text.data == NULL) {
248 return NGX_ERROR;
249 }
250
251 len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
252 ls[i].addr_text.data, len, 1);
253 if (len == 0) {
254 return NGX_ERROR;
255 }
256
257 ls[i].addr_text.len = len;
258
259 ls[i].backlog = NGX_LISTEN_BACKLOG;
260
261 olen = sizeof(int);
262
263 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_TYPE, (void *) &ls[i].type,
264 &olen)
265 == -1)
266 {
267 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
268 "getsockopt(SO_TYPE) %V failed", &ls[i].addr_text);
269 ls[i].ignore = 1;
270 continue;
271 }
272
273 olen = sizeof(int);
274
275 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
276 &olen)
277 == -1)
278 {
279 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
280 "getsockopt(SO_RCVBUF) %V failed, ignored",
281 &ls[i].addr_text);
282
283 ls[i].rcvbuf = -1;
284 }
285
286 olen = sizeof(int);
287
288 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
289 &olen)
290 == -1)
291 {
292 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
293 "getsockopt(SO_SNDBUF) %V failed, ignored",
294 &ls[i].addr_text);
295
296 ls[i].sndbuf = -1;
297 }
298
299 #if 0
300 /* SO_SETFIB is currently a set only option */
301
302 #if (NGX_HAVE_SETFIB)
303
304 olen = sizeof(int);
305
306 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
307 (void *) &ls[i].setfib, &olen)
308 == -1)
309 {
310 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
311 "getsockopt(SO_SETFIB) %V failed, ignored",
312 &ls[i].addr_text);
313
314 ls[i].setfib = -1;
315 }
316
317 #endif
318 #endif
319
320 #if (NGX_HAVE_REUSEPORT)
321
322 reuseport = 0;
323 olen = sizeof(int);
324
325 #ifdef SO_REUSEPORT_LB
326
327 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT_LB,
328 (void *) &reuseport, &olen)
329 == -1)
330 {
331 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
332 "getsockopt(SO_REUSEPORT_LB) %V failed, ignored",
333 &ls[i].addr_text);
334
335 } else {
336 ls[i].reuseport = reuseport ? 1 : 0;
337 }
338
339 #else
340
341 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
342 (void *) &reuseport, &olen)
343 == -1)
344 {
345 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
346 "getsockopt(SO_REUSEPORT) %V failed, ignored",
347 &ls[i].addr_text);
348
349 } else {
350 ls[i].reuseport = reuseport ? 1 : 0;
351 }
352 #endif
353
354 #endif
355
356 if (ls[i].type != SOCK_STREAM) {
357 continue;
358 }
359
360 #if (NGX_HAVE_TCP_FASTOPEN)
361
362 olen = sizeof(int);
363
364 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
365 (void *) &ls[i].fastopen, &olen)
366 == -1)
367 {
368 err = ngx_socket_errno;
369
370 if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT
371 && err != NGX_EINVAL)
372 {
373 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
374 "getsockopt(TCP_FASTOPEN) %V failed, ignored",
375 &ls[i].addr_text);
376 }
377
378 ls[i].fastopen = -1;
379 }
380
381 #endif
382
383 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
384
385 ngx_memzero(&af, sizeof(struct accept_filter_arg));
386 olen = sizeof(struct accept_filter_arg);
387
388 if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
389 == -1)
390 {
391 err = ngx_socket_errno;
392
393 if (err == NGX_EINVAL) {
394 continue;
395 }
396
397 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
398 "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
399 &ls[i].addr_text);
400 continue;
401 }
402
403 if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
404 continue;
405 }
406
407 ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
408 if (ls[i].accept_filter == NULL) {
409 return NGX_ERROR;
410 }
411
412 (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
413 (u_char *) af.af_name, 16);
414 #endif
415
416 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
417
418 timeout = 0;
419 olen = sizeof(int);
420
421 if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
422 == -1)
423 {
424 err = ngx_socket_errno;
425
426 if (err == NGX_EOPNOTSUPP) {
427 continue;
428 }
429
430 ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
431 "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
432 &ls[i].addr_text);
433 continue;
434 }
435
436 if (olen < sizeof(int) || timeout == 0) {
437 continue;
438 }
439
440 ls[i].deferred_accept = 1;
441 #endif
442 }
443
444 return NGX_OK;
445 }
446
447
448 ngx_int_t
ngx_open_listening_sockets(ngx_cycle_t * cycle)449 ngx_open_listening_sockets(ngx_cycle_t *cycle)
450 {
451 int reuseaddr;
452 ngx_uint_t i, tries, failed;
453 ngx_err_t err;
454 ngx_log_t *log;
455 ngx_socket_t s;
456 ngx_listening_t *ls;
457
458 #if (NGX_HAVE_FSTACK)
459 int type;
460 #endif
461
462 reuseaddr = 1;
463 #if (NGX_SUPPRESS_WARN)
464 failed = 0;
465 #endif
466
467 log = cycle->log;
468
469 /* TODO: configurable try number */
470
471 for (tries = 5; tries; tries--) {
472 failed = 0;
473
474 /* for each listening socket */
475
476 ls = cycle->listening.elts;
477 for (i = 0; i < cycle->listening.nelts; i++) {
478
479 #if (NGX_HAVE_FSTACK)
480 type = ls[i].type;
481 if(ngx_ff_skip_listening_socket(cycle, &ls[i], &type)){
482 continue;
483 }
484 #endif
485
486 if (ls[i].ignore) {
487 continue;
488 }
489
490 #if (NGX_HAVE_REUSEPORT)
491
492 if (ls[i].add_reuseport) {
493
494 /*
495 * to allow transition from a socket without SO_REUSEPORT
496 * to multiple sockets with SO_REUSEPORT, we have to set
497 * SO_REUSEPORT on the old socket before opening new ones
498 */
499
500 int reuseport = 1;
501
502 #ifdef SO_REUSEPORT_LB
503
504 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT_LB,
505 (const void *) &reuseport, sizeof(int))
506 == -1)
507 {
508 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
509 "setsockopt(SO_REUSEPORT_LB) %V failed, "
510 "ignored",
511 &ls[i].addr_text);
512 }
513
514 #else
515
516 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
517 (const void *) &reuseport, sizeof(int))
518 == -1)
519 {
520 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
521 "setsockopt(SO_REUSEPORT) %V failed, ignored",
522 &ls[i].addr_text);
523 }
524 #endif
525
526 ls[i].add_reuseport = 0;
527 }
528 #endif
529
530 if (ls[i].fd != (ngx_socket_t) -1) {
531 continue;
532 }
533
534 if (ls[i].inherited) {
535
536 /* TODO: close on exit */
537 /* TODO: nonblocking */
538 /* TODO: deferred accept */
539
540 continue;
541 }
542
543 #if (NGX_HAVE_FSTACK)
544 s = ngx_socket(ls[i].sockaddr->sa_family, type, 0);
545 #else
546 s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
547 #endif
548
549 if (s == (ngx_socket_t) -1) {
550 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
551 ngx_socket_n " %V failed", &ls[i].addr_text);
552 return NGX_ERROR;
553 }
554
555 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
556 (const void *) &reuseaddr, sizeof(int))
557 == -1)
558 {
559 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
560 "setsockopt(SO_REUSEADDR) %V failed",
561 &ls[i].addr_text);
562
563 if (ngx_close_socket(s) == -1) {
564 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
565 ngx_close_socket_n " %V failed",
566 &ls[i].addr_text);
567 }
568
569 return NGX_ERROR;
570 }
571
572 #if (NGX_HAVE_REUSEPORT)
573
574 if (ls[i].reuseport && !ngx_test_config) {
575 int reuseport;
576
577 reuseport = 1;
578
579 #ifdef SO_REUSEPORT_LB
580
581 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB,
582 (const void *) &reuseport, sizeof(int))
583 == -1)
584 {
585 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
586 "setsockopt(SO_REUSEPORT_LB) %V failed",
587 &ls[i].addr_text);
588
589 if (ngx_close_socket(s) == -1) {
590 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
591 ngx_close_socket_n " %V failed",
592 &ls[i].addr_text);
593 }
594
595 return NGX_ERROR;
596 }
597
598 #else
599
600 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
601 (const void *) &reuseport, sizeof(int))
602 == -1)
603 {
604 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
605 "setsockopt(SO_REUSEPORT) %V failed",
606 &ls[i].addr_text);
607
608 if (ngx_close_socket(s) == -1) {
609 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
610 ngx_close_socket_n " %V failed",
611 &ls[i].addr_text);
612 }
613
614 return NGX_ERROR;
615 }
616 #endif
617 }
618 #endif
619
620 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
621
622 if (ls[i].sockaddr->sa_family == AF_INET6) {
623 int ipv6only;
624
625 ipv6only = ls[i].ipv6only;
626
627 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
628 (const void *) &ipv6only, sizeof(int))
629 == -1)
630 {
631 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
632 "setsockopt(IPV6_V6ONLY) %V failed, ignored",
633 &ls[i].addr_text);
634 }
635 }
636 #endif
637 /* TODO: close on exit */
638
639 if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
640 if (ngx_nonblocking(s) == -1) {
641 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
642 ngx_nonblocking_n " %V failed",
643 &ls[i].addr_text);
644
645 if (ngx_close_socket(s) == -1) {
646 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
647 ngx_close_socket_n " %V failed",
648 &ls[i].addr_text);
649 }
650
651 return NGX_ERROR;
652 }
653 }
654
655 ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
656 "bind() %V #%d ", &ls[i].addr_text, s);
657
658 if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
659 err = ngx_socket_errno;
660
661 if (err != NGX_EADDRINUSE || !ngx_test_config) {
662 ngx_log_error(NGX_LOG_EMERG, log, err,
663 "bind() to %V failed", &ls[i].addr_text);
664 }
665
666 if (ngx_close_socket(s) == -1) {
667 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
668 ngx_close_socket_n " %V failed",
669 &ls[i].addr_text);
670 }
671
672 if (err != NGX_EADDRINUSE) {
673 return NGX_ERROR;
674 }
675
676 if (!ngx_test_config) {
677 failed = 1;
678 }
679
680 continue;
681 }
682
683 #if (NGX_HAVE_UNIX_DOMAIN)
684
685 if (ls[i].sockaddr->sa_family == AF_UNIX) {
686 mode_t mode;
687 u_char *name;
688
689 name = ls[i].addr_text.data + sizeof("unix:") - 1;
690 mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
691
692 if (chmod((char *) name, mode) == -1) {
693 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
694 "chmod() \"%s\" failed", name);
695 }
696
697 if (ngx_test_config) {
698 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
699 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
700 ngx_delete_file_n " %s failed", name);
701 }
702 }
703 }
704 #endif
705
706 if (ls[i].type != SOCK_STREAM) {
707 ls[i].fd = s;
708 continue;
709 }
710
711 if (listen(s, ls[i].backlog) == -1) {
712 err = ngx_socket_errno;
713
714 /*
715 * on OpenVZ after suspend/resume EADDRINUSE
716 * may be returned by listen() instead of bind(), see
717 * https://bugzilla.openvz.org/show_bug.cgi?id=2470
718 */
719
720 if (err != NGX_EADDRINUSE || !ngx_test_config) {
721 ngx_log_error(NGX_LOG_EMERG, log, err,
722 "listen() to %V, backlog %d failed",
723 &ls[i].addr_text, ls[i].backlog);
724 }
725
726 if (ngx_close_socket(s) == -1) {
727 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
728 ngx_close_socket_n " %V failed",
729 &ls[i].addr_text);
730 }
731
732 if (err != NGX_EADDRINUSE) {
733 return NGX_ERROR;
734 }
735
736 if (!ngx_test_config) {
737 failed = 1;
738 }
739
740 continue;
741 }
742
743 ls[i].listen = 1;
744
745 ls[i].fd = s;
746 }
747
748 if (!failed) {
749 break;
750 }
751
752 /* TODO: delay configurable */
753
754 ngx_log_error(NGX_LOG_NOTICE, log, 0,
755 "try again to bind() after 500ms");
756
757 ngx_msleep(500);
758 }
759
760 if (failed) {
761 ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
762 return NGX_ERROR;
763 }
764
765 return NGX_OK;
766 }
767
768
769 void
ngx_configure_listening_sockets(ngx_cycle_t * cycle)770 ngx_configure_listening_sockets(ngx_cycle_t *cycle)
771 {
772 int value;
773 ngx_uint_t i;
774 ngx_listening_t *ls;
775
776 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
777 struct accept_filter_arg af;
778 #endif
779
780 ls = cycle->listening.elts;
781 for (i = 0; i < cycle->listening.nelts; i++) {
782
783 #if (NGX_HAVE_FSTACK)
784 if(ngx_ff_skip_listening_socket(cycle, &ls[i], NULL)){
785 continue;
786 }
787 #endif
788
789 ls[i].log = *ls[i].logp;
790
791 if (ls[i].rcvbuf != -1) {
792 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
793 (const void *) &ls[i].rcvbuf, sizeof(int))
794 == -1)
795 {
796 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
797 "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
798 ls[i].rcvbuf, &ls[i].addr_text);
799 }
800 }
801
802 if (ls[i].sndbuf != -1) {
803 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
804 (const void *) &ls[i].sndbuf, sizeof(int))
805 == -1)
806 {
807 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
808 "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
809 ls[i].sndbuf, &ls[i].addr_text);
810 }
811 }
812
813 if (ls[i].keepalive) {
814 value = (ls[i].keepalive == 1) ? 1 : 0;
815
816 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
817 (const void *) &value, sizeof(int))
818 == -1)
819 {
820 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
821 "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
822 value, &ls[i].addr_text);
823 }
824 }
825
826 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
827
828 if (ls[i].keepidle) {
829 value = ls[i].keepidle;
830
831 #if (NGX_KEEPALIVE_FACTOR)
832 value *= NGX_KEEPALIVE_FACTOR;
833 #endif
834
835 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
836 (const void *) &value, sizeof(int))
837 == -1)
838 {
839 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
840 "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
841 value, &ls[i].addr_text);
842 }
843 }
844
845 if (ls[i].keepintvl) {
846 value = ls[i].keepintvl;
847
848 #if (NGX_KEEPALIVE_FACTOR)
849 value *= NGX_KEEPALIVE_FACTOR;
850 #endif
851
852 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
853 (const void *) &value, sizeof(int))
854 == -1)
855 {
856 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
857 "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
858 value, &ls[i].addr_text);
859 }
860 }
861
862 if (ls[i].keepcnt) {
863 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
864 (const void *) &ls[i].keepcnt, sizeof(int))
865 == -1)
866 {
867 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
868 "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
869 ls[i].keepcnt, &ls[i].addr_text);
870 }
871 }
872
873 #endif
874
875 #if (NGX_HAVE_SETFIB)
876 if (ls[i].setfib != -1) {
877 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
878 (const void *) &ls[i].setfib, sizeof(int))
879 == -1)
880 {
881 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
882 "setsockopt(SO_SETFIB, %d) %V failed, ignored",
883 ls[i].setfib, &ls[i].addr_text);
884 }
885 }
886 #endif
887
888 #if (NGX_HAVE_TCP_FASTOPEN)
889 if (ls[i].fastopen != -1) {
890 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
891 (const void *) &ls[i].fastopen, sizeof(int))
892 == -1)
893 {
894 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
895 "setsockopt(TCP_FASTOPEN, %d) %V failed, ignored",
896 ls[i].fastopen, &ls[i].addr_text);
897 }
898 }
899 #endif
900
901 #if 0
902 if (1) {
903 int tcp_nodelay = 1;
904
905 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
906 (const void *) &tcp_nodelay, sizeof(int))
907 == -1)
908 {
909 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
910 "setsockopt(TCP_NODELAY) %V failed, ignored",
911 &ls[i].addr_text);
912 }
913 }
914 #endif
915
916 if (ls[i].listen) {
917
918 /* change backlog via listen() */
919
920 if (listen(ls[i].fd, ls[i].backlog) == -1) {
921 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
922 "listen() to %V, backlog %d failed, ignored",
923 &ls[i].addr_text, ls[i].backlog);
924 }
925 }
926
927 /*
928 * setting deferred mode should be last operation on socket,
929 * because code may prematurely continue cycle on failure
930 */
931
932 #if (NGX_HAVE_DEFERRED_ACCEPT)
933
934 #ifdef SO_ACCEPTFILTER
935
936 if (ls[i].delete_deferred) {
937 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
938 == -1)
939 {
940 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
941 "setsockopt(SO_ACCEPTFILTER, NULL) "
942 "for %V failed, ignored",
943 &ls[i].addr_text);
944
945 if (ls[i].accept_filter) {
946 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
947 "could not change the accept filter "
948 "to \"%s\" for %V, ignored",
949 ls[i].accept_filter, &ls[i].addr_text);
950 }
951
952 continue;
953 }
954
955 ls[i].deferred_accept = 0;
956 }
957
958 if (ls[i].add_deferred) {
959 ngx_memzero(&af, sizeof(struct accept_filter_arg));
960 (void) ngx_cpystrn((u_char *) af.af_name,
961 (u_char *) ls[i].accept_filter, 16);
962
963 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
964 &af, sizeof(struct accept_filter_arg))
965 == -1)
966 {
967 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
968 "setsockopt(SO_ACCEPTFILTER, \"%s\") "
969 "for %V failed, ignored",
970 ls[i].accept_filter, &ls[i].addr_text);
971 continue;
972 }
973
974 ls[i].deferred_accept = 1;
975 }
976
977 #endif
978
979 #ifdef TCP_DEFER_ACCEPT
980
981 if (ls[i].add_deferred || ls[i].delete_deferred) {
982
983 if (ls[i].add_deferred) {
984 /*
985 * There is no way to find out how long a connection was
986 * in queue (and a connection may bypass deferred queue at all
987 * if syncookies were used), hence we use 1 second timeout
988 * here.
989 */
990 value = 1;
991
992 } else {
993 value = 0;
994 }
995
996 if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
997 &value, sizeof(int))
998 == -1)
999 {
1000 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
1001 "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
1002 "ignored",
1003 value, &ls[i].addr_text);
1004
1005 continue;
1006 }
1007 }
1008
1009 if (ls[i].add_deferred) {
1010 ls[i].deferred_accept = 1;
1011 }
1012
1013 #endif
1014
1015 #endif /* NGX_HAVE_DEFERRED_ACCEPT */
1016
1017 #if (NGX_HAVE_IP_RECVDSTADDR)
1018
1019 if (ls[i].wildcard
1020 && ls[i].type == SOCK_DGRAM
1021 && ls[i].sockaddr->sa_family == AF_INET)
1022 {
1023 value = 1;
1024
1025 if (setsockopt(ls[i].fd, IPPROTO_IP, IP_RECVDSTADDR,
1026 (const void *) &value, sizeof(int))
1027 == -1)
1028 {
1029 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
1030 "setsockopt(IP_RECVDSTADDR) "
1031 "for %V failed, ignored",
1032 &ls[i].addr_text);
1033 }
1034 }
1035
1036 /* TODO: configure , auto/feature */
1037 #if !(NGX_HAVE_FSTACK)
1038 #elif (NGX_HAVE_IP_PKTINFO)
1039
1040 if (ls[i].wildcard
1041 && ls[i].type == SOCK_DGRAM
1042 && ls[i].sockaddr->sa_family == AF_INET)
1043 {
1044 value = 1;
1045
1046 if (setsockopt(ls[i].fd, IPPROTO_IP, IP_PKTINFO,
1047 (const void *) &value, sizeof(int))
1048 == -1)
1049 {
1050 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
1051 "setsockopt(IP_PKTINFO) "
1052 "for %V failed, ignored",
1053 &ls[i].addr_text);
1054 }
1055 }
1056 #endif /* NGX_HAVE_FSTACK */
1057 #endif
1058
1059 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
1060
1061 if (ls[i].wildcard
1062 && ls[i].type == SOCK_DGRAM
1063 && ls[i].sockaddr->sa_family == AF_INET6)
1064 {
1065 value = 1;
1066
1067 if (setsockopt(ls[i].fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
1068 (const void *) &value, sizeof(int))
1069 == -1)
1070 {
1071 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
1072 "setsockopt(IPV6_RECVPKTINFO) "
1073 "for %V failed, ignored",
1074 &ls[i].addr_text);
1075 }
1076 }
1077
1078 #endif
1079 }
1080
1081 return;
1082 }
1083
1084
1085 void
ngx_close_listening_sockets(ngx_cycle_t * cycle)1086 ngx_close_listening_sockets(ngx_cycle_t *cycle)
1087 {
1088 ngx_uint_t i;
1089 ngx_listening_t *ls;
1090 ngx_connection_t *c;
1091
1092 if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
1093 return;
1094 }
1095
1096 ngx_accept_mutex_held = 0;
1097 ngx_use_accept_mutex = 0;
1098
1099 ls = cycle->listening.elts;
1100 for (i = 0; i < cycle->listening.nelts; i++) {
1101
1102 c = ls[i].connection;
1103
1104 if (c) {
1105 if (c->read->active) {
1106 if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
1107
1108 /*
1109 * it seems that Linux-2.6.x OpenVZ sends events
1110 * for closed shared listening sockets unless
1111 * the events was explicitly deleted
1112 */
1113
1114 ngx_del_event(c->read, NGX_READ_EVENT, 0);
1115
1116 } else {
1117 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1118 }
1119 }
1120
1121 ngx_free_connection(c);
1122
1123 c->fd = (ngx_socket_t) -1;
1124 }
1125
1126 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
1127 "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
1128
1129 #if (NGX_HAVE_FSTACK)
1130 if(ls[i].fd != (ngx_socket_t) -1) {
1131 if (ngx_close_socket(ls[i].fd) == -1) {
1132 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1133 ngx_close_socket_n " %V failed", &ls[i].addr_text);
1134 }
1135 }
1136 #else
1137 if (ngx_close_socket(ls[i].fd) == -1) {
1138 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1139 ngx_close_socket_n " %V failed", &ls[i].addr_text);
1140 }
1141 #endif //(NGX_HAVE_FSTACK)
1142
1143 #if (NGX_HAVE_UNIX_DOMAIN)
1144
1145 if (ls[i].sockaddr->sa_family == AF_UNIX
1146 && ngx_process <= NGX_PROCESS_MASTER
1147 && ngx_new_binary == 0)
1148 {
1149 u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
1150
1151 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1152 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1153 ngx_delete_file_n " %s failed", name);
1154 }
1155 }
1156
1157 #endif
1158
1159 ls[i].fd = (ngx_socket_t) -1;
1160 }
1161
1162 cycle->listening.nelts = 0;
1163 }
1164
1165
1166 ngx_connection_t *
ngx_get_connection(ngx_socket_t s,ngx_log_t * log)1167 ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
1168 {
1169 ngx_uint_t instance;
1170 ngx_event_t *rev, *wev;
1171 ngx_connection_t *c;
1172
1173 /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
1174
1175 if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
1176 ngx_log_error(NGX_LOG_ALERT, log, 0,
1177 "the new socket has number %d, "
1178 "but only %ui files are available",
1179 s, ngx_cycle->files_n);
1180 return NULL;
1181 }
1182
1183 c = ngx_cycle->free_connections;
1184
1185 if (c == NULL) {
1186 ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
1187 c = ngx_cycle->free_connections;
1188 }
1189
1190 if (c == NULL) {
1191 ngx_log_error(NGX_LOG_ALERT, log, 0,
1192 "%ui worker_connections are not enough",
1193 ngx_cycle->connection_n);
1194
1195 return NULL;
1196 }
1197
1198 ngx_cycle->free_connections = c->data;
1199 ngx_cycle->free_connection_n--;
1200
1201 if (ngx_cycle->files && ngx_cycle->files[s] == NULL) {
1202 ngx_cycle->files[s] = c;
1203 }
1204
1205 rev = c->read;
1206 wev = c->write;
1207
1208 ngx_memzero(c, sizeof(ngx_connection_t));
1209
1210 c->read = rev;
1211 c->write = wev;
1212 c->fd = s;
1213 c->log = log;
1214
1215 instance = rev->instance;
1216
1217 ngx_memzero(rev, sizeof(ngx_event_t));
1218 ngx_memzero(wev, sizeof(ngx_event_t));
1219
1220 rev->instance = !instance;
1221 wev->instance = !instance;
1222
1223 rev->index = NGX_INVALID_INDEX;
1224 wev->index = NGX_INVALID_INDEX;
1225
1226 rev->data = c;
1227 wev->data = c;
1228
1229 wev->write = 1;
1230
1231 #if (NGX_HAVE_FSTACK)
1232 rev->belong_to_host = wev->belong_to_host = is_fstack_fd(s) ? 0 : 1;
1233 #endif
1234
1235 return c;
1236 }
1237
1238
1239 void
ngx_free_connection(ngx_connection_t * c)1240 ngx_free_connection(ngx_connection_t *c)
1241 {
1242 c->data = ngx_cycle->free_connections;
1243 ngx_cycle->free_connections = c;
1244 ngx_cycle->free_connection_n++;
1245
1246 if (ngx_cycle->files && ngx_cycle->files[c->fd] == c) {
1247 ngx_cycle->files[c->fd] = NULL;
1248 }
1249 }
1250
1251
1252 void
ngx_close_connection(ngx_connection_t * c)1253 ngx_close_connection(ngx_connection_t *c)
1254 {
1255 ngx_err_t err;
1256 ngx_uint_t log_error, level;
1257 ngx_socket_t fd;
1258
1259 if (c->fd == (ngx_socket_t) -1) {
1260 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
1261 return;
1262 }
1263
1264 if (c->read->timer_set) {
1265 ngx_del_timer(c->read);
1266 }
1267
1268 if (c->write->timer_set) {
1269 ngx_del_timer(c->write);
1270 }
1271
1272 if (!c->shared) {
1273 #if (NGX_HAVE_FSTACK)
1274 if (ngx_event_actions.del_conn) {
1275 #else
1276 if (ngx_del_conn) {
1277 #endif
1278 ngx_del_conn(c, NGX_CLOSE_EVENT);
1279
1280 } else {
1281 if (c->read->active || c->read->disabled) {
1282 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1283 }
1284
1285 if (c->write->active || c->write->disabled) {
1286 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
1287 }
1288 }
1289 }
1290
1291 if (c->read->posted) {
1292 ngx_delete_posted_event(c->read);
1293 }
1294
1295 if (c->write->posted) {
1296 ngx_delete_posted_event(c->write);
1297 }
1298
1299 c->read->closed = 1;
1300 c->write->closed = 1;
1301
1302 ngx_reusable_connection(c, 0);
1303
1304 log_error = c->log_error;
1305
1306 ngx_free_connection(c);
1307
1308 fd = c->fd;
1309 c->fd = (ngx_socket_t) -1;
1310
1311 if (c->shared) {
1312 return;
1313 }
1314
1315 if (ngx_close_socket(fd) == -1) {
1316
1317 err = ngx_socket_errno;
1318
1319 if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
1320
1321 switch (log_error) {
1322
1323 case NGX_ERROR_INFO:
1324 level = NGX_LOG_INFO;
1325 break;
1326
1327 case NGX_ERROR_ERR:
1328 level = NGX_LOG_ERR;
1329 break;
1330
1331 default:
1332 level = NGX_LOG_CRIT;
1333 }
1334
1335 } else {
1336 level = NGX_LOG_CRIT;
1337 }
1338
1339 ngx_log_error(level, c->log, err, ngx_close_socket_n " %d failed", fd);
1340 }
1341 }
1342
1343
1344 void
1345 ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
1346 {
1347 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
1348 "reusable connection: %ui", reusable);
1349
1350 if (c->reusable) {
1351 ngx_queue_remove(&c->queue);
1352 ngx_cycle->reusable_connections_n--;
1353
1354 #if (NGX_STAT_STUB)
1355 (void) ngx_atomic_fetch_add(ngx_stat_waiting, -1);
1356 #endif
1357 }
1358
1359 c->reusable = reusable;
1360
1361 if (reusable) {
1362 /* need cast as ngx_cycle is volatile */
1363
1364 ngx_queue_insert_head(
1365 (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
1366 ngx_cycle->reusable_connections_n++;
1367
1368 #if (NGX_STAT_STUB)
1369 (void) ngx_atomic_fetch_add(ngx_stat_waiting, 1);
1370 #endif
1371 }
1372 }
1373
1374
1375 static void
1376 ngx_drain_connections(ngx_cycle_t *cycle)
1377 {
1378 ngx_uint_t i, n;
1379 ngx_queue_t *q;
1380 ngx_connection_t *c;
1381
1382 n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
1383
1384 for (i = 0; i < n; i++) {
1385 if (ngx_queue_empty(&cycle->reusable_connections_queue)) {
1386 break;
1387 }
1388
1389 q = ngx_queue_last(&cycle->reusable_connections_queue);
1390 c = ngx_queue_data(q, ngx_connection_t, queue);
1391
1392 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
1393 "reusing connection");
1394
1395 c->close = 1;
1396 c->read->handler(c->read);
1397 }
1398 }
1399
1400
1401 void
1402 ngx_close_idle_connections(ngx_cycle_t *cycle)
1403 {
1404 ngx_uint_t i;
1405 ngx_connection_t *c;
1406
1407 c = cycle->connections;
1408
1409 for (i = 0; i < cycle->connection_n; i++) {
1410
1411 /* THREAD: lock */
1412
1413 if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
1414 c[i].close = 1;
1415 c[i].read->handler(c[i].read);
1416 }
1417 }
1418 }
1419
1420
1421 ngx_int_t
1422 ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
1423 ngx_uint_t port)
1424 {
1425 socklen_t len;
1426 ngx_uint_t addr;
1427 ngx_sockaddr_t sa;
1428 struct sockaddr_in *sin;
1429 #if (NGX_HAVE_INET6)
1430 ngx_uint_t i;
1431 struct sockaddr_in6 *sin6;
1432 #endif
1433
1434 addr = 0;
1435
1436 if (c->local_socklen) {
1437 switch (c->local_sockaddr->sa_family) {
1438
1439 #if (NGX_HAVE_INET6)
1440 case AF_INET6:
1441 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
1442
1443 for (i = 0; addr == 0 && i < 16; i++) {
1444 addr |= sin6->sin6_addr.s6_addr[i];
1445 }
1446
1447 break;
1448 #endif
1449
1450 #if (NGX_HAVE_UNIX_DOMAIN)
1451 case AF_UNIX:
1452 addr = 1;
1453 break;
1454 #endif
1455
1456 default: /* AF_INET */
1457 sin = (struct sockaddr_in *) c->local_sockaddr;
1458 addr = sin->sin_addr.s_addr;
1459 break;
1460 }
1461 }
1462
1463 if (addr == 0) {
1464
1465 len = sizeof(ngx_sockaddr_t);
1466
1467 if (getsockname(c->fd, &sa.sockaddr, &len) == -1) {
1468 ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1469 return NGX_ERROR;
1470 }
1471
1472 c->local_sockaddr = ngx_palloc(c->pool, len);
1473 if (c->local_sockaddr == NULL) {
1474 return NGX_ERROR;
1475 }
1476
1477 ngx_memcpy(c->local_sockaddr, &sa, len);
1478
1479 c->local_socklen = len;
1480 }
1481
1482 if (s == NULL) {
1483 return NGX_OK;
1484 }
1485
1486 s->len = ngx_sock_ntop(c->local_sockaddr, c->local_socklen,
1487 s->data, s->len, port);
1488
1489 return NGX_OK;
1490 }
1491
1492
1493 ngx_int_t
1494 ngx_tcp_nodelay(ngx_connection_t *c)
1495 {
1496 int tcp_nodelay;
1497
1498 if (c->tcp_nodelay != NGX_TCP_NODELAY_UNSET) {
1499 return NGX_OK;
1500 }
1501
1502 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "tcp_nodelay");
1503
1504 tcp_nodelay = 1;
1505
1506 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1507 (const void *) &tcp_nodelay, sizeof(int))
1508 == -1)
1509 {
1510 #if (NGX_SOLARIS)
1511 if (c->log_error == NGX_ERROR_INFO) {
1512
1513 /* Solaris returns EINVAL if a socket has been shut down */
1514 c->log_error = NGX_ERROR_IGNORE_EINVAL;
1515
1516 ngx_connection_error(c, ngx_socket_errno,
1517 "setsockopt(TCP_NODELAY) failed");
1518
1519 c->log_error = NGX_ERROR_INFO;
1520
1521 return NGX_ERROR;
1522 }
1523 #endif
1524
1525 ngx_connection_error(c, ngx_socket_errno,
1526 "setsockopt(TCP_NODELAY) failed");
1527 return NGX_ERROR;
1528 }
1529
1530 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1531
1532 return NGX_OK;
1533 }
1534
1535
1536 ngx_int_t
1537 ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
1538 {
1539 ngx_uint_t level;
1540
1541 /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
1542
1543 if ((err == NGX_ECONNRESET
1544 #if (NGX_WIN32)
1545 || err == NGX_ECONNABORTED
1546 #endif
1547 ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
1548 {
1549 return 0;
1550 }
1551
1552 #if (NGX_SOLARIS)
1553 if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
1554 return 0;
1555 }
1556 #endif
1557
1558 if (err == 0
1559 || err == NGX_ECONNRESET
1560 #if (NGX_WIN32)
1561 || err == NGX_ECONNABORTED
1562 #else
1563 || err == NGX_EPIPE
1564 #endif
1565 || err == NGX_ENOTCONN
1566 || err == NGX_ETIMEDOUT
1567 || err == NGX_ECONNREFUSED
1568 || err == NGX_ENETDOWN
1569 || err == NGX_ENETUNREACH
1570 || err == NGX_EHOSTDOWN
1571 || err == NGX_EHOSTUNREACH)
1572 {
1573 switch (c->log_error) {
1574
1575 case NGX_ERROR_IGNORE_EINVAL:
1576 case NGX_ERROR_IGNORE_ECONNRESET:
1577 case NGX_ERROR_INFO:
1578 level = NGX_LOG_INFO;
1579 break;
1580
1581 default:
1582 level = NGX_LOG_ERR;
1583 }
1584
1585 } else {
1586 level = NGX_LOG_ALERT;
1587 }
1588
1589 ngx_log_error(level, c->log, err, text);
1590
1591 return NGX_ERROR;
1592 }
1593