Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions deps/uv/docs/src/tcp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,34 +91,6 @@ API

.. versionchanged:: 1.49.0 If `delay` is less than 1 then ``UV_EINVAL``` is returned.

.. c:function:: int uv_tcp_keepalive_ex(uv_tcp_t* handle, int on, unsigned int idle, unsigned int intvl, unsigned int cnt)

Enable / disable TCP keep-alive with all socket options: `TCP_KEEPIDLE`, `TCP_KEEPINTVL` and `TCP_KEEPCNT`.
`idle` is the value for `TCP_KEEPIDLE`, `intvl` is the value for `TCP_KEEPINTVL`,
`cnt` is the value for `TCP_KEEPCNT`, ignored when `on` is zero.

With TCP keep-alive enabled, `idle` is the time (in seconds) the connection needs to remain idle before
TCP starts sending keep-alive probes. `intvl` is the time (in seconds) between individual keep-alive probes.
TCP will drop the connection after sending `cnt` probes without getting any replies from the peer, then the
handle is destroyed with a ``UV_ETIMEDOUT`` error passed to the corresponding callback.

If one of `idle`, `intvl`, or `cnt` is less than 1, ``UV_EINVAL`` is returned.

.. versionchanged:: 1.52.0 added support of setting `TCP_KEEPINTVL` and `TCP_KEEPCNT` socket options.

.. note::
Ensure that the socket options are supported by the underlying operating system.
Currently supported platforms:
- AIX
- DragonFlyBSD
- FreeBSD
- illumos
- Linux
- macOS
- NetBSD
- Solaris
- Windows

.. c:function:: int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable)

Enable / disable simultaneous asynchronous accept requests that are
Expand Down
5 changes: 0 additions & 5 deletions deps/uv/include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -602,11 +602,6 @@ UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
int enable,
unsigned int delay);
UV_EXTERN int uv_tcp_keepalive_ex(uv_tcp_t* handle,
int on,
unsigned int idle,
unsigned int intvl,
unsigned int cnt);
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);

enum uv_tcp_flags {
Expand Down
6 changes: 1 addition & 5 deletions deps/uv/src/unix/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,7 @@ int uv__slurp(const char* filename, char* buf, size_t len);
/* tcp */
int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
int uv__tcp_nodelay(int fd, int on);
int uv__tcp_keepalive(int fd,
int on,
unsigned int idle,
unsigned int intvl,
unsigned int cnt);
int uv__tcp_keepalive(int fd, int on, unsigned int delay);

/* tty */
void uv__tty_close(uv_tty_t* handle);
Expand Down
2 changes: 1 addition & 1 deletion deps/uv/src/unix/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {

/* TODO Use delay the user passed in. */
if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) &&
uv__tcp_keepalive(fd, 1, 60, 1, 10)) {
uv__tcp_keepalive(fd, 1, 60)) {
return UV__ERR(errno);
}
}
Expand Down
47 changes: 22 additions & 25 deletions deps/uv/src/unix/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,18 +465,22 @@ int uv__tcp_nodelay(int fd, int on) {
#else
#define UV_KEEPALIVE_FACTOR(x)
#endif
int uv__tcp_keepalive(int fd,
int on,
unsigned int idle,
unsigned int intvl,
unsigned int cnt) {
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
int idle;
int intvl;
int cnt;

(void) &idle;
(void) &intvl;
(void) &cnt;

if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
return UV__ERR(errno);

if (!on)
return 0;

if (idle < 1 || intvl < 1 || cnt < 1)
if (delay < 1)
return UV_EINVAL;

#ifdef __sun
Expand All @@ -502,16 +506,13 @@ int uv__tcp_keepalive(int fd,
* The TCP connection will be aborted after certain amount of probes, which is set by TCP_KEEPCNT, without receiving response.
*/

/* Kernel expects at least 10 seconds for TCP_KEEPIDLE and TCP_KEEPINTVL. */
idle = delay;
/* Kernel expects at least 10 seconds. */
if (idle < 10)
idle = 10;
if (intvl < 10)
intvl = 10;
/* Kernel expects at most 10 days for TCP_KEEPIDLE and TCP_KEEPINTVL. */
/* Kernel expects at most 10 days. */
if (idle > 10*24*60*60)
idle = 10*24*60*60;
if (intvl > 10*24*60*60)
intvl = 10*24*60*60;

UV_KEEPALIVE_FACTOR(idle);

Expand All @@ -521,10 +522,12 @@ int uv__tcp_keepalive(int fd,
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
return UV__ERR(errno);

intvl = 10; /* required at least 10 seconds */
UV_KEEPALIVE_FACTOR(intvl);
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
return UV__ERR(errno);

cnt = 1; /* 1 retry, ensure (TCP_KEEPINTVL * TCP_KEEPCNT) is 10 seconds */
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
return UV__ERR(errno);
#else
Expand All @@ -536,14 +539,15 @@ int uv__tcp_keepalive(int fd,

/* Note that the consequent probes will not be sent at equal intervals on Solaris,
* but will be sent using the exponential backoff algorithm. */
unsigned int time_to_abort = intvl * cnt;
int time_to_abort = 10; /* 10 seconds */
UV_KEEPALIVE_FACTOR(time_to_abort);
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, &time_to_abort, sizeof(time_to_abort)))
return UV__ERR(errno);
#endif

#else /* !defined(__sun) */

idle = delay;
UV_KEEPALIVE_FACTOR(idle);
#ifdef TCP_KEEPIDLE
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
Expand All @@ -555,12 +559,14 @@ int uv__tcp_keepalive(int fd,
#endif

#ifdef TCP_KEEPINTVL
intvl = 1; /* 1 second; same as default on Win32 */
UV_KEEPALIVE_FACTOR(intvl);
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
return UV__ERR(errno);
#endif

#ifdef TCP_KEEPCNT
cnt = 10; /* 10 retries; same as hardcoded on Win32 */
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
return UV__ERR(errno);
#endif
Expand Down Expand Up @@ -588,20 +594,11 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
}


int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int idle) {
return uv_tcp_keepalive_ex(handle, on, idle, 1, 10);
}


int uv_tcp_keepalive_ex(uv_tcp_t* handle,
int on,
unsigned int idle,
unsigned int intvl,
unsigned int cnt) {
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
int err;

if (uv__stream_fd(handle) != -1) {
err = uv__tcp_keepalive(uv__stream_fd(handle), on, idle, intvl, cnt);
err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
if (err)
return err;
}
Expand All @@ -611,7 +608,7 @@ int uv_tcp_keepalive_ex(uv_tcp_t* handle,
else
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;

/* TODO Store idle if uv__stream_fd(handle) == -1 but don't want to enlarge
/* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
* uv_tcp_t with an int that's almost never used...
*/

Expand Down
126 changes: 31 additions & 95 deletions deps/uv/src/win/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,98 +49,28 @@ static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
}


/*
* Check if Windows version is 10.0.16299 (Windows 10, version 1709) or later.
*/
static int uv__windows10_version1709(void) {
OSVERSIONINFOW os_info;
if (!pRtlGetVersion)
return 0;
pRtlGetVersion(&os_info);
if (os_info.dwMajorVersion < 10)
return 0;
if (os_info.dwMajorVersion > 10)
return 1;
if (os_info.dwMinorVersion > 0)
return 1;
return os_info.dwBuildNumber >= 16299;
}


static int uv__tcp_keepalive(uv_tcp_t* handle,
SOCKET socket,
int on,
unsigned int idle,
unsigned int intvl,
unsigned int cnt) {
static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
if (setsockopt(socket,
SOL_SOCKET,
SO_KEEPALIVE,
(const char*)&on,
sizeof on) == -1) {
(const char*)&enable,
sizeof enable) == -1) {
return WSAGetLastError();
}

if (!on)
if (!enable)
return 0;

if (idle < 1 || intvl < 1 || cnt < 1)
if (delay < 1)
return UV_EINVAL;

/* Windows 10, version 1709 (build 10.0.16299) and later require second units
* for TCP keepalive options. */
if (uv__windows10_version1709()) {
if (setsockopt(socket,
IPPROTO_TCP,
TCP_KEEPIDLE,
(const char*)&idle,
sizeof idle) == -1) {
return WSAGetLastError();
}

if (setsockopt(socket,
IPPROTO_TCP,
TCP_KEEPINTVL,
(const char*)&intvl,
sizeof intvl) == -1) {
return WSAGetLastError();
}

if (setsockopt(socket,
IPPROTO_TCP,
TCP_KEEPCNT,
(const char*)&cnt,
sizeof cnt) == -1) {
return WSAGetLastError();
}

return 0;
}

/* For those versions prior to Windows 10 version 1709,
* we fall back to SIO_KEEPALIVE_VALS that expects millisecond units.
* The SIO_KEEPALIVE_VALS IOCTL is supported on Windows 2000
* and later versions of the operating system. */
struct tcp_keepalive keepalive;
keepalive.onoff = on;
keepalive.keepalivetime = idle * 1000;
keepalive.keepaliveinterval = intvl * 1000;
/* On Windows Vista and later, the number of keep-alive probes
* (data retransmissions) is set to 10 and cannot be changed.
* On Windows Server 2003, Windows XP, and Windows 2000, the default setting
* for number of keep-alive probes is 5 and cannot be changed programmatically.
*/
DWORD dummy;
if (WSAIoctl(socket,
SIO_KEEPALIVE_VALS,
(LPVOID) &keepalive,
sizeof keepalive,
NULL,
0,
&dummy,
NULL,
NULL) == -1)
if (setsockopt(socket,
IPPROTO_TCP,
TCP_KEEPALIVE,
(const char*)&delay,
sizeof delay) == -1) {
return WSAGetLastError();
}

return 0;
}
Expand Down Expand Up @@ -202,7 +132,7 @@ static int uv__tcp_set_socket(uv_loop_t* loop,

/* TODO: Use stored delay. */
if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) {
err = uv__tcp_keepalive(handle, socket, 1, 60, 1, 10);
err = uv__tcp_keepalive(handle, socket, 1, 60);
if (err)
return err;
}
Expand Down Expand Up @@ -819,6 +749,20 @@ static int uv__is_loopback(const struct sockaddr_storage* storage) {
return 0;
}

// Check if Windows version is 10.0.16299 or later
static int uv__is_fast_loopback_fail_supported(void) {
OSVERSIONINFOW os_info;
if (!pRtlGetVersion)
return 0;
pRtlGetVersion(&os_info);
if (os_info.dwMajorVersion < 10)
return 0;
if (os_info.dwMajorVersion > 10)
return 1;
if (os_info.dwMinorVersion > 0)
return 1;
return os_info.dwBuildNumber >= 16299;
}

static int uv__tcp_try_connect(uv_connect_t* req,
uv_tcp_t* handle,
Expand Down Expand Up @@ -865,7 +809,7 @@ static int uv__tcp_try_connect(uv_connect_t* req,
* is not reachable, instead of waiting for 2s. We do not care if this fails.
* This only works on Windows version 10.0.16299 and later.
*/
if (uv__windows10_version1709() && uv__is_loopback(&converted)) {
if (uv__is_fast_loopback_fail_supported() && uv__is_loopback(&converted)) {
memset(&retransmit_ioctl, 0, sizeof(retransmit_ioctl));
retransmit_ioctl.Rtt = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
retransmit_ioctl.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
Expand Down Expand Up @@ -1391,30 +1335,22 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
}


int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int idle) {
return uv_tcp_keepalive_ex(handle, on, idle, 1, 10);
}

int uv_tcp_keepalive_ex(uv_tcp_t* handle,
int on,
unsigned int idle,
unsigned int intvl,
unsigned int cnt) {
int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
int err;

if (handle->socket != INVALID_SOCKET) {
err = uv__tcp_keepalive(handle, handle->socket, on, idle, intvl, cnt);
err = uv__tcp_keepalive(handle, handle->socket, enable, delay);
if (err)
return uv_translate_sys_error(err);
}

if (on) {
if (enable) {
handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
} else {
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
}

/* TODO: Store idle if handle->socket isn't created yet. */
/* TODO: Store delay if handle->socket isn't created yet. */

return 0;
}
Expand Down
Loading
Loading