10e552da7Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
20e552da7Schristos *
30e552da7Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
40e552da7Schristos * of this software and associated documentation files (the "Software"), to
50e552da7Schristos * deal in the Software without restriction, including without limitation the
60e552da7Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
70e552da7Schristos * sell copies of the Software, and to permit persons to whom the Software is
80e552da7Schristos * furnished to do so, subject to the following conditions:
90e552da7Schristos *
100e552da7Schristos * The above copyright notice and this permission notice shall be included in
110e552da7Schristos * all copies or substantial portions of the Software.
120e552da7Schristos *
130e552da7Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
140e552da7Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150e552da7Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160e552da7Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
170e552da7Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
180e552da7Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
190e552da7Schristos * IN THE SOFTWARE.
200e552da7Schristos */
210e552da7Schristos
220e552da7Schristos #include "uv.h"
230e552da7Schristos #include "internal.h"
240e552da7Schristos
250e552da7Schristos #include <stdlib.h>
260e552da7Schristos #include <unistd.h>
270e552da7Schristos #include <assert.h>
280e552da7Schristos #include <errno.h>
290e552da7Schristos
300e552da7Schristos
new_socket(uv_tcp_t * handle,int domain,unsigned long flags)310e552da7Schristos static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
320e552da7Schristos struct sockaddr_storage saddr;
330e552da7Schristos socklen_t slen;
340e552da7Schristos int sockfd;
350e552da7Schristos int err;
360e552da7Schristos
370e552da7Schristos err = uv__socket(domain, SOCK_STREAM, 0);
380e552da7Schristos if (err < 0)
390e552da7Schristos return err;
400e552da7Schristos sockfd = err;
410e552da7Schristos
420e552da7Schristos err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
430e552da7Schristos if (err) {
440e552da7Schristos uv__close(sockfd);
450e552da7Schristos return err;
460e552da7Schristos }
470e552da7Schristos
480e552da7Schristos if (flags & UV_HANDLE_BOUND) {
490e552da7Schristos /* Bind this new socket to an arbitrary port */
500e552da7Schristos slen = sizeof(saddr);
510e552da7Schristos memset(&saddr, 0, sizeof(saddr));
520e552da7Schristos if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
530e552da7Schristos uv__close(sockfd);
540e552da7Schristos return UV__ERR(errno);
550e552da7Schristos }
560e552da7Schristos
570e552da7Schristos if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
580e552da7Schristos uv__close(sockfd);
590e552da7Schristos return UV__ERR(errno);
600e552da7Schristos }
610e552da7Schristos }
620e552da7Schristos
630e552da7Schristos return 0;
640e552da7Schristos }
650e552da7Schristos
660e552da7Schristos
maybe_new_socket(uv_tcp_t * handle,int domain,unsigned long flags)670e552da7Schristos static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
680e552da7Schristos struct sockaddr_storage saddr;
690e552da7Schristos socklen_t slen;
700e552da7Schristos
710e552da7Schristos if (domain == AF_UNSPEC) {
720e552da7Schristos handle->flags |= flags;
730e552da7Schristos return 0;
740e552da7Schristos }
750e552da7Schristos
760e552da7Schristos if (uv__stream_fd(handle) != -1) {
770e552da7Schristos
780e552da7Schristos if (flags & UV_HANDLE_BOUND) {
790e552da7Schristos
800e552da7Schristos if (handle->flags & UV_HANDLE_BOUND) {
810e552da7Schristos /* It is already bound to a port. */
820e552da7Schristos handle->flags |= flags;
830e552da7Schristos return 0;
840e552da7Schristos }
850e552da7Schristos
860e552da7Schristos /* Query to see if tcp socket is bound. */
870e552da7Schristos slen = sizeof(saddr);
880e552da7Schristos memset(&saddr, 0, sizeof(saddr));
890e552da7Schristos if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
900e552da7Schristos return UV__ERR(errno);
910e552da7Schristos
920e552da7Schristos if ((saddr.ss_family == AF_INET6 &&
930e552da7Schristos ((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
940e552da7Schristos (saddr.ss_family == AF_INET &&
950e552da7Schristos ((struct sockaddr_in*) &saddr)->sin_port != 0)) {
960e552da7Schristos /* Handle is already bound to a port. */
970e552da7Schristos handle->flags |= flags;
980e552da7Schristos return 0;
990e552da7Schristos }
1000e552da7Schristos
1010e552da7Schristos /* Bind to arbitrary port */
1020e552da7Schristos if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
1030e552da7Schristos return UV__ERR(errno);
1040e552da7Schristos }
1050e552da7Schristos
1060e552da7Schristos handle->flags |= flags;
1070e552da7Schristos return 0;
1080e552da7Schristos }
1090e552da7Schristos
1100e552da7Schristos return new_socket(handle, domain, flags);
1110e552da7Schristos }
1120e552da7Schristos
1130e552da7Schristos
uv_tcp_init_ex(uv_loop_t * loop,uv_tcp_t * tcp,unsigned int flags)1140e552da7Schristos int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
1150e552da7Schristos int domain;
1160e552da7Schristos
1170e552da7Schristos /* Use the lower 8 bits for the domain */
1180e552da7Schristos domain = flags & 0xFF;
1190e552da7Schristos if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
1200e552da7Schristos return UV_EINVAL;
1210e552da7Schristos
1220e552da7Schristos if (flags & ~0xFF)
1230e552da7Schristos return UV_EINVAL;
1240e552da7Schristos
1250e552da7Schristos uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
1260e552da7Schristos
1270e552da7Schristos /* If anything fails beyond this point we need to remove the handle from
1280e552da7Schristos * the handle queue, since it was added by uv__handle_init in uv_stream_init.
1290e552da7Schristos */
1300e552da7Schristos
1310e552da7Schristos if (domain != AF_UNSPEC) {
1320e552da7Schristos int err = maybe_new_socket(tcp, domain, 0);
1330e552da7Schristos if (err) {
1340e552da7Schristos QUEUE_REMOVE(&tcp->handle_queue);
1350e552da7Schristos return err;
1360e552da7Schristos }
1370e552da7Schristos }
1380e552da7Schristos
1390e552da7Schristos return 0;
1400e552da7Schristos }
1410e552da7Schristos
1420e552da7Schristos
uv_tcp_init(uv_loop_t * loop,uv_tcp_t * tcp)1430e552da7Schristos int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
1440e552da7Schristos return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
1450e552da7Schristos }
1460e552da7Schristos
1470e552da7Schristos
uv__tcp_bind(uv_tcp_t * tcp,const struct sockaddr * addr,unsigned int addrlen,unsigned int flags)1480e552da7Schristos int uv__tcp_bind(uv_tcp_t* tcp,
1490e552da7Schristos const struct sockaddr* addr,
1500e552da7Schristos unsigned int addrlen,
1510e552da7Schristos unsigned int flags) {
1520e552da7Schristos int err;
1530e552da7Schristos int on;
1540e552da7Schristos
1550e552da7Schristos /* Cannot set IPv6-only mode on non-IPv6 socket. */
1560e552da7Schristos if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
1570e552da7Schristos return UV_EINVAL;
1580e552da7Schristos
1590e552da7Schristos err = maybe_new_socket(tcp, addr->sa_family, 0);
1600e552da7Schristos if (err)
1610e552da7Schristos return err;
1620e552da7Schristos
1630e552da7Schristos on = 1;
1640e552da7Schristos if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
1650e552da7Schristos return UV__ERR(errno);
1660e552da7Schristos
1670e552da7Schristos #ifndef __OpenBSD__
1680e552da7Schristos #ifdef IPV6_V6ONLY
1690e552da7Schristos if (addr->sa_family == AF_INET6) {
1700e552da7Schristos on = (flags & UV_TCP_IPV6ONLY) != 0;
1710e552da7Schristos if (setsockopt(tcp->io_watcher.fd,
1720e552da7Schristos IPPROTO_IPV6,
1730e552da7Schristos IPV6_V6ONLY,
1740e552da7Schristos &on,
1750e552da7Schristos sizeof on) == -1) {
1760e552da7Schristos #if defined(__MVS__)
1770e552da7Schristos if (errno == EOPNOTSUPP)
1780e552da7Schristos return UV_EINVAL;
1790e552da7Schristos #endif
1800e552da7Schristos return UV__ERR(errno);
1810e552da7Schristos }
1820e552da7Schristos }
1830e552da7Schristos #endif
1840e552da7Schristos #endif
1850e552da7Schristos
1860e552da7Schristos errno = 0;
187*5f2f4271Schristos err = bind(tcp->io_watcher.fd, addr, addrlen);
188*5f2f4271Schristos if (err == -1 && errno != EADDRINUSE) {
1890e552da7Schristos if (errno == EAFNOSUPPORT)
1900e552da7Schristos /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
1910e552da7Schristos * socket created with AF_INET to an AF_INET6 address or vice versa. */
1920e552da7Schristos return UV_EINVAL;
1930e552da7Schristos return UV__ERR(errno);
1940e552da7Schristos }
195*5f2f4271Schristos tcp->delayed_error = (err == -1) ? UV__ERR(errno) : 0;
1960e552da7Schristos
1970e552da7Schristos tcp->flags |= UV_HANDLE_BOUND;
1980e552da7Schristos if (addr->sa_family == AF_INET6)
1990e552da7Schristos tcp->flags |= UV_HANDLE_IPV6;
2000e552da7Schristos
2010e552da7Schristos return 0;
2020e552da7Schristos }
2030e552da7Schristos
2040e552da7Schristos
uv__tcp_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,unsigned int addrlen,uv_connect_cb cb)2050e552da7Schristos int uv__tcp_connect(uv_connect_t* req,
2060e552da7Schristos uv_tcp_t* handle,
2070e552da7Schristos const struct sockaddr* addr,
2080e552da7Schristos unsigned int addrlen,
2090e552da7Schristos uv_connect_cb cb) {
2100e552da7Schristos int err;
2110e552da7Schristos int r;
2120e552da7Schristos
2130e552da7Schristos assert(handle->type == UV_TCP);
2140e552da7Schristos
2150e552da7Schristos if (handle->connect_req != NULL)
2160e552da7Schristos return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
2170e552da7Schristos
218*5f2f4271Schristos if (handle->delayed_error != 0)
219*5f2f4271Schristos goto out;
220*5f2f4271Schristos
2210e552da7Schristos err = maybe_new_socket(handle,
2220e552da7Schristos addr->sa_family,
2230e552da7Schristos UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
2240e552da7Schristos if (err)
2250e552da7Schristos return err;
2260e552da7Schristos
2270e552da7Schristos do {
2280e552da7Schristos errno = 0;
2290e552da7Schristos r = connect(uv__stream_fd(handle), addr, addrlen);
2300e552da7Schristos } while (r == -1 && errno == EINTR);
2310e552da7Schristos
2320e552da7Schristos /* We not only check the return value, but also check the errno != 0.
2330e552da7Schristos * Because in rare cases connect() will return -1 but the errno
2340e552da7Schristos * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
2350e552da7Schristos * and actually the tcp three-way handshake is completed.
2360e552da7Schristos */
2370e552da7Schristos if (r == -1 && errno != 0) {
2380e552da7Schristos if (errno == EINPROGRESS)
2390e552da7Schristos ; /* not an error */
2400e552da7Schristos else if (errno == ECONNREFUSED
2410e552da7Schristos #if defined(__OpenBSD__)
2420e552da7Schristos || errno == EINVAL
2430e552da7Schristos #endif
2440e552da7Schristos )
2450e552da7Schristos /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
2460e552da7Schristos * next tick to report the error. Solaris and OpenBSD wants to report
2470e552da7Schristos * immediately -- other unixes want to wait.
2480e552da7Schristos */
2490e552da7Schristos handle->delayed_error = UV__ERR(ECONNREFUSED);
2500e552da7Schristos else
2510e552da7Schristos return UV__ERR(errno);
2520e552da7Schristos }
2530e552da7Schristos
254*5f2f4271Schristos out:
255*5f2f4271Schristos
2560e552da7Schristos uv__req_init(handle->loop, req, UV_CONNECT);
2570e552da7Schristos req->cb = cb;
2580e552da7Schristos req->handle = (uv_stream_t*) handle;
2590e552da7Schristos QUEUE_INIT(&req->queue);
2600e552da7Schristos handle->connect_req = req;
2610e552da7Schristos
2620e552da7Schristos uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
2630e552da7Schristos
2640e552da7Schristos if (handle->delayed_error)
2650e552da7Schristos uv__io_feed(handle->loop, &handle->io_watcher);
2660e552da7Schristos
2670e552da7Schristos return 0;
2680e552da7Schristos }
2690e552da7Schristos
2700e552da7Schristos
uv_tcp_open(uv_tcp_t * handle,uv_os_sock_t sock)2710e552da7Schristos int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
2720e552da7Schristos int err;
2730e552da7Schristos
2740e552da7Schristos if (uv__fd_exists(handle->loop, sock))
2750e552da7Schristos return UV_EEXIST;
2760e552da7Schristos
2770e552da7Schristos err = uv__nonblock(sock, 1);
2780e552da7Schristos if (err)
2790e552da7Schristos return err;
2800e552da7Schristos
2810e552da7Schristos return uv__stream_open((uv_stream_t*)handle,
2820e552da7Schristos sock,
2830e552da7Schristos UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
2840e552da7Schristos }
2850e552da7Schristos
2860e552da7Schristos
uv_tcp_getsockname(const uv_tcp_t * handle,struct sockaddr * name,int * namelen)2870e552da7Schristos int uv_tcp_getsockname(const uv_tcp_t* handle,
2880e552da7Schristos struct sockaddr* name,
2890e552da7Schristos int* namelen) {
2900e552da7Schristos
2910e552da7Schristos if (handle->delayed_error)
2920e552da7Schristos return handle->delayed_error;
2930e552da7Schristos
2940e552da7Schristos return uv__getsockpeername((const uv_handle_t*) handle,
2950e552da7Schristos getsockname,
2960e552da7Schristos name,
2970e552da7Schristos namelen);
2980e552da7Schristos }
2990e552da7Schristos
3000e552da7Schristos
uv_tcp_getpeername(const uv_tcp_t * handle,struct sockaddr * name,int * namelen)3010e552da7Schristos int uv_tcp_getpeername(const uv_tcp_t* handle,
3020e552da7Schristos struct sockaddr* name,
3030e552da7Schristos int* namelen) {
3040e552da7Schristos
3050e552da7Schristos if (handle->delayed_error)
3060e552da7Schristos return handle->delayed_error;
3070e552da7Schristos
3080e552da7Schristos return uv__getsockpeername((const uv_handle_t*) handle,
3090e552da7Schristos getpeername,
3100e552da7Schristos name,
3110e552da7Schristos namelen);
3120e552da7Schristos }
3130e552da7Schristos
3140e552da7Schristos
uv_tcp_close_reset(uv_tcp_t * handle,uv_close_cb close_cb)3150e552da7Schristos int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
3160e552da7Schristos int fd;
3170e552da7Schristos struct linger l = { 1, 0 };
3180e552da7Schristos
3190e552da7Schristos /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
3200e552da7Schristos if (handle->flags & UV_HANDLE_SHUTTING)
3210e552da7Schristos return UV_EINVAL;
3220e552da7Schristos
3230e552da7Schristos fd = uv__stream_fd(handle);
324*5f2f4271Schristos if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) {
325*5f2f4271Schristos if (errno == EINVAL) {
326*5f2f4271Schristos /* Open Group Specifications Issue 7, 2018 edition states that
327*5f2f4271Schristos * EINVAL may mean the socket has been shut down already.
328*5f2f4271Schristos * Behavior observed on Solaris, illumos and macOS. */
329*5f2f4271Schristos errno = 0;
330*5f2f4271Schristos } else {
3310e552da7Schristos return UV__ERR(errno);
332*5f2f4271Schristos }
333*5f2f4271Schristos }
3340e552da7Schristos
3350e552da7Schristos uv_close((uv_handle_t*) handle, close_cb);
3360e552da7Schristos return 0;
3370e552da7Schristos }
3380e552da7Schristos
3390e552da7Schristos
uv__tcp_listen(uv_tcp_t * tcp,int backlog,uv_connection_cb cb)340*5f2f4271Schristos int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
341*5f2f4271Schristos static int single_accept_cached = -1;
3420e552da7Schristos unsigned long flags;
343*5f2f4271Schristos int single_accept;
3440e552da7Schristos int err;
3450e552da7Schristos
3460e552da7Schristos if (tcp->delayed_error)
3470e552da7Schristos return tcp->delayed_error;
3480e552da7Schristos
349*5f2f4271Schristos single_accept = uv__load_relaxed(&single_accept_cached);
3500e552da7Schristos if (single_accept == -1) {
3510e552da7Schristos const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
3520e552da7Schristos single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */
353*5f2f4271Schristos uv__store_relaxed(&single_accept_cached, single_accept);
3540e552da7Schristos }
3550e552da7Schristos
3560e552da7Schristos if (single_accept)
3570e552da7Schristos tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
3580e552da7Schristos
3590e552da7Schristos flags = 0;
3600e552da7Schristos #if defined(__MVS__)
3610e552da7Schristos /* on zOS the listen call does not bind automatically
3620e552da7Schristos if the socket is unbound. Hence the manual binding to
3630e552da7Schristos an arbitrary port is required to be done manually
3640e552da7Schristos */
3650e552da7Schristos flags |= UV_HANDLE_BOUND;
3660e552da7Schristos #endif
3670e552da7Schristos err = maybe_new_socket(tcp, AF_INET, flags);
3680e552da7Schristos if (err)
3690e552da7Schristos return err;
3700e552da7Schristos
3710e552da7Schristos if (listen(tcp->io_watcher.fd, backlog))
3720e552da7Schristos return UV__ERR(errno);
3730e552da7Schristos
3740e552da7Schristos tcp->connection_cb = cb;
3750e552da7Schristos tcp->flags |= UV_HANDLE_BOUND;
3760e552da7Schristos
3770e552da7Schristos /* Start listening for connections. */
3780e552da7Schristos tcp->io_watcher.cb = uv__server_io;
3790e552da7Schristos uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
3800e552da7Schristos
3810e552da7Schristos return 0;
3820e552da7Schristos }
3830e552da7Schristos
3840e552da7Schristos
uv__tcp_nodelay(int fd,int on)3850e552da7Schristos int uv__tcp_nodelay(int fd, int on) {
3860e552da7Schristos if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
3870e552da7Schristos return UV__ERR(errno);
3880e552da7Schristos return 0;
3890e552da7Schristos }
3900e552da7Schristos
3910e552da7Schristos
uv__tcp_keepalive(int fd,int on,unsigned int delay)3920e552da7Schristos int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
3930e552da7Schristos if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
3940e552da7Schristos return UV__ERR(errno);
3950e552da7Schristos
3960e552da7Schristos #ifdef TCP_KEEPIDLE
3970e552da7Schristos if (on) {
3980e552da7Schristos int intvl = 1; /* 1 second; same as default on Win32 */
3990e552da7Schristos int cnt = 10; /* 10 retries; same as hardcoded on Win32 */
4000e552da7Schristos if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
4010e552da7Schristos return UV__ERR(errno);
4020e552da7Schristos if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
4030e552da7Schristos return UV__ERR(errno);
4040e552da7Schristos if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
4050e552da7Schristos return UV__ERR(errno);
4060e552da7Schristos }
4070e552da7Schristos #endif
4080e552da7Schristos
4090e552da7Schristos /* Solaris/SmartOS, if you don't support keep-alive,
4100e552da7Schristos * then don't advertise it in your system headers...
4110e552da7Schristos */
4120e552da7Schristos /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
4130e552da7Schristos #if defined(TCP_KEEPALIVE) && !defined(__sun)
4140e552da7Schristos if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
4150e552da7Schristos return UV__ERR(errno);
4160e552da7Schristos #endif
4170e552da7Schristos
4180e552da7Schristos return 0;
4190e552da7Schristos }
4200e552da7Schristos
4210e552da7Schristos
uv_tcp_nodelay(uv_tcp_t * handle,int on)4220e552da7Schristos int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
4230e552da7Schristos int err;
4240e552da7Schristos
4250e552da7Schristos if (uv__stream_fd(handle) != -1) {
4260e552da7Schristos err = uv__tcp_nodelay(uv__stream_fd(handle), on);
4270e552da7Schristos if (err)
4280e552da7Schristos return err;
4290e552da7Schristos }
4300e552da7Schristos
4310e552da7Schristos if (on)
4320e552da7Schristos handle->flags |= UV_HANDLE_TCP_NODELAY;
4330e552da7Schristos else
4340e552da7Schristos handle->flags &= ~UV_HANDLE_TCP_NODELAY;
4350e552da7Schristos
4360e552da7Schristos return 0;
4370e552da7Schristos }
4380e552da7Schristos
4390e552da7Schristos
uv_tcp_keepalive(uv_tcp_t * handle,int on,unsigned int delay)4400e552da7Schristos int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
4410e552da7Schristos int err;
4420e552da7Schristos
4430e552da7Schristos if (uv__stream_fd(handle) != -1) {
4440e552da7Schristos err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
4450e552da7Schristos if (err)
4460e552da7Schristos return err;
4470e552da7Schristos }
4480e552da7Schristos
4490e552da7Schristos if (on)
4500e552da7Schristos handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
4510e552da7Schristos else
4520e552da7Schristos handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
4530e552da7Schristos
4540e552da7Schristos /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
4550e552da7Schristos * uv_tcp_t with an int that's almost never used...
4560e552da7Schristos */
4570e552da7Schristos
4580e552da7Schristos return 0;
4590e552da7Schristos }
4600e552da7Schristos
4610e552da7Schristos
uv_tcp_simultaneous_accepts(uv_tcp_t * handle,int enable)4620e552da7Schristos int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
4630e552da7Schristos if (enable)
4640e552da7Schristos handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
4650e552da7Schristos else
4660e552da7Schristos handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
4670e552da7Schristos return 0;
4680e552da7Schristos }
4690e552da7Schristos
4700e552da7Schristos
uv__tcp_close(uv_tcp_t * handle)4710e552da7Schristos void uv__tcp_close(uv_tcp_t* handle) {
4720e552da7Schristos uv__stream_close((uv_stream_t*)handle);
4730e552da7Schristos }
474*5f2f4271Schristos
475*5f2f4271Schristos
uv_socketpair(int type,int protocol,uv_os_sock_t fds[2],int flags0,int flags1)476*5f2f4271Schristos int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
477*5f2f4271Schristos uv_os_sock_t temp[2];
478*5f2f4271Schristos int err;
479*5f2f4271Schristos #if defined(__FreeBSD__) || defined(__linux__)
480*5f2f4271Schristos int flags;
481*5f2f4271Schristos
482*5f2f4271Schristos flags = type | SOCK_CLOEXEC;
483*5f2f4271Schristos if ((flags0 & UV_NONBLOCK_PIPE) && (flags1 & UV_NONBLOCK_PIPE))
484*5f2f4271Schristos flags |= SOCK_NONBLOCK;
485*5f2f4271Schristos
486*5f2f4271Schristos if (socketpair(AF_UNIX, flags, protocol, temp))
487*5f2f4271Schristos return UV__ERR(errno);
488*5f2f4271Schristos
489*5f2f4271Schristos if (flags & UV_FS_O_NONBLOCK) {
490*5f2f4271Schristos fds[0] = temp[0];
491*5f2f4271Schristos fds[1] = temp[1];
492*5f2f4271Schristos return 0;
493*5f2f4271Schristos }
494*5f2f4271Schristos #else
495*5f2f4271Schristos if (socketpair(AF_UNIX, type, protocol, temp))
496*5f2f4271Schristos return UV__ERR(errno);
497*5f2f4271Schristos
498*5f2f4271Schristos if ((err = uv__cloexec(temp[0], 1)))
499*5f2f4271Schristos goto fail;
500*5f2f4271Schristos if ((err = uv__cloexec(temp[1], 1)))
501*5f2f4271Schristos goto fail;
502*5f2f4271Schristos #endif
503*5f2f4271Schristos
504*5f2f4271Schristos if (flags0 & UV_NONBLOCK_PIPE)
505*5f2f4271Schristos if ((err = uv__nonblock(temp[0], 1)))
506*5f2f4271Schristos goto fail;
507*5f2f4271Schristos if (flags1 & UV_NONBLOCK_PIPE)
508*5f2f4271Schristos if ((err = uv__nonblock(temp[1], 1)))
509*5f2f4271Schristos goto fail;
510*5f2f4271Schristos
511*5f2f4271Schristos fds[0] = temp[0];
512*5f2f4271Schristos fds[1] = temp[1];
513*5f2f4271Schristos return 0;
514*5f2f4271Schristos
515*5f2f4271Schristos fail:
516*5f2f4271Schristos uv__close(temp[0]);
517*5f2f4271Schristos uv__close(temp[1]);
518*5f2f4271Schristos return err;
519*5f2f4271Schristos }
520