int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { static int single_accept = -1; if (tcp->delayed_error) return uv__set_sys_error(tcp->loop, tcp->delayed_error); if (single_accept == -1) { const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */ } if (single_accept) tcp->flags |= UV_TCP_SINGLE_ACCEPT; if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE)) return -1; if (listen(tcp->io_watcher.fd, backlog)) return uv__set_sys_error(tcp->loop, errno); tcp->connection_cb = cb; /* Start listening for connections. */ tcp->io_watcher.cb = uv__server_io; uv__io_start(tcp->loop, &tcp->io_watcher, UV__POLLIN); return 0; }
static int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr, int addrsize) { int on; if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE)) return -1; on = 1; if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) return uv__set_sys_error(tcp->loop, errno); if (tcp->flags & UV_TCP_V6ONLY) { on = 1; if (setsockopt(tcp->io_watcher.fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) return uv__set_sys_error(tcp->loop, errno); } errno = 0; if (bind(tcp->io_watcher.fd, addr, addrsize) && errno != EADDRINUSE) return uv__set_sys_error(tcp->loop, errno); tcp->delayed_error = errno; return 0; }
static int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr, int addrsize) { int saved_errno; int status; saved_errno = errno; status = -1; if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE)) return -1; tcp->delayed_error = 0; if (bind(tcp->fd, addr, addrsize) == -1) { if (errno == EADDRINUSE) { tcp->delayed_error = errno; } else { uv__set_sys_error(tcp->loop, errno); goto out; } } status = 0; out: errno = saved_errno; return status; }
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) { int domain; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return -EINVAL; if (flags & ~0xFF) return -EINVAL; uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ if (domain != AF_UNSPEC) { int err = maybe_new_socket(tcp, domain, 0); if (err) { QUEUE_REMOVE(&tcp->handle_queue); return err; } } return 0; }
int uv__tcp_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, unsigned int addrlen, uv_connect_cb cb) { int err; int r; assert(handle->type == UV_TCP); if (handle->connect_req != NULL) return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */ err = maybe_new_socket(handle, addr->sa_family, UV_STREAM_READABLE | UV_STREAM_WRITABLE); if (err) return err; handle->delayed_error = 0; do { errno = 0; r = connect(uv__stream_fd(handle), addr, addrlen); } while (r == -1 && errno == EINTR); /* We not only check the return value, but also check the errno != 0. * Because in rare cases connect() will return -1 but the errno * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227) * and actually the tcp three-way handshake is completed. */ if (r == -1 && errno != 0) { if (errno == EINPROGRESS) ; /* not an error */ else if (errno == ECONNREFUSED) /* If we get a ECONNREFUSED wait until the next tick to report the * error. Solaris wants to report immediately--other unixes want to * wait. */ handle->delayed_error = -errno; else return -errno; } uv__req_init(handle->loop, req, UV_CONNECT); req->cb = cb; req->handle = (uv_stream_t*) handle; QUEUE_INIT(&req->queue); handle->connect_req = req; uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); if (handle->delayed_error) uv__io_feed(handle->loop, &handle->io_watcher); return 0; }
int uv__tcp_bind(uv_tcp_t* tcp, const struct sockaddr* addr, unsigned int addrlen, unsigned int flags) { int err; int on; /* Cannot set IPv6-only mode on non-IPv6 socket. */ if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) return -EINVAL; err = maybe_new_socket(tcp, addr->sa_family, 0); if (err) return err; on = 1; if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) return -errno; #ifdef IPV6_V6ONLY if (addr->sa_family == AF_INET6) { on = (flags & UV_TCP_IPV6ONLY) != 0; if (setsockopt(tcp->io_watcher.fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) == -1) { #if defined(__MVS__) if (errno == EOPNOTSUPP) return -EINVAL; #endif return -errno; } } #endif errno = 0; if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) { if (errno == EAFNOSUPPORT) /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a * socket created with AF_INET to an AF_INET6 address or vice versa. */ return -EINVAL; return -errno; } tcp->delayed_error = -errno; tcp->flags |= UV_HANDLE_BOUND; if (addr->sa_family == AF_INET6) tcp->flags |= UV_HANDLE_IPV6; return 0; }
static int uv__connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr* addr, socklen_t addrlen, uv_connect_cb cb) { int err; int r; assert(handle->type == UV_TCP); if (handle->connect_req != NULL) return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */ err = maybe_new_socket(handle, addr->sa_family, UV_STREAM_READABLE | UV_STREAM_WRITABLE); if (err) return err; handle->delayed_error = 0; do r = connect(uv__stream_fd(handle), addr, addrlen); while (r == -1 && errno == EINTR); if (r == -1) { if (errno == EINPROGRESS) ; /* not an error */ else if (errno == ECONNREFUSED) /* If we get a ECONNREFUSED wait until the next tick to report the * error. Solaris wants to report immediately--other unixes want to * wait. */ handle->delayed_error = -errno; else return -errno; } uv__req_init(handle->loop, req, UV_CONNECT); req->cb = cb; req->handle = (uv_stream_t*) handle; QUEUE_INIT(&req->queue); handle->connect_req = req; uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT); if (handle->delayed_error) uv__io_feed(handle->loop, &handle->io_watcher); return 0; }
static int uv__connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr* addr, socklen_t addrlen, uv_connect_cb cb) { int r; assert(handle->type == UV_TCP); if (handle->connect_req) return uv__set_sys_error(handle->loop, EALREADY); if (maybe_new_socket(handle, addr->sa_family, UV_STREAM_READABLE|UV_STREAM_WRITABLE)) { return -1; } handle->delayed_error = 0; do r = connect(handle->fd, addr, addrlen); while (r == -1 && errno == EINTR); if (r == -1) { if (errno == EINPROGRESS) ; /* not an error */ else if (errno == ECONNREFUSED) /* If we get a ECONNREFUSED wait until the next tick to report the * error. Solaris wants to report immediately--other unixes want to * wait. */ handle->delayed_error = errno; else return uv__set_sys_error(handle->loop, errno); } uv__req_init(handle->loop, req, UV_CONNECT); req->cb = cb; req->handle = (uv_stream_t*) handle; ngx_queue_init(&req->queue); handle->connect_req = req; uv__io_start(handle->loop, &handle->write_watcher); if (handle->delayed_error) uv__io_feed(handle->loop, &handle->write_watcher, UV__IO_WRITE); return 0; }
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { if (tcp->delayed_error) return uv__set_sys_error(tcp->loop, tcp->delayed_error); if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE)) return -1; if (listen(tcp->fd, backlog)) return uv__set_sys_error(tcp->loop, errno); tcp->connection_cb = cb; /* Start listening for connections. */ uv__io_set(&tcp->read_watcher, uv__server_io, tcp->fd, UV__IO_READ); uv__io_start(tcp->loop, &tcp->read_watcher); return 0; }
int uv__tcp_bind(uv_tcp_t* tcp, const struct sockaddr* addr, unsigned int addrlen, unsigned int flags) { int err; int on; /* Cannot set IPv6-only mode on non-IPv6 socket. */ if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) return -EINVAL; err = maybe_new_socket(tcp, addr->sa_family, UV_STREAM_READABLE | UV_STREAM_WRITABLE); if (err) return err; on = 1; if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) return -errno; #ifdef IPV6_V6ONLY if (addr->sa_family == AF_INET6) { on = (flags & UV_TCP_IPV6ONLY) != 0; if (setsockopt(tcp->io_watcher.fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) == -1) { return -errno; } } #endif errno = 0; if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) return -errno; tcp->delayed_error = -errno; if (addr->sa_family == AF_INET6) tcp->flags |= UV_HANDLE_IPV6; return 0; }
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { static int single_accept = -1; unsigned long flags; int err; if (tcp->delayed_error) return tcp->delayed_error; if (single_accept == -1) { const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */ } if (single_accept) tcp->flags |= UV_TCP_SINGLE_ACCEPT; flags = 0; #if defined(__MVS__) /* on zOS the listen call does not bind automatically if the socket is unbound. Hence the manual binding to an arbitrary port is required to be done manually */ flags |= UV_HANDLE_BOUND; #endif err = maybe_new_socket(tcp, AF_INET, flags); if (err) return err; if (listen(tcp->io_watcher.fd, backlog)) return -errno; tcp->connection_cb = cb; tcp->flags |= UV_HANDLE_BOUND; /* Start listening for connections. */ tcp->io_watcher.cb = uv__server_io; uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN); return 0; }
static int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr, int addrsize) { int err; int on; err = maybe_new_socket(tcp, domain, UV_STREAM_READABLE | UV_STREAM_WRITABLE); if (err) return err; on = 1; if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) return -errno; errno = 0; if (bind(tcp->io_watcher.fd, addr, addrsize) && errno != EADDRINUSE) return -errno; tcp->delayed_error = -errno; return 0; }
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { static int single_accept = -1; if (tcp->delayed_error) return uv__set_sys_error(tcp->loop, tcp->delayed_error); if (single_accept == -1) { const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); single_accept = (val == NULL) || (atoi(val) != 0); /* on by default */ } if (!single_accept) goto no_single_accept; tcp->idle_handle = malloc(sizeof(*tcp->idle_handle)); if (tcp->idle_handle == NULL) return uv__set_sys_error(tcp->loop, ENOMEM); if (uv_idle_init(tcp->loop, tcp->idle_handle)) abort(); tcp->flags |= UV_TCP_SINGLE_ACCEPT; no_single_accept: if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE)) return -1; if (listen(tcp->fd, backlog)) return uv__set_sys_error(tcp->loop, errno); tcp->connection_cb = cb; /* Start listening for connections. */ uv__io_set(&tcp->read_watcher, uv__server_io, tcp->fd, UV__IO_READ); uv__io_start(tcp->loop, &tcp->read_watcher); return 0; }