Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / event / ngx_event_connect.c
blobe6ae6564e6cee9b9f645efff8147594b6f59b2ad
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_event_connect.h>
14 ngx_int_t
15 ngx_event_connect_peer(ngx_peer_connection_t *pc)
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;
25 rc = pc->get(pc, pc->data);
26 if (rc != NGX_OK) {
27 return rc;
30 s = ngx_socket(pc->sockaddr->sa_family, SOCK_STREAM, 0);
32 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0, "socket %d", s);
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;
41 c = ngx_get_connection(s, pc->log);
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");
49 return NGX_ERROR;
52 if (pc->rcvbuf) {
53 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
54 (const void *) &pc->rcvbuf, sizeof(int)) == -1)
56 ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
57 "setsockopt(SO_RCVBUF) failed");
58 goto failed;
62 if (ngx_nonblocking(s) == -1) {
63 ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
64 ngx_nonblocking_n " failed");
66 goto failed;
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);
74 goto failed;
78 c->recv = ngx_recv;
79 c->send = ngx_send;
80 c->recv_chain = ngx_recv_chain;
81 c->send_chain = ngx_send_chain;
83 c->sendfile = 1;
85 c->log_error = pc->log_error;
87 if (pc->sockaddr->sa_family == AF_UNIX) {
88 c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
89 c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
91 #if (NGX_SOLARIS)
92 /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
93 c->sendfile = 0;
94 #endif
97 rev = c->read;
98 wev = c->write;
100 rev->log = pc->log;
101 wev->log = pc->log;
103 pc->connection = c;
105 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
107 #if (NGX_THREADS)
109 /* TODO: lock event when call completion handler */
111 rev->lock = pc->lock;
112 wev->lock = pc->lock;
113 rev->own_lock = &c->lock;
114 wev->own_lock = &c->lock;
116 #endif
118 if (ngx_add_conn) {
119 if (ngx_add_conn(c) == NGX_ERROR) {
120 goto failed;
124 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
125 "connect to %V, fd:%d #%d", pc->name, s, c->number);
127 rc = connect(s, pc->sockaddr, pc->socklen);
129 if (rc == -1) {
130 err = ngx_socket_errno;
133 if (err != NGX_EINPROGRESS
134 #if (NGX_WIN32)
135 /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
136 && err != NGX_EAGAIN
137 #endif
140 if (err == NGX_ECONNREFUSED
141 #if (NGX_LINUX)
143 * Linux returns EAGAIN instead of ECONNREFUSED
144 * for unix sockets if listen queue is full
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)
154 level = NGX_LOG_ERR;
156 } else {
157 level = NGX_LOG_CRIT;
160 ngx_log_error(level, c->log, err, "connect() to %V failed",
161 pc->name);
163 ngx_close_connection(c);
164 pc->connection = NULL;
166 return NGX_DECLINED;
170 if (ngx_add_conn) {
171 if (rc == -1) {
173 /* NGX_EINPROGRESS */
175 return NGX_AGAIN;
178 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
180 wev->ready = 1;
182 return NGX_OK;
185 if (ngx_event_flags & NGX_USE_AIO_EVENT) {
187 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, ngx_socket_errno,
188 "connect(): %d", rc);
190 /* aio, iocp */
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;
199 * FreeBSD's aio allows to post an operation on non-connected socket.
200 * NT does not support it.
202 * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
205 rev->ready = 1;
206 wev->ready = 1;
208 return NGX_OK;
211 if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
213 /* kqueue */
215 event = NGX_CLEAR_EVENT;
217 } else {
219 /* select, poll, /dev/poll */
221 event = NGX_LEVEL_EVENT;
224 if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
225 goto failed;
228 if (rc == -1) {
230 /* NGX_EINPROGRESS */
232 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
233 goto failed;
236 return NGX_AGAIN;
239 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
241 wev->ready = 1;
243 return NGX_OK;
245 failed:
247 ngx_close_connection(c);
248 pc->connection = NULL;
250 return NGX_ERROR;
254 ngx_int_t
255 ngx_event_get_peer(ngx_peer_connection_t *pc, void *data)
257 return NGX_OK;