Annotation of embedaddon/nginx/src/event/ngx_event_connect.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: #include <ngx_event_connect.h>
        !            12: 
        !            13: 
        !            14: ngx_int_t
        !            15: ngx_event_connect_peer(ngx_peer_connection_t *pc)
        !            16: {
        !            17:     int                rc;
        !            18:     ngx_int_t          event;
        !            19:     ngx_err_t          err;
        !            20:     ngx_uint_t         level;
        !            21:     ngx_socket_t       s;
        !            22:     ngx_event_t       *rev, *wev;
        !            23:     ngx_connection_t  *c;
        !            24: 
        !            25:     rc = pc->get(pc, pc->data);
        !            26:     if (rc != NGX_OK) {
        !            27:         return rc;
        !            28:     }
        !            29: 
        !            30:     s = ngx_socket(pc->sockaddr->sa_family, SOCK_STREAM, 0);
        !            31: 
        !            32:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0, "socket %d", s);
        !            33: 
        !            34:     if (s == -1) {
        !            35:         ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
        !            36:                       ngx_socket_n " failed");
        !            37:         return NGX_ERROR;
        !            38:     }
        !            39: 
        !            40: 
        !            41:     c = ngx_get_connection(s, pc->log);
        !            42: 
        !            43:     if (c == NULL) {
        !            44:         if (ngx_close_socket(s) == -1) {
        !            45:             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
        !            46:                           ngx_close_socket_n "failed");
        !            47:         }
        !            48: 
        !            49:         return NGX_ERROR;
        !            50:     }
        !            51: 
        !            52:     if (pc->rcvbuf) {
        !            53:         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
        !            54:                        (const void *) &pc->rcvbuf, sizeof(int)) == -1)
        !            55:         {
        !            56:             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
        !            57:                           "setsockopt(SO_RCVBUF) failed");
        !            58:             goto failed;
        !            59:         }
        !            60:     }
        !            61: 
        !            62:     if (ngx_nonblocking(s) == -1) {
        !            63:         ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
        !            64:                       ngx_nonblocking_n " failed");
        !            65: 
        !            66:         goto failed;
        !            67:     }
        !            68: 
        !            69:     if (pc->local) {
        !            70:         if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
        !            71:             ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
        !            72:                           "bind(%V) failed", &pc->local->name);
        !            73: 
        !            74:             goto failed;
        !            75:         }
        !            76:     }
        !            77: 
        !            78:     c->recv = ngx_recv;
        !            79:     c->send = ngx_send;
        !            80:     c->recv_chain = ngx_recv_chain;
        !            81:     c->send_chain = ngx_send_chain;
        !            82: 
        !            83:     c->sendfile = 1;
        !            84: 
        !            85:     c->log_error = pc->log_error;
        !            86: 
        !            87:     if (pc->sockaddr->sa_family == AF_UNIX) {
        !            88:         c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
        !            89:         c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
        !            90: 
        !            91: #if (NGX_SOLARIS)
        !            92:         /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
        !            93:         c->sendfile = 0;
        !            94: #endif
        !            95:     }
        !            96: 
        !            97:     rev = c->read;
        !            98:     wev = c->write;
        !            99: 
        !           100:     rev->log = pc->log;
        !           101:     wev->log = pc->log;
        !           102: 
        !           103:     pc->connection = c;
        !           104: 
        !           105:     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
        !           106: 
        !           107: #if (NGX_THREADS)
        !           108: 
        !           109:     /* TODO: lock event when call completion handler */
        !           110: 
        !           111:     rev->lock = pc->lock;
        !           112:     wev->lock = pc->lock;
        !           113:     rev->own_lock = &c->lock;
        !           114:     wev->own_lock = &c->lock;
        !           115: 
        !           116: #endif
        !           117: 
        !           118:     if (ngx_add_conn) {
        !           119:         if (ngx_add_conn(c) == NGX_ERROR) {
        !           120:             goto failed;
        !           121:         }
        !           122:     }
        !           123: 
        !           124:     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
        !           125:                    "connect to %V, fd:%d #%d", pc->name, s, c->number);
        !           126: 
        !           127:     rc = connect(s, pc->sockaddr, pc->socklen);
        !           128: 
        !           129:     if (rc == -1) {
        !           130:         err = ngx_socket_errno;
        !           131: 
        !           132: 
        !           133:         if (err != NGX_EINPROGRESS
        !           134: #if (NGX_WIN32)
        !           135:             /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
        !           136:             && err != NGX_EAGAIN
        !           137: #endif
        !           138:             )
        !           139:         {
        !           140:             if (err == NGX_ECONNREFUSED
        !           141: #if (NGX_LINUX)
        !           142:                 /*
        !           143:                  * Linux returns EAGAIN instead of ECONNREFUSED
        !           144:                  * for unix sockets if listen queue is full
        !           145:                  */
        !           146:                 || err == NGX_EAGAIN
        !           147: #endif
        !           148:                 || err == NGX_ECONNRESET
        !           149:                 || err == NGX_ENETDOWN
        !           150:                 || err == NGX_ENETUNREACH
        !           151:                 || err == NGX_EHOSTDOWN
        !           152:                 || err == NGX_EHOSTUNREACH)
        !           153:             {
        !           154:                 level = NGX_LOG_ERR;
        !           155: 
        !           156:             } else {
        !           157:                 level = NGX_LOG_CRIT;
        !           158:             }
        !           159: 
        !           160:             ngx_log_error(level, c->log, err, "connect() to %V failed",
        !           161:                           pc->name);
        !           162: 
        !           163:             ngx_close_connection(c);
        !           164:             pc->connection = NULL;
        !           165: 
        !           166:             return NGX_DECLINED;
        !           167:         }
        !           168:     }
        !           169: 
        !           170:     if (ngx_add_conn) {
        !           171:         if (rc == -1) {
        !           172: 
        !           173:             /* NGX_EINPROGRESS */
        !           174: 
        !           175:             return NGX_AGAIN;
        !           176:         }
        !           177: 
        !           178:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
        !           179: 
        !           180:         wev->ready = 1;
        !           181: 
        !           182:         return NGX_OK;
        !           183:     }
        !           184: 
        !           185:     if (ngx_event_flags & NGX_USE_AIO_EVENT) {
        !           186: 
        !           187:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, ngx_socket_errno,
        !           188:                        "connect(): %d", rc);
        !           189: 
        !           190:         /* aio, iocp */
        !           191: 
        !           192:         if (ngx_blocking(s) == -1) {
        !           193:             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
        !           194:                           ngx_blocking_n " failed");
        !           195:             goto failed;
        !           196:         }
        !           197: 
        !           198:         /*
        !           199:          * FreeBSD's aio allows to post an operation on non-connected socket.
        !           200:          * NT does not support it.
        !           201:          *
        !           202:          * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
        !           203:          */
        !           204: 
        !           205:         rev->ready = 1;
        !           206:         wev->ready = 1;
        !           207: 
        !           208:         return NGX_OK;
        !           209:     }
        !           210: 
        !           211:     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
        !           212: 
        !           213:         /* kqueue */
        !           214: 
        !           215:         event = NGX_CLEAR_EVENT;
        !           216: 
        !           217:     } else {
        !           218: 
        !           219:         /* select, poll, /dev/poll */
        !           220: 
        !           221:         event = NGX_LEVEL_EVENT;
        !           222:     }
        !           223: 
        !           224:     if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
        !           225:         goto failed;
        !           226:     }
        !           227: 
        !           228:     if (rc == -1) {
        !           229: 
        !           230:         /* NGX_EINPROGRESS */
        !           231: 
        !           232:         if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
        !           233:             goto failed;
        !           234:         }
        !           235: 
        !           236:         return NGX_AGAIN;
        !           237:     }
        !           238: 
        !           239:     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
        !           240: 
        !           241:     wev->ready = 1;
        !           242: 
        !           243:     return NGX_OK;
        !           244: 
        !           245: failed:
        !           246: 
        !           247:     ngx_close_connection(c);
        !           248:     pc->connection = NULL;
        !           249: 
        !           250:     return NGX_ERROR;
        !           251: }
        !           252: 
        !           253: 
        !           254: ngx_int_t
        !           255: ngx_event_get_peer(ngx_peer_connection_t *pc, void *data)
        !           256: {
        !           257:     return NGX_OK;
        !           258: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>