Annotation of embedaddon/nginx/src/core/ngx_connection.c, revision 1.1
1.1 ! misho 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: ngx_os_io_t ngx_io;
! 14:
! 15:
! 16: static void ngx_drain_connections(void);
! 17:
! 18:
! 19: ngx_listening_t *
! 20: ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
! 21: {
! 22: size_t len;
! 23: ngx_listening_t *ls;
! 24: struct sockaddr *sa;
! 25: u_char text[NGX_SOCKADDR_STRLEN];
! 26:
! 27: ls = ngx_array_push(&cf->cycle->listening);
! 28: if (ls == NULL) {
! 29: return NULL;
! 30: }
! 31:
! 32: ngx_memzero(ls, sizeof(ngx_listening_t));
! 33:
! 34: sa = ngx_palloc(cf->pool, socklen);
! 35: if (sa == NULL) {
! 36: return NULL;
! 37: }
! 38:
! 39: ngx_memcpy(sa, sockaddr, socklen);
! 40:
! 41: ls->sockaddr = sa;
! 42: ls->socklen = socklen;
! 43:
! 44: len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
! 45: ls->addr_text.len = len;
! 46:
! 47: switch (ls->sockaddr->sa_family) {
! 48: #if (NGX_HAVE_INET6)
! 49: case AF_INET6:
! 50: ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
! 51: break;
! 52: #endif
! 53: #if (NGX_HAVE_UNIX_DOMAIN)
! 54: case AF_UNIX:
! 55: ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
! 56: len++;
! 57: break;
! 58: #endif
! 59: case AF_INET:
! 60: ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
! 61: break;
! 62: default:
! 63: ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
! 64: break;
! 65: }
! 66:
! 67: ls->addr_text.data = ngx_pnalloc(cf->pool, len);
! 68: if (ls->addr_text.data == NULL) {
! 69: return NULL;
! 70: }
! 71:
! 72: ngx_memcpy(ls->addr_text.data, text, len);
! 73:
! 74: ls->fd = (ngx_socket_t) -1;
! 75: ls->type = SOCK_STREAM;
! 76:
! 77: ls->backlog = NGX_LISTEN_BACKLOG;
! 78: ls->rcvbuf = -1;
! 79: ls->sndbuf = -1;
! 80:
! 81: #if (NGX_HAVE_SETFIB)
! 82: ls->setfib = -1;
! 83: #endif
! 84:
! 85: return ls;
! 86: }
! 87:
! 88:
! 89: ngx_int_t
! 90: ngx_set_inherited_sockets(ngx_cycle_t *cycle)
! 91: {
! 92: size_t len;
! 93: ngx_uint_t i;
! 94: ngx_listening_t *ls;
! 95: socklen_t olen;
! 96: #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
! 97: ngx_err_t err;
! 98: struct accept_filter_arg af;
! 99: #endif
! 100: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
! 101: int timeout;
! 102: #endif
! 103:
! 104: ls = cycle->listening.elts;
! 105: for (i = 0; i < cycle->listening.nelts; i++) {
! 106:
! 107: ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN);
! 108: if (ls[i].sockaddr == NULL) {
! 109: return NGX_ERROR;
! 110: }
! 111:
! 112: ls[i].socklen = NGX_SOCKADDRLEN;
! 113: if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
! 114: ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
! 115: "getsockname() of the inherited "
! 116: "socket #%d failed", ls[i].fd);
! 117: ls[i].ignore = 1;
! 118: continue;
! 119: }
! 120:
! 121: switch (ls[i].sockaddr->sa_family) {
! 122:
! 123: #if (NGX_HAVE_INET6)
! 124: case AF_INET6:
! 125: ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
! 126: len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
! 127: break;
! 128: #endif
! 129:
! 130: #if (NGX_HAVE_UNIX_DOMAIN)
! 131: case AF_UNIX:
! 132: ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
! 133: len = NGX_UNIX_ADDRSTRLEN;
! 134: break;
! 135: #endif
! 136:
! 137: case AF_INET:
! 138: ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
! 139: len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
! 140: break;
! 141:
! 142: default:
! 143: ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
! 144: "the inherited socket #%d has "
! 145: "an unsupported protocol family", ls[i].fd);
! 146: ls[i].ignore = 1;
! 147: continue;
! 148: }
! 149:
! 150: ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
! 151: if (ls[i].addr_text.data == NULL) {
! 152: return NGX_ERROR;
! 153: }
! 154:
! 155: len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data, len, 1);
! 156: if (len == 0) {
! 157: return NGX_ERROR;
! 158: }
! 159:
! 160: ls[i].addr_text.len = len;
! 161:
! 162: ls[i].backlog = NGX_LISTEN_BACKLOG;
! 163:
! 164: olen = sizeof(int);
! 165:
! 166: if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
! 167: &olen)
! 168: == -1)
! 169: {
! 170: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 171: "getsockopt(SO_RCVBUF) %V failed, ignored",
! 172: &ls[i].addr_text);
! 173:
! 174: ls[i].rcvbuf = -1;
! 175: }
! 176:
! 177: olen = sizeof(int);
! 178:
! 179: if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
! 180: &olen)
! 181: == -1)
! 182: {
! 183: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 184: "getsockopt(SO_SNDBUF) %V failed, ignored",
! 185: &ls[i].addr_text);
! 186:
! 187: ls[i].sndbuf = -1;
! 188: }
! 189:
! 190: #if 0
! 191: /* SO_SETFIB is currently a set only option */
! 192:
! 193: #if (NGX_HAVE_SETFIB)
! 194:
! 195: if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB,
! 196: (void *) &ls[i].setfib, &olen)
! 197: == -1)
! 198: {
! 199: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 200: "getsockopt(SO_SETFIB) %V failed, ignored",
! 201: &ls[i].addr_text);
! 202:
! 203: ls[i].setfib = -1;
! 204: }
! 205:
! 206: #endif
! 207: #endif
! 208:
! 209: #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
! 210:
! 211: ngx_memzero(&af, sizeof(struct accept_filter_arg));
! 212: olen = sizeof(struct accept_filter_arg);
! 213:
! 214: if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
! 215: == -1)
! 216: {
! 217: err = ngx_errno;
! 218:
! 219: if (err == NGX_EINVAL) {
! 220: continue;
! 221: }
! 222:
! 223: ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
! 224: "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
! 225: &ls[i].addr_text);
! 226: continue;
! 227: }
! 228:
! 229: if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
! 230: continue;
! 231: }
! 232:
! 233: ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
! 234: if (ls[i].accept_filter == NULL) {
! 235: return NGX_ERROR;
! 236: }
! 237:
! 238: (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
! 239: (u_char *) af.af_name, 16);
! 240: #endif
! 241:
! 242: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
! 243:
! 244: timeout = 0;
! 245: olen = sizeof(int);
! 246:
! 247: if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
! 248: == -1)
! 249: {
! 250: ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
! 251: "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
! 252: &ls[i].addr_text);
! 253: continue;
! 254: }
! 255:
! 256: if (olen < sizeof(int) || timeout == 0) {
! 257: continue;
! 258: }
! 259:
! 260: ls[i].deferred_accept = 1;
! 261: #endif
! 262: }
! 263:
! 264: return NGX_OK;
! 265: }
! 266:
! 267:
! 268: ngx_int_t
! 269: ngx_open_listening_sockets(ngx_cycle_t *cycle)
! 270: {
! 271: int reuseaddr;
! 272: ngx_uint_t i, tries, failed;
! 273: ngx_err_t err;
! 274: ngx_log_t *log;
! 275: ngx_socket_t s;
! 276: ngx_listening_t *ls;
! 277:
! 278: reuseaddr = 1;
! 279: #if (NGX_SUPPRESS_WARN)
! 280: failed = 0;
! 281: #endif
! 282:
! 283: log = cycle->log;
! 284:
! 285: /* TODO: configurable try number */
! 286:
! 287: for (tries = 5; tries; tries--) {
! 288: failed = 0;
! 289:
! 290: /* for each listening socket */
! 291:
! 292: ls = cycle->listening.elts;
! 293: for (i = 0; i < cycle->listening.nelts; i++) {
! 294:
! 295: if (ls[i].ignore) {
! 296: continue;
! 297: }
! 298:
! 299: if (ls[i].fd != -1) {
! 300: continue;
! 301: }
! 302:
! 303: if (ls[i].inherited) {
! 304:
! 305: /* TODO: close on exit */
! 306: /* TODO: nonblocking */
! 307: /* TODO: deferred accept */
! 308:
! 309: continue;
! 310: }
! 311:
! 312: s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
! 313:
! 314: if (s == -1) {
! 315: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 316: ngx_socket_n " %V failed", &ls[i].addr_text);
! 317: return NGX_ERROR;
! 318: }
! 319:
! 320: if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
! 321: (const void *) &reuseaddr, sizeof(int))
! 322: == -1)
! 323: {
! 324: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 325: "setsockopt(SO_REUSEADDR) %V failed",
! 326: &ls[i].addr_text);
! 327:
! 328: if (ngx_close_socket(s) == -1) {
! 329: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 330: ngx_close_socket_n " %V failed",
! 331: &ls[i].addr_text);
! 332: }
! 333:
! 334: return NGX_ERROR;
! 335: }
! 336:
! 337: #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
! 338:
! 339: if (ls[i].sockaddr->sa_family == AF_INET6) {
! 340: int ipv6only;
! 341:
! 342: ipv6only = ls[i].ipv6only;
! 343:
! 344: if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
! 345: (const void *) &ipv6only, sizeof(int))
! 346: == -1)
! 347: {
! 348: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 349: "setsockopt(IPV6_V6ONLY) %V failed, ignored",
! 350: &ls[i].addr_text);
! 351: }
! 352: }
! 353: #endif
! 354: /* TODO: close on exit */
! 355:
! 356: if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
! 357: if (ngx_nonblocking(s) == -1) {
! 358: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 359: ngx_nonblocking_n " %V failed",
! 360: &ls[i].addr_text);
! 361:
! 362: if (ngx_close_socket(s) == -1) {
! 363: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 364: ngx_close_socket_n " %V failed",
! 365: &ls[i].addr_text);
! 366: }
! 367:
! 368: return NGX_ERROR;
! 369: }
! 370: }
! 371:
! 372: ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
! 373: "bind() %V #%d ", &ls[i].addr_text, s);
! 374:
! 375: if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
! 376: err = ngx_socket_errno;
! 377:
! 378: if (err == NGX_EADDRINUSE && ngx_test_config) {
! 379: continue;
! 380: }
! 381:
! 382: ngx_log_error(NGX_LOG_EMERG, log, err,
! 383: "bind() to %V failed", &ls[i].addr_text);
! 384:
! 385: if (ngx_close_socket(s) == -1) {
! 386: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 387: ngx_close_socket_n " %V failed",
! 388: &ls[i].addr_text);
! 389: }
! 390:
! 391: if (err != NGX_EADDRINUSE) {
! 392: return NGX_ERROR;
! 393: }
! 394:
! 395: failed = 1;
! 396:
! 397: continue;
! 398: }
! 399:
! 400: #if (NGX_HAVE_UNIX_DOMAIN)
! 401:
! 402: if (ls[i].sockaddr->sa_family == AF_UNIX) {
! 403: mode_t mode;
! 404: u_char *name;
! 405:
! 406: name = ls[i].addr_text.data + sizeof("unix:") - 1;
! 407: mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
! 408:
! 409: if (chmod((char *) name, mode) == -1) {
! 410: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 411: "chmod() \"%s\" failed", name);
! 412: }
! 413:
! 414: if (ngx_test_config) {
! 415: if (ngx_delete_file(name) == NGX_FILE_ERROR) {
! 416: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 417: ngx_delete_file_n " %s failed", name);
! 418: }
! 419: }
! 420: }
! 421: #endif
! 422:
! 423: if (listen(s, ls[i].backlog) == -1) {
! 424: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 425: "listen() to %V, backlog %d failed",
! 426: &ls[i].addr_text, ls[i].backlog);
! 427:
! 428: if (ngx_close_socket(s) == -1) {
! 429: ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
! 430: ngx_close_socket_n " %V failed",
! 431: &ls[i].addr_text);
! 432: }
! 433:
! 434: return NGX_ERROR;
! 435: }
! 436:
! 437: ls[i].listen = 1;
! 438:
! 439: ls[i].fd = s;
! 440: }
! 441:
! 442: if (!failed) {
! 443: break;
! 444: }
! 445:
! 446: /* TODO: delay configurable */
! 447:
! 448: ngx_log_error(NGX_LOG_NOTICE, log, 0,
! 449: "try again to bind() after 500ms");
! 450:
! 451: ngx_msleep(500);
! 452: }
! 453:
! 454: if (failed) {
! 455: ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
! 456: return NGX_ERROR;
! 457: }
! 458:
! 459: return NGX_OK;
! 460: }
! 461:
! 462:
! 463: void
! 464: ngx_configure_listening_sockets(ngx_cycle_t *cycle)
! 465: {
! 466: int keepalive;
! 467: ngx_uint_t i;
! 468: ngx_listening_t *ls;
! 469:
! 470: #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
! 471: struct accept_filter_arg af;
! 472: #endif
! 473: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
! 474: int timeout;
! 475: #endif
! 476:
! 477: ls = cycle->listening.elts;
! 478: for (i = 0; i < cycle->listening.nelts; i++) {
! 479:
! 480: ls[i].log = *ls[i].logp;
! 481:
! 482: if (ls[i].rcvbuf != -1) {
! 483: if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
! 484: (const void *) &ls[i].rcvbuf, sizeof(int))
! 485: == -1)
! 486: {
! 487: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 488: "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
! 489: ls[i].rcvbuf, &ls[i].addr_text);
! 490: }
! 491: }
! 492:
! 493: if (ls[i].sndbuf != -1) {
! 494: if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
! 495: (const void *) &ls[i].sndbuf, sizeof(int))
! 496: == -1)
! 497: {
! 498: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 499: "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
! 500: ls[i].sndbuf, &ls[i].addr_text);
! 501: }
! 502: }
! 503:
! 504: if (ls[i].keepalive) {
! 505: keepalive = (ls[i].keepalive == 1) ? 1 : 0;
! 506:
! 507: if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
! 508: (const void *) &keepalive, sizeof(int))
! 509: == -1)
! 510: {
! 511: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 512: "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
! 513: keepalive, &ls[i].addr_text);
! 514: }
! 515: }
! 516:
! 517: #if (NGX_HAVE_KEEPALIVE_TUNABLE)
! 518:
! 519: if (ls[i].keepidle) {
! 520: if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
! 521: (const void *) &ls[i].keepidle, sizeof(int))
! 522: == -1)
! 523: {
! 524: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 525: "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
! 526: ls[i].keepidle, &ls[i].addr_text);
! 527: }
! 528: }
! 529:
! 530: if (ls[i].keepintvl) {
! 531: if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
! 532: (const void *) &ls[i].keepintvl, sizeof(int))
! 533: == -1)
! 534: {
! 535: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 536: "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
! 537: ls[i].keepintvl, &ls[i].addr_text);
! 538: }
! 539: }
! 540:
! 541: if (ls[i].keepcnt) {
! 542: if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
! 543: (const void *) &ls[i].keepcnt, sizeof(int))
! 544: == -1)
! 545: {
! 546: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 547: "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
! 548: ls[i].keepcnt, &ls[i].addr_text);
! 549: }
! 550: }
! 551:
! 552: #endif
! 553:
! 554: #if (NGX_HAVE_SETFIB)
! 555: if (ls[i].setfib != -1) {
! 556: if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
! 557: (const void *) &ls[i].setfib, sizeof(int))
! 558: == -1)
! 559: {
! 560: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 561: "setsockopt(SO_SETFIB, %d) %V failed, ignored",
! 562: ls[i].setfib, &ls[i].addr_text);
! 563: }
! 564: }
! 565: #endif
! 566:
! 567: #if 0
! 568: if (1) {
! 569: int tcp_nodelay = 1;
! 570:
! 571: if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
! 572: (const void *) &tcp_nodelay, sizeof(int))
! 573: == -1)
! 574: {
! 575: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 576: "setsockopt(TCP_NODELAY) %V failed, ignored",
! 577: &ls[i].addr_text);
! 578: }
! 579: }
! 580: #endif
! 581:
! 582: if (ls[i].listen) {
! 583:
! 584: /* change backlog via listen() */
! 585:
! 586: if (listen(ls[i].fd, ls[i].backlog) == -1) {
! 587: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
! 588: "listen() to %V, backlog %d failed, ignored",
! 589: &ls[i].addr_text, ls[i].backlog);
! 590: }
! 591: }
! 592:
! 593: /*
! 594: * setting deferred mode should be last operation on socket,
! 595: * because code may prematurely continue cycle on failure
! 596: */
! 597:
! 598: #if (NGX_HAVE_DEFERRED_ACCEPT)
! 599:
! 600: #ifdef SO_ACCEPTFILTER
! 601:
! 602: if (ls[i].delete_deferred) {
! 603: if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
! 604: == -1)
! 605: {
! 606: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 607: "setsockopt(SO_ACCEPTFILTER, NULL) "
! 608: "for %V failed, ignored",
! 609: &ls[i].addr_text);
! 610:
! 611: if (ls[i].accept_filter) {
! 612: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
! 613: "could not change the accept filter "
! 614: "to \"%s\" for %V, ignored",
! 615: ls[i].accept_filter, &ls[i].addr_text);
! 616: }
! 617:
! 618: continue;
! 619: }
! 620:
! 621: ls[i].deferred_accept = 0;
! 622: }
! 623:
! 624: if (ls[i].add_deferred) {
! 625: ngx_memzero(&af, sizeof(struct accept_filter_arg));
! 626: (void) ngx_cpystrn((u_char *) af.af_name,
! 627: (u_char *) ls[i].accept_filter, 16);
! 628:
! 629: if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
! 630: &af, sizeof(struct accept_filter_arg))
! 631: == -1)
! 632: {
! 633: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 634: "setsockopt(SO_ACCEPTFILTER, \"%s\") "
! 635: "for %V failed, ignored",
! 636: ls[i].accept_filter, &ls[i].addr_text);
! 637: continue;
! 638: }
! 639:
! 640: ls[i].deferred_accept = 1;
! 641: }
! 642:
! 643: #endif
! 644:
! 645: #ifdef TCP_DEFER_ACCEPT
! 646:
! 647: if (ls[i].add_deferred || ls[i].delete_deferred) {
! 648:
! 649: if (ls[i].add_deferred) {
! 650: timeout = (int) (ls[i].post_accept_timeout / 1000);
! 651:
! 652: } else {
! 653: timeout = 0;
! 654: }
! 655:
! 656: if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
! 657: &timeout, sizeof(int))
! 658: == -1)
! 659: {
! 660: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 661: "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
! 662: "ignored",
! 663: timeout, &ls[i].addr_text);
! 664:
! 665: continue;
! 666: }
! 667: }
! 668:
! 669: if (ls[i].add_deferred) {
! 670: ls[i].deferred_accept = 1;
! 671: }
! 672:
! 673: #endif
! 674:
! 675: #endif /* NGX_HAVE_DEFERRED_ACCEPT */
! 676: }
! 677:
! 678: return;
! 679: }
! 680:
! 681:
! 682: void
! 683: ngx_close_listening_sockets(ngx_cycle_t *cycle)
! 684: {
! 685: ngx_uint_t i;
! 686: ngx_listening_t *ls;
! 687: ngx_connection_t *c;
! 688:
! 689: if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
! 690: return;
! 691: }
! 692:
! 693: ngx_accept_mutex_held = 0;
! 694: ngx_use_accept_mutex = 0;
! 695:
! 696: ls = cycle->listening.elts;
! 697: for (i = 0; i < cycle->listening.nelts; i++) {
! 698:
! 699: c = ls[i].connection;
! 700:
! 701: if (c) {
! 702: if (c->read->active) {
! 703: if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
! 704: ngx_del_conn(c, NGX_CLOSE_EVENT);
! 705:
! 706: } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
! 707:
! 708: /*
! 709: * it seems that Linux-2.6.x OpenVZ sends events
! 710: * for closed shared listening sockets unless
! 711: * the events was explicitly deleted
! 712: */
! 713:
! 714: ngx_del_event(c->read, NGX_READ_EVENT, 0);
! 715:
! 716: } else {
! 717: ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
! 718: }
! 719: }
! 720:
! 721: ngx_free_connection(c);
! 722:
! 723: c->fd = (ngx_socket_t) -1;
! 724: }
! 725:
! 726: ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
! 727: "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
! 728:
! 729: if (ngx_close_socket(ls[i].fd) == -1) {
! 730: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
! 731: ngx_close_socket_n " %V failed", &ls[i].addr_text);
! 732: }
! 733:
! 734: #if (NGX_HAVE_UNIX_DOMAIN)
! 735:
! 736: if (ls[i].sockaddr->sa_family == AF_UNIX
! 737: && ngx_process <= NGX_PROCESS_MASTER
! 738: && ngx_new_binary == 0)
! 739: {
! 740: u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
! 741:
! 742: if (ngx_delete_file(name) == NGX_FILE_ERROR) {
! 743: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
! 744: ngx_delete_file_n " %s failed", name);
! 745: }
! 746: }
! 747:
! 748: #endif
! 749:
! 750: ls[i].fd = (ngx_socket_t) -1;
! 751: }
! 752:
! 753: cycle->listening.nelts = 0;
! 754: }
! 755:
! 756:
! 757: ngx_connection_t *
! 758: ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
! 759: {
! 760: ngx_uint_t instance;
! 761: ngx_event_t *rev, *wev;
! 762: ngx_connection_t *c;
! 763:
! 764: /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
! 765:
! 766: if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
! 767: ngx_log_error(NGX_LOG_ALERT, log, 0,
! 768: "the new socket has number %d, "
! 769: "but only %ui files are available",
! 770: s, ngx_cycle->files_n);
! 771: return NULL;
! 772: }
! 773:
! 774: /* ngx_mutex_lock */
! 775:
! 776: c = ngx_cycle->free_connections;
! 777:
! 778: if (c == NULL) {
! 779: ngx_drain_connections();
! 780: c = ngx_cycle->free_connections;
! 781: }
! 782:
! 783: if (c == NULL) {
! 784: ngx_log_error(NGX_LOG_ALERT, log, 0,
! 785: "%ui worker_connections are not enough",
! 786: ngx_cycle->connection_n);
! 787:
! 788: /* ngx_mutex_unlock */
! 789:
! 790: return NULL;
! 791: }
! 792:
! 793: ngx_cycle->free_connections = c->data;
! 794: ngx_cycle->free_connection_n--;
! 795:
! 796: /* ngx_mutex_unlock */
! 797:
! 798: if (ngx_cycle->files) {
! 799: ngx_cycle->files[s] = c;
! 800: }
! 801:
! 802: rev = c->read;
! 803: wev = c->write;
! 804:
! 805: ngx_memzero(c, sizeof(ngx_connection_t));
! 806:
! 807: c->read = rev;
! 808: c->write = wev;
! 809: c->fd = s;
! 810: c->log = log;
! 811:
! 812: instance = rev->instance;
! 813:
! 814: ngx_memzero(rev, sizeof(ngx_event_t));
! 815: ngx_memzero(wev, sizeof(ngx_event_t));
! 816:
! 817: rev->instance = !instance;
! 818: wev->instance = !instance;
! 819:
! 820: rev->index = NGX_INVALID_INDEX;
! 821: wev->index = NGX_INVALID_INDEX;
! 822:
! 823: rev->data = c;
! 824: wev->data = c;
! 825:
! 826: wev->write = 1;
! 827:
! 828: return c;
! 829: }
! 830:
! 831:
! 832: void
! 833: ngx_free_connection(ngx_connection_t *c)
! 834: {
! 835: /* ngx_mutex_lock */
! 836:
! 837: c->data = ngx_cycle->free_connections;
! 838: ngx_cycle->free_connections = c;
! 839: ngx_cycle->free_connection_n++;
! 840:
! 841: /* ngx_mutex_unlock */
! 842:
! 843: if (ngx_cycle->files) {
! 844: ngx_cycle->files[c->fd] = NULL;
! 845: }
! 846: }
! 847:
! 848:
! 849: void
! 850: ngx_close_connection(ngx_connection_t *c)
! 851: {
! 852: ngx_err_t err;
! 853: ngx_uint_t log_error, level;
! 854: ngx_socket_t fd;
! 855:
! 856: if (c->fd == -1) {
! 857: ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
! 858: return;
! 859: }
! 860:
! 861: if (c->read->timer_set) {
! 862: ngx_del_timer(c->read);
! 863: }
! 864:
! 865: if (c->write->timer_set) {
! 866: ngx_del_timer(c->write);
! 867: }
! 868:
! 869: if (ngx_del_conn) {
! 870: ngx_del_conn(c, NGX_CLOSE_EVENT);
! 871:
! 872: } else {
! 873: if (c->read->active || c->read->disabled) {
! 874: ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
! 875: }
! 876:
! 877: if (c->write->active || c->write->disabled) {
! 878: ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
! 879: }
! 880: }
! 881:
! 882: #if (NGX_THREADS)
! 883:
! 884: /*
! 885: * we have to clean the connection information before the closing
! 886: * because another thread may reopen the same file descriptor
! 887: * before we clean the connection
! 888: */
! 889:
! 890: ngx_mutex_lock(ngx_posted_events_mutex);
! 891:
! 892: if (c->read->prev) {
! 893: ngx_delete_posted_event(c->read);
! 894: }
! 895:
! 896: if (c->write->prev) {
! 897: ngx_delete_posted_event(c->write);
! 898: }
! 899:
! 900: c->read->closed = 1;
! 901: c->write->closed = 1;
! 902:
! 903: ngx_unlock(&c->lock);
! 904: c->read->locked = 0;
! 905: c->write->locked = 0;
! 906:
! 907: ngx_mutex_unlock(ngx_posted_events_mutex);
! 908:
! 909: #else
! 910:
! 911: if (c->read->prev) {
! 912: ngx_delete_posted_event(c->read);
! 913: }
! 914:
! 915: if (c->write->prev) {
! 916: ngx_delete_posted_event(c->write);
! 917: }
! 918:
! 919: c->read->closed = 1;
! 920: c->write->closed = 1;
! 921:
! 922: #endif
! 923:
! 924: ngx_reusable_connection(c, 0);
! 925:
! 926: log_error = c->log_error;
! 927:
! 928: ngx_free_connection(c);
! 929:
! 930: fd = c->fd;
! 931: c->fd = (ngx_socket_t) -1;
! 932:
! 933: if (ngx_close_socket(fd) == -1) {
! 934:
! 935: err = ngx_socket_errno;
! 936:
! 937: if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
! 938:
! 939: switch (log_error) {
! 940:
! 941: case NGX_ERROR_INFO:
! 942: level = NGX_LOG_INFO;
! 943: break;
! 944:
! 945: case NGX_ERROR_ERR:
! 946: level = NGX_LOG_ERR;
! 947: break;
! 948:
! 949: default:
! 950: level = NGX_LOG_CRIT;
! 951: }
! 952:
! 953: } else {
! 954: level = NGX_LOG_CRIT;
! 955: }
! 956:
! 957: /* we use ngx_cycle->log because c->log was in c->pool */
! 958:
! 959: ngx_log_error(level, ngx_cycle->log, err,
! 960: ngx_close_socket_n " %d failed", fd);
! 961: }
! 962: }
! 963:
! 964:
! 965: void
! 966: ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
! 967: {
! 968: ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
! 969: "reusable connection: %ui", reusable);
! 970:
! 971: if (c->reusable) {
! 972: ngx_queue_remove(&c->queue);
! 973:
! 974: #if (NGX_STAT_STUB)
! 975: (void) ngx_atomic_fetch_add(ngx_stat_waiting, -1);
! 976: #endif
! 977: }
! 978:
! 979: c->reusable = reusable;
! 980:
! 981: if (reusable) {
! 982: /* need cast as ngx_cycle is volatile */
! 983:
! 984: ngx_queue_insert_head(
! 985: (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
! 986:
! 987: #if (NGX_STAT_STUB)
! 988: (void) ngx_atomic_fetch_add(ngx_stat_waiting, 1);
! 989: #endif
! 990: }
! 991: }
! 992:
! 993:
! 994: static void
! 995: ngx_drain_connections(void)
! 996: {
! 997: ngx_int_t i;
! 998: ngx_queue_t *q;
! 999: ngx_connection_t *c;
! 1000:
! 1001: for (i = 0; i < 32; i++) {
! 1002: if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) {
! 1003: break;
! 1004: }
! 1005:
! 1006: q = ngx_queue_last(&ngx_cycle->reusable_connections_queue);
! 1007: c = ngx_queue_data(q, ngx_connection_t, queue);
! 1008:
! 1009: ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
! 1010: "reusing connection");
! 1011:
! 1012: c->close = 1;
! 1013: c->read->handler(c->read);
! 1014: }
! 1015: }
! 1016:
! 1017:
! 1018: ngx_int_t
! 1019: ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
! 1020: ngx_uint_t port)
! 1021: {
! 1022: socklen_t len;
! 1023: ngx_uint_t addr;
! 1024: u_char sa[NGX_SOCKADDRLEN];
! 1025: struct sockaddr_in *sin;
! 1026: #if (NGX_HAVE_INET6)
! 1027: ngx_uint_t i;
! 1028: struct sockaddr_in6 *sin6;
! 1029: #endif
! 1030:
! 1031: switch (c->local_sockaddr->sa_family) {
! 1032:
! 1033: #if (NGX_HAVE_INET6)
! 1034: case AF_INET6:
! 1035: sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
! 1036:
! 1037: for (addr = 0, i = 0; addr == 0 && i < 16; i++) {
! 1038: addr |= sin6->sin6_addr.s6_addr[i];
! 1039: }
! 1040:
! 1041: break;
! 1042: #endif
! 1043:
! 1044: default: /* AF_INET */
! 1045: sin = (struct sockaddr_in *) c->local_sockaddr;
! 1046: addr = sin->sin_addr.s_addr;
! 1047: break;
! 1048: }
! 1049:
! 1050: if (addr == 0) {
! 1051:
! 1052: len = NGX_SOCKADDRLEN;
! 1053:
! 1054: if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) {
! 1055: ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
! 1056: return NGX_ERROR;
! 1057: }
! 1058:
! 1059: c->local_sockaddr = ngx_palloc(c->pool, len);
! 1060: if (c->local_sockaddr == NULL) {
! 1061: return NGX_ERROR;
! 1062: }
! 1063:
! 1064: ngx_memcpy(c->local_sockaddr, &sa, len);
! 1065: }
! 1066:
! 1067: if (s == NULL) {
! 1068: return NGX_OK;
! 1069: }
! 1070:
! 1071: s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, port);
! 1072:
! 1073: return NGX_OK;
! 1074: }
! 1075:
! 1076:
! 1077: ngx_int_t
! 1078: ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
! 1079: {
! 1080: ngx_uint_t level;
! 1081:
! 1082: /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
! 1083:
! 1084: if ((err == NGX_ECONNRESET
! 1085: #if (NGX_WIN32)
! 1086: || err == NGX_ECONNABORTED
! 1087: #endif
! 1088: ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
! 1089: {
! 1090: return 0;
! 1091: }
! 1092:
! 1093: #if (NGX_SOLARIS)
! 1094: if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
! 1095: return 0;
! 1096: }
! 1097: #endif
! 1098:
! 1099: if (err == 0
! 1100: || err == NGX_ECONNRESET
! 1101: #if (NGX_WIN32)
! 1102: || err == NGX_ECONNABORTED
! 1103: #else
! 1104: || err == NGX_EPIPE
! 1105: #endif
! 1106: || err == NGX_ENOTCONN
! 1107: || err == NGX_ETIMEDOUT
! 1108: || err == NGX_ECONNREFUSED
! 1109: || err == NGX_ENETDOWN
! 1110: || err == NGX_ENETUNREACH
! 1111: || err == NGX_EHOSTDOWN
! 1112: || err == NGX_EHOSTUNREACH)
! 1113: {
! 1114: switch (c->log_error) {
! 1115:
! 1116: case NGX_ERROR_IGNORE_EINVAL:
! 1117: case NGX_ERROR_IGNORE_ECONNRESET:
! 1118: case NGX_ERROR_INFO:
! 1119: level = NGX_LOG_INFO;
! 1120: break;
! 1121:
! 1122: default:
! 1123: level = NGX_LOG_ERR;
! 1124: }
! 1125:
! 1126: } else {
! 1127: level = NGX_LOG_ALERT;
! 1128: }
! 1129:
! 1130: ngx_log_error(level, c->log, err, text);
! 1131:
! 1132: return NGX_ERROR;
! 1133: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>