Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_event_connect.c
Go to the documentation of this file.
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 
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;
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) {
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) {
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  {
57  "setsockopt(SO_RCVBUF) failed");
58  goto failed;
59  }
60  }
61 
62  if (ngx_nonblocking(s) == -1) {
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) {
72  "bind(%V) failed", &pc->local->name);
73 
74  goto failed;
75  }
76  }
77 
78  c->recv = ngx_recv;
79  c->send = ngx_send;
82 
83  c->sendfile = 1;
84 
85  c->log_error = pc->log_error;
86 
87  if (pc->sockaddr->sa_family == AF_UNIX) {
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 
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 
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 
186 
188  "connect(): %d", rc);
189 
190  /* aio, iocp */
191 
192  if (ngx_blocking(s) == -1) {
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 
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 
248  pc->connection = NULL;
249 
250  return NGX_ERROR;
251 }
252 
253 
254 ngx_int_t
256 {
257  return NGX_OK;
258 }