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>