Skip to content
This repository was archived by the owner on May 4, 2018. It is now read-only.
Open
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
9 changes: 7 additions & 2 deletions include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -653,11 +653,16 @@ UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
/*
* Enable/disable TCP keep-alive.
*
* `delay` is the initial delay in seconds, ignored when `enable` is zero.
* Options below are ignored when `enable` is zero.
* `delay` is the initial delay in seconds. If 0, value is ignored.
* `interval` is the interval in seconds after initial probe. If 0, value is ignored.
* `count` is the number of failed probes before flagging socket dead. If 0, value is ignored. Unix-only.
*/
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
int enable,
unsigned int delay);
unsigned int delay,
unsigned int interval,
unsigned int count);

/*
* This setting applies to Windows only.
Expand Down
2 changes: 1 addition & 1 deletion src/unix/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ int uv__accept(int sockfd);
/* 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 delay);
int uv__tcp_keepalive(int fd, int on, unsigned int delay, unsigned int interval, unsigned int count);

/* pipe */
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
Expand Down
4 changes: 2 additions & 2 deletions src/unix/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,8 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
return uv__set_sys_error(stream->loop, errno);

/* TODO Use delay the user passed in. */
if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60))
/* TODO Use delay, interval, count the user passed in. */
if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60, 0, 0))
return uv__set_sys_error(stream->loop, errno);
}

Expand Down
23 changes: 18 additions & 5 deletions src/unix/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,20 +290,31 @@ int uv__tcp_nodelay(int fd, int on) {
}


int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
int uv__tcp_keepalive(int fd, int on, unsigned int delay,
unsigned int interval, unsigned int count) {
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
return -1;

#ifdef TCP_KEEPIDLE
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
if (on && delay && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
return -1;
#endif

/* Solaris/SmartOS, if you don't support keep-alive,
* then don't advertise it in your system headers...
*/
#if defined(TCP_KEEPALIVE) && !defined(__sun)
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
if (on && delay && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
return -1;
#endif

#ifdef TCP_KEEPINTVL
if (on && interval && setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)))
return -1;
#endif

#ifdef TCP_KEEPCNT
if (on && count && setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof (count)))
return -1;
#endif

Expand All @@ -325,9 +336,10 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
}


int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay,
unsigned int interval, unsigned int count) {
if (uv__stream_fd(handle) != -1)
if (uv__tcp_keepalive(uv__stream_fd(handle), on, delay))
if (uv__tcp_keepalive(uv__stream_fd(handle), on, delay, interval, count))
return -1;

if (on)
Expand All @@ -337,6 +349,7 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {

/* 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...
* same with interval and count
*/

return 0;
Expand Down
49 changes: 39 additions & 10 deletions src/win/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "handle-inl.h"
#include "stream-inl.h"
#include "req-inl.h"
#include "mstcpip.h"


/*
Expand Down Expand Up @@ -57,7 +58,8 @@ static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
}


static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay,
unsigned int interval, unsigned int count) {
if (setsockopt(socket,
SOL_SOCKET,
SO_KEEPALIVE,
Expand All @@ -67,14 +69,41 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
return -1;
}

if (enable && setsockopt(socket,
IPPROTO_TCP,
TCP_KEEPALIVE,
(const char*)&delay,
sizeof delay) == -1) {
#ifdef TCP_KEEPALIVE
if (enable && delay && setsockopt(socket,
IPPROTO_TCP,
TCP_KEEPALIVE,
(const char*)&delay,
sizeof delay) == -1) {
uv__set_sys_error(handle->loop, errno);
return -1;
}
#endif

#ifdef SIO_KEEPALIVE_VALS
if (enable && (delay || interval)) {
struct tcp_keepalive vals;
DWORD outlen = 0;
vals.onoff = 1;
if (!delay) delay = 60 * 60 * 2; /* default is 2 hours */
if (!interval) interval = 1; /* default is 1 second */
vals.keepalivetime = delay * 1000;
vals.keepaliveinterval = interval * 1000;
if (WSAIoctl(socket,
SIO_KEEPALIVE_VALS,
&vals,
sizeof(vals),
NULL,
0,
&outlen,
NULL,
NULL) != 0) {
return -1;
}
}
#endif

/* count cannot be applied without registry changes and system reboot */

return 0;
}
Expand Down Expand Up @@ -129,9 +158,9 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
return -1;
}

/* TODO: Use stored delay. */
/* TODO: Use stored delay, interval, count. */
if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) &&
uv__tcp_keepalive(handle, socket, 1, 60)) {
uv__tcp_keepalive(handle, socket, 1, 60, 0, 0)) {
return -1;
}

Expand Down Expand Up @@ -1194,9 +1223,9 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
}


int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay, unsigned int interval, unsigned int count) {
if (handle->socket != INVALID_SOCKET &&
uv__tcp_keepalive(handle, handle->socket, enable, delay)) {
uv__tcp_keepalive(handle, handle->socket, enable, delay, interval, count)) {
return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion test/test-tcp-flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ TEST_IMPL(tcp_flags) {
r = uv_tcp_nodelay(&handle, 1);
ASSERT(r == 0);

r = uv_tcp_keepalive(&handle, 1, 60);
r = uv_tcp_keepalive(&handle, 1, 60, 60, 8);
ASSERT(r == 0);

uv_close((uv_handle_t*)&handle, NULL);
Expand Down