Blame src/unix/tcp.c

Packit b5b901
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit b5b901
 *
Packit b5b901
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit b5b901
 * of this software and associated documentation files (the "Software"), to
Packit b5b901
 * deal in the Software without restriction, including without limitation the
Packit b5b901
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit b5b901
 * sell copies of the Software, and to permit persons to whom the Software is
Packit b5b901
 * furnished to do so, subject to the following conditions:
Packit b5b901
 *
Packit b5b901
 * The above copyright notice and this permission notice shall be included in
Packit b5b901
 * all copies or substantial portions of the Software.
Packit b5b901
 *
Packit b5b901
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit b5b901
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit b5b901
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit b5b901
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit b5b901
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit b5b901
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit b5b901
 * IN THE SOFTWARE.
Packit b5b901
 */
Packit b5b901
Packit b5b901
#include "uv.h"
Packit b5b901
#include "internal.h"
Packit b5b901
Packit b5b901
#include <stdlib.h>
Packit b5b901
#include <unistd.h>
Packit b5b901
#include <assert.h>
Packit b5b901
#include <errno.h>
Packit b5b901
Packit b5b901
Packit b5b901
static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
Packit b5b901
  struct sockaddr_storage saddr;
Packit b5b901
  socklen_t slen;
Packit b5b901
  int sockfd;
Packit b5b901
  int err;
Packit b5b901
Packit b5b901
  err = uv__socket(domain, SOCK_STREAM, 0);
Packit b5b901
  if (err < 0)
Packit b5b901
    return err;
Packit b5b901
  sockfd = err;
Packit b5b901
Packit b5b901
  err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
Packit b5b901
  if (err) {
Packit b5b901
    uv__close(sockfd);
Packit b5b901
    return err;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  if (flags & UV_HANDLE_BOUND) {
Packit b5b901
    /* Bind this new socket to an arbitrary port */
Packit b5b901
    slen = sizeof(saddr);
Packit b5b901
    memset(&saddr, 0, sizeof(saddr));
Packit b5b901
    if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
Packit b5b901
      uv__close(sockfd);
Packit b5b901
      return UV__ERR(errno);
Packit b5b901
    }
Packit b5b901
Packit b5b901
    if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
Packit b5b901
      uv__close(sockfd);
Packit b5b901
      return UV__ERR(errno);
Packit b5b901
    }
Packit b5b901
  }
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
Packit b5b901
  struct sockaddr_storage saddr;
Packit b5b901
  socklen_t slen;
Packit b5b901
Packit b5b901
  if (domain == AF_UNSPEC) {
Packit b5b901
    handle->flags |= flags;
Packit b5b901
    return 0;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  if (uv__stream_fd(handle) != -1) {
Packit b5b901
Packit b5b901
    if (flags & UV_HANDLE_BOUND) {
Packit b5b901
Packit b5b901
      if (handle->flags & UV_HANDLE_BOUND) {
Packit b5b901
        /* It is already bound to a port. */
Packit b5b901
        handle->flags |= flags;
Packit b5b901
        return 0;
Packit b5b901
      }
Packit Service e08953
Packit b5b901
      /* Query to see if tcp socket is bound. */
Packit b5b901
      slen = sizeof(saddr);
Packit b5b901
      memset(&saddr, 0, sizeof(saddr));
Packit b5b901
      if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
Packit b5b901
        return UV__ERR(errno);
Packit b5b901
Packit b5b901
      if ((saddr.ss_family == AF_INET6 &&
Packit b5b901
          ((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
Packit b5b901
          (saddr.ss_family == AF_INET &&
Packit b5b901
          ((struct sockaddr_in*) &saddr)->sin_port != 0)) {
Packit b5b901
        /* Handle is already bound to a port. */
Packit b5b901
        handle->flags |= flags;
Packit b5b901
        return 0;
Packit b5b901
      }
Packit b5b901
Packit b5b901
      /* Bind to arbitrary port */
Packit b5b901
      if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
Packit b5b901
        return UV__ERR(errno);
Packit b5b901
    }
Packit b5b901
Packit b5b901
    handle->flags |= flags;
Packit b5b901
    return 0;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  return new_socket(handle, domain, flags);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
Packit b5b901
  int domain;
Packit b5b901
Packit b5b901
  /* Use the lower 8 bits for the domain */
Packit b5b901
  domain = flags & 0xFF;
Packit b5b901
  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
Packit b5b901
    return UV_EINVAL;
Packit b5b901
Packit b5b901
  if (flags & ~0xFF)
Packit b5b901
    return UV_EINVAL;
Packit b5b901
Packit b5b901
  uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
Packit b5b901
Packit b5b901
  /* If anything fails beyond this point we need to remove the handle from
Packit b5b901
   * the handle queue, since it was added by uv__handle_init in uv_stream_init.
Packit b5b901
   */
Packit b5b901
Packit b5b901
  if (domain != AF_UNSPEC) {
Packit b5b901
    int err = maybe_new_socket(tcp, domain, 0);
Packit b5b901
    if (err) {
Packit b5b901
      QUEUE_REMOVE(&tcp->handle_queue);
Packit b5b901
      return err;
Packit b5b901
    }
Packit b5b901
  }
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
Packit b5b901
  return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv__tcp_bind(uv_tcp_t* tcp,
Packit b5b901
                 const struct sockaddr* addr,
Packit b5b901
                 unsigned int addrlen,
Packit b5b901
                 unsigned int flags) {
Packit b5b901
  int err;
Packit b5b901
  int on;
Packit b5b901
Packit b5b901
  /* Cannot set IPv6-only mode on non-IPv6 socket. */
Packit b5b901
  if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
Packit b5b901
    return UV_EINVAL;
Packit b5b901
Packit b5b901
  err = maybe_new_socket(tcp, addr->sa_family, 0);
Packit b5b901
  if (err)
Packit b5b901
    return err;
Packit b5b901
Packit b5b901
  on = 1;
Packit b5b901
  if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
Packit b5b901
#ifndef __OpenBSD__
Packit b5b901
#ifdef IPV6_V6ONLY
Packit b5b901
  if (addr->sa_family == AF_INET6) {
Packit b5b901
    on = (flags & UV_TCP_IPV6ONLY) != 0;
Packit b5b901
    if (setsockopt(tcp->io_watcher.fd,
Packit b5b901
                   IPPROTO_IPV6,
Packit b5b901
                   IPV6_V6ONLY,
Packit b5b901
                   &on,
Packit b5b901
                   sizeof on) == -1) {
Packit b5b901
#if defined(__MVS__)
Packit b5b901
      if (errno == EOPNOTSUPP)
Packit b5b901
        return UV_EINVAL;
Packit b5b901
#endif
Packit b5b901
      return UV__ERR(errno);
Packit b5b901
    }
Packit b5b901
  }
Packit b5b901
#endif
Packit b5b901
#endif
Packit b5b901
Packit b5b901
  errno = 0;
Packit b5b901
  if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
Packit b5b901
    if (errno == EAFNOSUPPORT)
Packit b5b901
      /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
Packit b5b901
       * socket created with AF_INET to an AF_INET6 address or vice versa. */
Packit b5b901
      return UV_EINVAL;
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
  }
Packit b5b901
  tcp->delayed_error = UV__ERR(errno);
Packit b5b901
Packit b5b901
  tcp->flags |= UV_HANDLE_BOUND;
Packit b5b901
  if (addr->sa_family == AF_INET6)
Packit b5b901
    tcp->flags |= UV_HANDLE_IPV6;
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv__tcp_connect(uv_connect_t* req,
Packit b5b901
                    uv_tcp_t* handle,
Packit b5b901
                    const struct sockaddr* addr,
Packit b5b901
                    unsigned int addrlen,
Packit b5b901
                    uv_connect_cb cb) {
Packit b5b901
  int err;
Packit b5b901
  int r;
Packit b5b901
Packit b5b901
  assert(handle->type == UV_TCP);
Packit b5b901
Packit b5b901
  if (handle->connect_req != NULL)
Packit b5b901
    return UV_EALREADY;  /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
Packit b5b901
Packit b5b901
  err = maybe_new_socket(handle,
Packit b5b901
                         addr->sa_family,
Packit b5b901
                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
Packit b5b901
  if (err)
Packit b5b901
    return err;
Packit b5b901
Packit b5b901
  handle->delayed_error = 0;
Packit b5b901
Packit b5b901
  do {
Packit b5b901
    errno = 0;
Packit b5b901
    r = connect(uv__stream_fd(handle), addr, addrlen);
Packit b5b901
  } while (r == -1 && errno == EINTR);
Packit b5b901
Packit b5b901
  /* We not only check the return value, but also check the errno != 0.
Packit b5b901
   * Because in rare cases connect() will return -1 but the errno
Packit b5b901
   * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
Packit b5b901
   * and actually the tcp three-way handshake is completed.
Packit b5b901
   */
Packit b5b901
  if (r == -1 && errno != 0) {
Packit b5b901
    if (errno == EINPROGRESS)
Packit b5b901
      ; /* not an error */
Packit Service e08953
    else if (errno == ECONNREFUSED
Packit Service e08953
#if defined(__OpenBSD__)
Packit Service e08953
      || errno == EINVAL
Packit Service e08953
#endif
Packit Service e08953
      )
Packit Service e08953
    /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
Packit Service e08953
     * next tick to report the error. Solaris and OpenBSD wants to report
Packit Service e08953
     * immediately -- other unixes want to wait.
Packit b5b901
     */
Packit Service e08953
      handle->delayed_error = UV__ERR(ECONNREFUSED);
Packit b5b901
    else
Packit b5b901
      return UV__ERR(errno);
Packit b5b901
  }
Packit b5b901
Packit b5b901
  uv__req_init(handle->loop, req, UV_CONNECT);
Packit b5b901
  req->cb = cb;
Packit b5b901
  req->handle = (uv_stream_t*) handle;
Packit b5b901
  QUEUE_INIT(&req->queue);
Packit b5b901
  handle->connect_req = req;
Packit b5b901
Packit b5b901
  uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
Packit b5b901
Packit b5b901
  if (handle->delayed_error)
Packit b5b901
    uv__io_feed(handle->loop, &handle->io_watcher);
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
Packit b5b901
  int err;
Packit b5b901
Packit b5b901
  if (uv__fd_exists(handle->loop, sock))
Packit b5b901
    return UV_EEXIST;
Packit b5b901
Packit b5b901
  err = uv__nonblock(sock, 1);
Packit b5b901
  if (err)
Packit b5b901
    return err;
Packit b5b901
Packit b5b901
  return uv__stream_open((uv_stream_t*)handle,
Packit b5b901
                         sock,
Packit b5b901
                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_getsockname(const uv_tcp_t* handle,
Packit b5b901
                       struct sockaddr* name,
Packit b5b901
                       int* namelen) {
Packit b5b901
Packit b5b901
  if (handle->delayed_error)
Packit b5b901
    return handle->delayed_error;
Packit b5b901
Packit Service e08953
  return uv__getsockpeername((const uv_handle_t*) handle,
Packit Service e08953
                             getsockname,
Packit Service e08953
                             name,
Packit Service e08953
                             namelen);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_getpeername(const uv_tcp_t* handle,
Packit b5b901
                       struct sockaddr* name,
Packit b5b901
                       int* namelen) {
Packit b5b901
Packit b5b901
  if (handle->delayed_error)
Packit b5b901
    return handle->delayed_error;
Packit b5b901
Packit Service e08953
  return uv__getsockpeername((const uv_handle_t*) handle,
Packit Service e08953
                             getpeername,
Packit Service e08953
                             name,
Packit Service e08953
                             namelen);
Packit Service e08953
}
Packit Service e08953
Packit Service e08953
Packit Service e08953
int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
Packit Service e08953
  int fd;
Packit Service e08953
  struct linger l = { 1, 0 };
Packit b5b901
Packit Service e08953
  /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
Packit Service e08953
  if (handle->flags & UV_HANDLE_SHUTTING)
Packit Service e08953
    return UV_EINVAL;
Packit b5b901
Packit Service e08953
  fd = uv__stream_fd(handle);
Packit Service e08953
  if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
Packit Service e08953
  uv_close((uv_handle_t*) handle, close_cb);
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
Packit b5b901
  static int single_accept = -1;
Packit b5b901
  unsigned long flags;
Packit b5b901
  int err;
Packit b5b901
Packit b5b901
  if (tcp->delayed_error)
Packit b5b901
    return tcp->delayed_error;
Packit b5b901
Packit b5b901
  if (single_accept == -1) {
Packit b5b901
    const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
Packit b5b901
    single_accept = (val != NULL && atoi(val) != 0);  /* Off by default. */
Packit b5b901
  }
Packit b5b901
Packit b5b901
  if (single_accept)
Packit b5b901
    tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
Packit b5b901
Packit b5b901
  flags = 0;
Packit b5b901
#if defined(__MVS__)
Packit b5b901
  /* on zOS the listen call does not bind automatically
Packit b5b901
     if the socket is unbound. Hence the manual binding to
Packit b5b901
     an arbitrary port is required to be done manually
Packit b5b901
  */
Packit b5b901
  flags |= UV_HANDLE_BOUND;
Packit b5b901
#endif
Packit b5b901
  err = maybe_new_socket(tcp, AF_INET, flags);
Packit b5b901
  if (err)
Packit b5b901
    return err;
Packit b5b901
Packit b5b901
  if (listen(tcp->io_watcher.fd, backlog))
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
Packit b5b901
  tcp->connection_cb = cb;
Packit b5b901
  tcp->flags |= UV_HANDLE_BOUND;
Packit b5b901
Packit b5b901
  /* Start listening for connections. */
Packit b5b901
  tcp->io_watcher.cb = uv__server_io;
Packit b5b901
  uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv__tcp_nodelay(int fd, int on) {
Packit b5b901
  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
Packit b5b901
  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
Packit b5b901
#ifdef TCP_KEEPIDLE
Packit Service e08953
  if (on) {
Packit Service e08953
    int intvl = 1;  /*  1 second; same as default on Win32 */
Packit Service e08953
    int cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
Packit Service e08953
    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
Packit Service e08953
      return UV__ERR(errno);
Packit Service e08953
    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
Packit Service e08953
      return UV__ERR(errno);
Packit Service e08953
    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
Packit Service e08953
      return UV__ERR(errno);
Packit Service e08953
  }
Packit b5b901
#endif
Packit b5b901
Packit b5b901
  /* Solaris/SmartOS, if you don't support keep-alive,
Packit b5b901
   * then don't advertise it in your system headers...
Packit b5b901
   */
Packit b5b901
  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
Packit b5b901
#if defined(TCP_KEEPALIVE) && !defined(__sun)
Packit b5b901
  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
Packit b5b901
    return UV__ERR(errno);
Packit b5b901
#endif
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
Packit b5b901
  int err;
Packit b5b901
Packit b5b901
  if (uv__stream_fd(handle) != -1) {
Packit b5b901
    err = uv__tcp_nodelay(uv__stream_fd(handle), on);
Packit b5b901
    if (err)
Packit b5b901
      return err;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  if (on)
Packit b5b901
    handle->flags |= UV_HANDLE_TCP_NODELAY;
Packit b5b901
  else
Packit b5b901
    handle->flags &= ~UV_HANDLE_TCP_NODELAY;
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
Packit b5b901
  int err;
Packit b5b901
Packit b5b901
  if (uv__stream_fd(handle) != -1) {
Packit b5b901
    err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
Packit b5b901
    if (err)
Packit b5b901
      return err;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  if (on)
Packit b5b901
    handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
Packit b5b901
  else
Packit b5b901
    handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
Packit b5b901
Packit b5b901
  /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
Packit b5b901
   *      uv_tcp_t with an int that's almost never used...
Packit b5b901
   */
Packit b5b901
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
Packit b5b901
  if (enable)
Packit b5b901
    handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
Packit b5b901
  else
Packit b5b901
    handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
void uv__tcp_close(uv_tcp_t* handle) {
Packit b5b901
  uv__stream_close((uv_stream_t*)handle);
Packit b5b901
}