unix/tcp.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "internal.h"
24 
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <assert.h>
28 #include <errno.h>
29 
30 
31 static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
32  struct sockaddr_storage saddr;
33  socklen_t slen;
34  int sockfd;
35  int err;
36 
37  err = uv__socket(domain, SOCK_STREAM, 0);
38  if (err < 0)
39  return err;
40  sockfd = err;
41 
43  if (err) {
44  uv__close(sockfd);
45  return err;
46  }
47 
48  if (flags & UV_HANDLE_BOUND) {
49  /* Bind this new socket to an arbitrary port */
50  slen = sizeof(saddr);
51  memset(&saddr, 0, sizeof(saddr));
52  if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
53  uv__close(sockfd);
54  return UV__ERR(errno);
55  }
56 
57  if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
58  uv__close(sockfd);
59  return UV__ERR(errno);
60  }
61  }
62 
63  return 0;
64 }
65 
66 
67 static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
68  struct sockaddr_storage saddr;
69  socklen_t slen;
70 
71  if (domain == AF_UNSPEC) {
72  handle->flags |= flags;
73  return 0;
74  }
75 
76  if (uv__stream_fd(handle) != -1) {
77 
78  if (flags & UV_HANDLE_BOUND) {
79 
80  if (handle->flags & UV_HANDLE_BOUND) {
81  /* It is already bound to a port. */
82  handle->flags |= flags;
83  return 0;
84  }
85 
86  /* Query to see if tcp socket is bound. */
87  slen = sizeof(saddr);
88  memset(&saddr, 0, sizeof(saddr));
89  if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
90  return UV__ERR(errno);
91 
92  if ((saddr.ss_family == AF_INET6 &&
93  ((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
94  (saddr.ss_family == AF_INET &&
95  ((struct sockaddr_in*) &saddr)->sin_port != 0)) {
96  /* Handle is already bound to a port. */
97  handle->flags |= flags;
98  return 0;
99  }
100 
101  /* Bind to arbitrary port */
102  if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
103  return UV__ERR(errno);
104  }
105 
106  handle->flags |= flags;
107  return 0;
108  }
109 
110  return new_socket(handle, domain, flags);
111 }
112 
113 
115  int domain;
116 
117  /* Use the lower 8 bits for the domain */
118  domain = flags & 0xFF;
119  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
120  return UV_EINVAL;
121 
122  if (flags & ~0xFF)
123  return UV_EINVAL;
124 
125  uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
126 
127  /* If anything fails beyond this point we need to remove the handle from
128  * the handle queue, since it was added by uv__handle_init in uv_stream_init.
129  */
130 
131  if (domain != AF_UNSPEC) {
132  int err = maybe_new_socket(tcp, domain, 0);
133  if (err) {
134  QUEUE_REMOVE(&tcp->handle_queue);
135  return err;
136  }
137  }
138 
139  return 0;
140 }
141 
142 
144  return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
145 }
146 
147 
149  const struct sockaddr* addr,
150  unsigned int addrlen,
151  unsigned int flags) {
152  int err;
153  int on;
154 
155  /* Cannot set IPv6-only mode on non-IPv6 socket. */
156  if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
157  return UV_EINVAL;
158 
159  err = maybe_new_socket(tcp, addr->sa_family, 0);
160  if (err)
161  return err;
162 
163  on = 1;
164  if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
165  return UV__ERR(errno);
166 
167 #ifndef __OpenBSD__
168 #ifdef IPV6_V6ONLY
169  if (addr->sa_family == AF_INET6) {
170  on = (flags & UV_TCP_IPV6ONLY) != 0;
171  if (setsockopt(tcp->io_watcher.fd,
172  IPPROTO_IPV6,
173  IPV6_V6ONLY,
174  &on,
175  sizeof on) == -1) {
176 #if defined(__MVS__)
177  if (errno == EOPNOTSUPP)
178  return UV_EINVAL;
179 #endif
180  return UV__ERR(errno);
181  }
182  }
183 #endif
184 #endif
185 
186  errno = 0;
187  if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
188  if (errno == EAFNOSUPPORT)
189  /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
190  * socket created with AF_INET to an AF_INET6 address or vice versa. */
191  return UV_EINVAL;
192  return UV__ERR(errno);
193  }
194  tcp->delayed_error = UV__ERR(errno);
195 
196  tcp->flags |= UV_HANDLE_BOUND;
197  if (addr->sa_family == AF_INET6)
198  tcp->flags |= UV_HANDLE_IPV6;
199 
200  return 0;
201 }
202 
203 
205  uv_tcp_t* handle,
206  const struct sockaddr* addr,
207  unsigned int addrlen,
208  uv_connect_cb cb) {
209  int err;
210  int r;
211 
212  assert(handle->type == UV_TCP);
213 
214  if (handle->connect_req != NULL)
215  return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
216 
218  addr->sa_family,
220  if (err)
221  return err;
222 
223  handle->delayed_error = 0;
224 
225  do {
226  errno = 0;
227  r = connect(uv__stream_fd(handle), addr, addrlen);
228  } while (r == -1 && errno == EINTR);
229 
230  /* We not only check the return value, but also check the errno != 0.
231  * Because in rare cases connect() will return -1 but the errno
232  * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
233  * and actually the tcp three-way handshake is completed.
234  */
235  if (r == -1 && errno != 0) {
236  if (errno == EINPROGRESS)
237  ; /* not an error */
238  else if (errno == ECONNREFUSED
239 #if defined(__OpenBSD__)
240  || errno == EINVAL
241 #endif
242  )
243  /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
244  * next tick to report the error. Solaris and OpenBSD wants to report
245  * immediately -- other unixes want to wait.
246  */
247  handle->delayed_error = UV__ERR(ECONNREFUSED);
248  else
249  return UV__ERR(errno);
250  }
251 
252  uv__req_init(handle->loop, req, UV_CONNECT);
253  req->cb = cb;
255  QUEUE_INIT(&req->queue);
256  handle->connect_req = req;
257 
258  uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
259 
260  if (handle->delayed_error)
261  uv__io_feed(handle->loop, &handle->io_watcher);
262 
263  return 0;
264 }
265 
266 
268  int err;
269 
270  if (uv__fd_exists(handle->loop, sock))
271  return UV_EEXIST;
272 
273  err = uv__nonblock(sock, 1);
274  if (err)
275  return err;
276 
278  sock,
280 }
281 
282 
284  struct sockaddr* name,
285  int* namelen) {
286 
287  if (handle->delayed_error)
288  return handle->delayed_error;
289 
290  return uv__getsockpeername((const uv_handle_t*) handle,
291  getsockname,
292  name,
293  namelen);
294 }
295 
296 
298  struct sockaddr* name,
299  int* namelen) {
300 
301  if (handle->delayed_error)
302  return handle->delayed_error;
303 
304  return uv__getsockpeername((const uv_handle_t*) handle,
305  getpeername,
306  name,
307  namelen);
308 }
309 
310 
312  int fd;
313  struct linger l = { 1, 0 };
314 
315  /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
316  if (handle->flags & UV_HANDLE_SHUTTING)
317  return UV_EINVAL;
318 
319  fd = uv__stream_fd(handle);
320  if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
321  return UV__ERR(errno);
322 
324  return 0;
325 }
326 
327 
329  static int single_accept = -1;
330  unsigned long flags;
331  int err;
332 
333  if (tcp->delayed_error)
334  return tcp->delayed_error;
335 
336  if (single_accept == -1) {
337  const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
338  single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */
339  }
340 
341  if (single_accept)
343 
344  flags = 0;
345 #if defined(__MVS__)
346  /* on zOS the listen call does not bind automatically
347  if the socket is unbound. Hence the manual binding to
348  an arbitrary port is required to be done manually
349  */
351 #endif
352  err = maybe_new_socket(tcp, AF_INET, flags);
353  if (err)
354  return err;
355 
356  if (listen(tcp->io_watcher.fd, backlog))
357  return UV__ERR(errno);
358 
359  tcp->connection_cb = cb;
360  tcp->flags |= UV_HANDLE_BOUND;
361 
362  /* Start listening for connections. */
363  tcp->io_watcher.cb = uv__server_io;
364  uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
365 
366  return 0;
367 }
368 
369 
370 int uv__tcp_nodelay(int fd, int on) {
371  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
372  return UV__ERR(errno);
373  return 0;
374 }
375 
376 
377 int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
378  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
379  return UV__ERR(errno);
380 
381 #ifdef TCP_KEEPIDLE
382  if (on) {
383  int intvl = 1; /* 1 second; same as default on Win32 */
384  int cnt = 10; /* 10 retries; same as hardcoded on Win32 */
385  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
386  return UV__ERR(errno);
387  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
388  return UV__ERR(errno);
389  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
390  return UV__ERR(errno);
391  }
392 #endif
393 
394  /* Solaris/SmartOS, if you don't support keep-alive,
395  * then don't advertise it in your system headers...
396  */
397  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
398 #if defined(TCP_KEEPALIVE) && !defined(__sun)
399  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
400  return UV__ERR(errno);
401 #endif
402 
403  return 0;
404 }
405 
406 
408  int err;
409 
410  if (uv__stream_fd(handle) != -1) {
412  if (err)
413  return err;
414  }
415 
416  if (on)
417  handle->flags |= UV_HANDLE_TCP_NODELAY;
418  else
419  handle->flags &= ~UV_HANDLE_TCP_NODELAY;
420 
421  return 0;
422 }
423 
424 
425 int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
426  int err;
427 
428  if (uv__stream_fd(handle) != -1) {
430  if (err)
431  return err;
432  }
433 
434  if (on)
436  else
437  handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
438 
439  /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
440  * uv_tcp_t with an int that's almost never used...
441  */
442 
443  return 0;
444 }
445 
446 
448  if (enable)
450  else
452  return 0;
453 }
454 
455 
458 }
UV_HANDLE_WRITABLE
@ UV_HANDLE_WRITABLE
Definition: uv-common.h:85
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
UV_HANDLE_TCP_KEEPALIVE
@ UV_HANDLE_TCP_KEEPALIVE
Definition: uv-common.h:98
uv__stream_close
void uv__stream_close(uv_stream_t *handle)
Definition: unix/stream.c:1633
uv_tcp_getpeername
int uv_tcp_getpeername(const uv_tcp_t *handle, struct sockaddr *name, int *namelen)
Definition: unix/tcp.c:297
uv_tcp_close_reset
int uv_tcp_close_reset(uv_tcp_t *handle, uv_close_cb close_cb)
Definition: unix/tcp.c:311
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
UV_HANDLE_BOUND
@ UV_HANDLE_BOUND
Definition: uv-common.h:83
memset
return memset(p, 0, total)
uv__socket
int uv__socket(int domain, int type, int protocol)
Definition: unix/core.c:424
uv_connect_s
Definition: uv.h:580
uv__req_init
#define uv__req_init(loop, req, typ)
Definition: uv-common.h:312
UV_HANDLE_TCP_SINGLE_ACCEPT
@ UV_HANDLE_TCP_SINGLE_ACCEPT
Definition: uv-common.h:99
uv_connect_s::handle
uv_stream_t * handle
Definition: uv.h:583
error_ref_leak.err
err
Definition: error_ref_leak.py:35
tcp
static uv_tcp_t tcp
Definition: test-connection-fail.c:29
uv__tcp_close
void uv__tcp_close(uv_tcp_t *handle)
Definition: unix/tcp.c:456
setup.name
name
Definition: setup.py:542
uv_tcp_listen
int uv_tcp_listen(uv_tcp_t *tcp, int backlog, uv_connection_cb cb)
Definition: unix/tcp.c:328
new_socket
static int new_socket(uv_tcp_t *handle, int domain, unsigned long flags)
Definition: unix/tcp.c:31
uv_close
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: unix/core.c:112
uv_connect_s::cb
UV_REQ_FIELDS uv_connect_cb cb
Definition: uv.h:582
uv_stream_s
Definition: uv.h:491
uv_os_sock_t
int uv_os_sock_t
Definition: unix.h:127
uv_tcp_nodelay
int uv_tcp_nodelay(uv_tcp_t *handle, int on)
Definition: unix/tcp.c:407
uv_tcp_init_ex
int uv_tcp_init_ex(uv_loop_t *loop, uv_tcp_t *tcp, unsigned int flags)
Definition: unix/tcp.c:114
uv_tcp_getsockname
int uv_tcp_getsockname(const uv_tcp_t *handle, struct sockaddr *name, int *namelen)
Definition: unix/tcp.c:283
QUEUE_INIT
#define QUEUE_INIT(q)
Definition: queue.h:45
uv_tcp_init
int uv_tcp_init(uv_loop_t *loop, uv_tcp_t *tcp)
Definition: unix/tcp.c:143
sockaddr_in6
Definition: ares_ipv6.h:25
uv_tcp_open
int uv_tcp_open(uv_tcp_t *handle, uv_os_sock_t sock)
Definition: unix/tcp.c:267
uv__server_io
void uv__server_io(uv_loop_t *loop, uv__io_t *w, unsigned int events)
Definition: unix/stream.c:528
uv__fd_exists
int uv__fd_exists(uv_loop_t *loop, int fd)
Definition: unix/core.c:953
req
static uv_connect_t req
Definition: test-connection-fail.c:30
UV_HANDLE_TCP_NODELAY
@ UV_HANDLE_TCP_NODELAY
Definition: uv-common.h:97
uv__io_start
void uv__io_start(uv_loop_t *loop, uv__io_t *w, unsigned int events)
Definition: unix/core.c:870
uv__getsockpeername
int uv__getsockpeername(const uv_handle_t *handle, uv__peersockfunc func, struct sockaddr *name, int *namelen)
Definition: unix/core.c:1485
TCP_KEEPALIVE
#define TCP_KEEPALIVE
Definition: winsock.h:42
maybe_new_socket
static int maybe_new_socket(uv_tcp_t *handle, int domain, unsigned long flags)
Definition: unix/tcp.c:67
uv__stream_init
void uv__stream_init(uv_loop_t *loop, uv_stream_t *stream, uv_handle_type type)
Definition: unix/stream.c:85
UV__ERR
#define UV__ERR(x)
Definition: errno.h:29
UV_TCP_IPV6ONLY
@ UV_TCP_IPV6ONLY
Definition: uv.h:561
UV_HANDLE_SHUTTING
@ UV_HANDLE_SHUTTING
Definition: uv-common.h:76
UV_HANDLE_IPV6
@ UV_HANDLE_IPV6
Definition: uv-common.h:94
QUEUE_REMOVE
#define QUEUE_REMOVE(q)
Definition: queue.h:101
close_cb
static void close_cb(uv_handle_t *handle)
Definition: benchmark-million-timers.c:36
uv_tcp_s
Definition: uv.h:544
uv_connect_cb
void(* uv_connect_cb)(uv_connect_t *req, int status)
Definition: uv.h:313
uv_tcp_keepalive
int uv_tcp_keepalive(uv_tcp_t *handle, int on, unsigned int delay)
Definition: unix/tcp.c:425
uv.h
IPV6_V6ONLY
#define IPV6_V6ONLY
Definition: winsock.h:46
uv__nonblock
#define uv__nonblock
Definition: third_party/libuv/src/unix/internal.h:174
uv__tcp_connect
int uv__tcp_connect(uv_connect_t *req, uv_tcp_t *handle, const struct sockaddr *addr, unsigned int addrlen, uv_connect_cb cb)
Definition: unix/tcp.c:204
internal.h
UV_HANDLE_READABLE
@ UV_HANDLE_READABLE
Definition: uv-common.h:84
uv__io_feed
void uv__io_feed(uv_loop_t *loop, uv__io_t *w)
Definition: unix/core.c:940
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
http2_test_server.listen
def listen(endpoint, test_case)
Definition: http2_test_server.py:87
uv_connection_cb
void(* uv_connection_cb)(uv_stream_t *server, int status)
Definition: uv.h:315
uv__stream_fd
#define uv__stream_fd(handle)
Definition: third_party/libuv/src/unix/internal.h:285
fix_build_deps.r
r
Definition: fix_build_deps.py:491
uv_tcp_simultaneous_accepts
int uv_tcp_simultaneous_accepts(uv_tcp_t *handle, int enable)
Definition: unix/tcp.c:447
uv__tcp_bind
int uv__tcp_bind(uv_tcp_t *tcp, const struct sockaddr *addr, unsigned int addrlen, unsigned int flags)
Definition: unix/tcp.c:148
handle
static csh handle
Definition: test_arm_regression.c:16
uv_handle_s
Definition: uv.h:441
uv_loop_s
Definition: uv.h:1767
flags
uint32_t flags
Definition: retry_filter.cc:632
uv_close_cb
void(* uv_close_cb)(uv_handle_t *handle)
Definition: uv.h:316
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
uv__stream_open
int uv__stream_open(uv_stream_t *, int fd, int flags)
Definition: unix/stream.c:406
uv__tcp_keepalive
int uv__tcp_keepalive(int fd, int on, unsigned int delay)
Definition: unix/tcp.c:377
uv__tcp_nodelay
int uv__tcp_nodelay(int fd, int on)
Definition: unix/tcp.c:370
getenv
#define getenv(ptr)
Definition: ares_private.h:106
addr
struct sockaddr_in addr
Definition: libuv/docs/code/tcp-echo-server/main.c:10
errno.h
cb
OPENSSL_EXPORT pem_password_cb * cb
Definition: pem.h:351
uv__close
int uv__close(int fd)
Definition: unix/core.c:557


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:29