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>