xref: /third_party/node/deps/uv/src/unix/tcp.c (revision 1cb0ef41)
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
31static 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
42  err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
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
67static 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
114int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
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
143int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
144  return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
145}
146
147
148int uv__tcp_bind(uv_tcp_t* tcp,
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  err = bind(tcp->io_watcher.fd, addr, addrlen);
188  if (err == -1 && errno != EADDRINUSE) {
189    if (errno == EAFNOSUPPORT)
190      /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
191       * socket created with AF_INET to an AF_INET6 address or vice versa. */
192      return UV_EINVAL;
193    return UV__ERR(errno);
194  }
195  tcp->delayed_error = (err == -1) ? UV__ERR(errno) : 0;
196
197  tcp->flags |= UV_HANDLE_BOUND;
198  if (addr->sa_family == AF_INET6)
199    tcp->flags |= UV_HANDLE_IPV6;
200
201  return 0;
202}
203
204
205int uv__tcp_connect(uv_connect_t* req,
206                    uv_tcp_t* handle,
207                    const struct sockaddr* addr,
208                    unsigned int addrlen,
209                    uv_connect_cb cb) {
210  int err;
211  int r;
212
213  assert(handle->type == UV_TCP);
214
215  if (handle->connect_req != NULL)
216    return UV_EALREADY;  /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
217
218  if (handle->delayed_error != 0)
219    goto out;
220
221  err = maybe_new_socket(handle,
222                         addr->sa_family,
223                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
224  if (err)
225    return err;
226
227  do {
228    errno = 0;
229    r = connect(uv__stream_fd(handle), addr, addrlen);
230  } while (r == -1 && errno == EINTR);
231
232  /* We not only check the return value, but also check the errno != 0.
233   * Because in rare cases connect() will return -1 but the errno
234   * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
235   * and actually the tcp three-way handshake is completed.
236   */
237  if (r == -1 && errno != 0) {
238    if (errno == EINPROGRESS)
239      ; /* not an error */
240    else if (errno == ECONNREFUSED
241#if defined(__OpenBSD__)
242      || errno == EINVAL
243#endif
244      )
245    /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
246     * next tick to report the error. Solaris and OpenBSD wants to report
247     * immediately -- other unixes want to wait.
248     */
249      handle->delayed_error = UV__ERR(ECONNREFUSED);
250    else
251      return UV__ERR(errno);
252  }
253
254out:
255
256  uv__req_init(handle->loop, req, UV_CONNECT);
257  req->cb = cb;
258  req->handle = (uv_stream_t*) handle;
259  QUEUE_INIT(&req->queue);
260  handle->connect_req = req;
261
262  uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
263
264  if (handle->delayed_error)
265    uv__io_feed(handle->loop, &handle->io_watcher);
266
267  return 0;
268}
269
270
271int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
272  int err;
273
274  if (uv__fd_exists(handle->loop, sock))
275    return UV_EEXIST;
276
277  err = uv__nonblock(sock, 1);
278  if (err)
279    return err;
280
281  return uv__stream_open((uv_stream_t*)handle,
282                         sock,
283                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
284}
285
286
287int uv_tcp_getsockname(const uv_tcp_t* handle,
288                       struct sockaddr* name,
289                       int* namelen) {
290
291  if (handle->delayed_error)
292    return handle->delayed_error;
293
294  return uv__getsockpeername((const uv_handle_t*) handle,
295                             getsockname,
296                             name,
297                             namelen);
298}
299
300
301int uv_tcp_getpeername(const uv_tcp_t* handle,
302                       struct sockaddr* name,
303                       int* namelen) {
304
305  if (handle->delayed_error)
306    return handle->delayed_error;
307
308  return uv__getsockpeername((const uv_handle_t*) handle,
309                             getpeername,
310                             name,
311                             namelen);
312}
313
314
315int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
316  int fd;
317  struct linger l = { 1, 0 };
318
319  /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
320  if (handle->flags & UV_HANDLE_SHUTTING)
321    return UV_EINVAL;
322
323  fd = uv__stream_fd(handle);
324  if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) {
325    if (errno == EINVAL) {
326      /* Open Group Specifications Issue 7, 2018 edition states that
327       * EINVAL may mean the socket has been shut down already.
328       * Behavior observed on Solaris, illumos and macOS. */
329      errno = 0;
330    } else {
331      return UV__ERR(errno);
332    }
333  }
334
335  uv_close((uv_handle_t*) handle, close_cb);
336  return 0;
337}
338
339
340int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
341  static int single_accept_cached = -1;
342  unsigned long flags;
343  int single_accept;
344  int err;
345
346  if (tcp->delayed_error)
347    return tcp->delayed_error;
348
349  single_accept = uv__load_relaxed(&single_accept_cached);
350  if (single_accept == -1) {
351    const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
352    single_accept = (val != NULL && atoi(val) != 0);  /* Off by default. */
353    uv__store_relaxed(&single_accept_cached, single_accept);
354  }
355
356  if (single_accept)
357    tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
358
359  flags = 0;
360#if defined(__MVS__)
361  /* on zOS the listen call does not bind automatically
362     if the socket is unbound. Hence the manual binding to
363     an arbitrary port is required to be done manually
364  */
365  flags |= UV_HANDLE_BOUND;
366#endif
367  err = maybe_new_socket(tcp, AF_INET, flags);
368  if (err)
369    return err;
370
371  if (listen(tcp->io_watcher.fd, backlog))
372    return UV__ERR(errno);
373
374  tcp->connection_cb = cb;
375  tcp->flags |= UV_HANDLE_BOUND;
376
377  /* Start listening for connections. */
378  tcp->io_watcher.cb = uv__server_io;
379  uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
380
381  return 0;
382}
383
384
385int uv__tcp_nodelay(int fd, int on) {
386  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
387    return UV__ERR(errno);
388  return 0;
389}
390
391
392int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
393  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
394    return UV__ERR(errno);
395
396#ifdef TCP_KEEPIDLE
397  if (on) {
398    int intvl = 1;  /*  1 second; same as default on Win32 */
399    int cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
400    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
401      return UV__ERR(errno);
402    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
403      return UV__ERR(errno);
404    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
405      return UV__ERR(errno);
406  }
407#endif
408
409  /* Solaris/SmartOS, if you don't support keep-alive,
410   * then don't advertise it in your system headers...
411   */
412  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
413#if defined(TCP_KEEPALIVE) && !defined(__sun)
414  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
415    return UV__ERR(errno);
416#endif
417
418  return 0;
419}
420
421
422int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
423  int err;
424
425  if (uv__stream_fd(handle) != -1) {
426    err = uv__tcp_nodelay(uv__stream_fd(handle), on);
427    if (err)
428      return err;
429  }
430
431  if (on)
432    handle->flags |= UV_HANDLE_TCP_NODELAY;
433  else
434    handle->flags &= ~UV_HANDLE_TCP_NODELAY;
435
436  return 0;
437}
438
439
440int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
441  int err;
442
443  if (uv__stream_fd(handle) != -1) {
444    err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
445    if (err)
446      return err;
447  }
448
449  if (on)
450    handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
451  else
452    handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
453
454  /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
455   *      uv_tcp_t with an int that's almost never used...
456   */
457
458  return 0;
459}
460
461
462int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
463  if (enable)
464    handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
465  else
466    handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
467  return 0;
468}
469
470
471void uv__tcp_close(uv_tcp_t* handle) {
472  uv__stream_close((uv_stream_t*)handle);
473}
474
475
476int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
477  uv_os_sock_t temp[2];
478  int err;
479#if defined(__FreeBSD__) || defined(__linux__)
480  int flags;
481
482  flags = type | SOCK_CLOEXEC;
483  if ((flags0 & UV_NONBLOCK_PIPE) && (flags1 & UV_NONBLOCK_PIPE))
484    flags |= SOCK_NONBLOCK;
485
486  if (socketpair(AF_UNIX, flags, protocol, temp))
487    return UV__ERR(errno);
488
489  if (flags & UV_FS_O_NONBLOCK) {
490    fds[0] = temp[0];
491    fds[1] = temp[1];
492    return 0;
493  }
494#else
495  if (socketpair(AF_UNIX, type, protocol, temp))
496    return UV__ERR(errno);
497
498  if ((err = uv__cloexec(temp[0], 1)))
499    goto fail;
500  if ((err = uv__cloexec(temp[1], 1)))
501    goto fail;
502#endif
503
504  if (flags0 & UV_NONBLOCK_PIPE)
505    if ((err = uv__nonblock(temp[0], 1)))
506        goto fail;
507  if (flags1 & UV_NONBLOCK_PIPE)
508    if ((err = uv__nonblock(temp[1], 1)))
509      goto fail;
510
511  fds[0] = temp[0];
512  fds[1] = temp[1];
513  return 0;
514
515fail:
516  uv__close(temp[0]);
517  uv__close(temp[1]);
518  return err;
519}
520