Browse files

Add keep-alive interval and count options.

The default probe interval and failure counts set by the OS are
too extreme. Lowering them will allow you to know when clients
disconnect sooner, which is helpful if you're running a chat server.
  • Loading branch information...
1 parent 2a8d2a5 commit 1d387de17296bd19bf18ef0920f784d814c78102 @fastest963 committed Mar 1, 2013
Showing with 68 additions and 21 deletions.
  1. +7 −2 include/uv.h
  2. +1 −1 src/unix/internal.h
  3. +2 −2 src/unix/stream.c
  4. +18 −5 src/unix/tcp.c
  5. +39 −10 src/win/tcp.c
  6. +1 −1 test/test-tcp-flags.c
View
9 include/uv.h
@@ -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.
View
2 src/unix/internal.h
@@ -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);
View
4 src/unix/stream.c
@@ -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);
}
View
23 src/unix/tcp.c
@@ -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
@@ -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)
@@ -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;
View
49 src/win/tcp.c
@@ -26,6 +26,7 @@
#include "handle-inl.h"
#include "stream-inl.h"
#include "req-inl.h"
+#include "mstcpip.h"
/*
@@ -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,
@@ -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;
}
@@ -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;
}
@@ -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;
}
View
2 test/test-tcp-flags.c
@@ -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);

0 comments on commit 1d387de

Please sign in to comment.