Return to ngx_event_connect.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / nginx / src / event |
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: }