Annotation of embedaddon/nginx/src/event/ngx_event_connect.c, revision 1.1.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>