3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
11 #include <ngx_event_connect.h>
15 ngx_event_connect_peer(ngx_peer_connection_t
*pc
)
22 ngx_event_t
*rev
, *wev
;
25 rc
= pc
->get(pc
, pc
->data
);
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
);
35 ngx_log_error(NGX_LOG_ALERT
, pc
->log
, ngx_socket_errno
,
36 ngx_socket_n
" failed");
41 c
= ngx_get_connection(s
, pc
->log
);
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");
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");
62 if (ngx_nonblocking(s
) == -1) {
63 ngx_log_error(NGX_LOG_ALERT
, pc
->log
, ngx_socket_errno
,
64 ngx_nonblocking_n
" failed");
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
);
80 c
->recv_chain
= ngx_recv_chain
;
81 c
->send_chain
= ngx_send_chain
;
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
;
92 /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
105 c
->number
= ngx_atomic_fetch_add(ngx_connection_counter
, 1);
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
;
119 if (ngx_add_conn(c
) == NGX_ERROR
) {
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
);
130 err
= ngx_socket_errno
;
133 if (err
!= NGX_EINPROGRESS
135 /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
140 if (err
== NGX_ECONNREFUSED
143 * Linux returns EAGAIN instead of ECONNREFUSED
144 * for unix sockets if listen queue is full
148 || err
== NGX_ECONNRESET
149 || err
== NGX_ENETDOWN
150 || err
== NGX_ENETUNREACH
151 || err
== NGX_EHOSTDOWN
152 || err
== NGX_EHOSTUNREACH
)
157 level
= NGX_LOG_CRIT
;
160 ngx_log_error(level
, c
->log
, err
, "connect() to %V failed",
163 ngx_close_connection(c
);
164 pc
->connection
= NULL
;
173 /* NGX_EINPROGRESS */
178 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, pc
->log
, 0, "connected");
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
);
192 if (ngx_blocking(s
) == -1) {
193 ngx_log_error(NGX_LOG_ALERT
, pc
->log
, ngx_socket_errno
,
194 ngx_blocking_n
" 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
211 if (ngx_event_flags
& NGX_USE_CLEAR_EVENT
) {
215 event
= NGX_CLEAR_EVENT
;
219 /* select, poll, /dev/poll */
221 event
= NGX_LEVEL_EVENT
;
224 if (ngx_add_event(rev
, NGX_READ_EVENT
, event
) != NGX_OK
) {
230 /* NGX_EINPROGRESS */
232 if (ngx_add_event(wev
, NGX_WRITE_EVENT
, event
) != NGX_OK
) {
239 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, pc
->log
, 0, "connected");
247 ngx_close_connection(c
);
248 pc
->connection
= NULL
;
255 ngx_event_get_peer(ngx_peer_connection_t
*pc
, void *data
)