diff options
author | Michael Grunder <michael.grunder@gmail.com> | 2022-09-03 12:39:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-03 12:39:57 -0700 |
commit | 61b5b299f0ac4f0efbe11a45716e06a9c35f37b7 (patch) | |
tree | aa27e6e89ac46f0fc8f1032c488924f47fcfeedc | |
parent | fce8abc1c19ab731f5c84797aa71b4d49921913f (diff) |
Use a windows specific keepalive function. (#1104)
Use a windows specific keepalive function.
While it is possible to toggle `TCP_KEEPALIVE` in windows via
setsockopt, you have to use `WSAIoctl` to set the interval.
Since `WSAIoctl` can actually do all of this in one call (toggle the
option, and set the corresponding interval), just use that in Windows
and avoid the call to `setsockopt` alltogether.
Fixes: #1100
-rw-r--r-- | net.c | 9 | ||||
-rw-r--r-- | sockcompat.c | 17 | ||||
-rw-r--r-- | sockcompat.h | 3 | ||||
-rw-r--r-- | test.c | 11 |
4 files changed, 40 insertions, 0 deletions
@@ -168,6 +168,7 @@ int redisKeepAlive(redisContext *c, int interval) { int val = 1; redisFD fd = c->fd; +#ifndef _WIN32 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; @@ -201,7 +202,15 @@ int redisKeepAlive(redisContext *c, int interval) { } #endif #endif +#else + int res; + res = win32_redisKeepAlive(fd, interval * 1000); + if (res != 0) { + __redisSetError(c, REDIS_ERR_OTHER, strerror(res)); + return REDIS_ERR; + } +#endif return REDIS_OK; } diff --git a/sockcompat.c b/sockcompat.c index 31df325..378745f 100644 --- a/sockcompat.c +++ b/sockcompat.c @@ -260,4 +260,21 @@ int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout) { _updateErrno(ret != SOCKET_ERROR); return ret != SOCKET_ERROR ? ret : -1; } + +int win32_redisKeepAlive(SOCKET sockfd, int interval_ms) { + struct tcp_keepalive cfg; + DWORD bytes_in; + int res; + + cfg.onoff = 1; + cfg.keepaliveinterval = interval_ms; + cfg.keepalivetime = interval_ms; + + res = WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, &cfg, + sizeof(struct tcp_keepalive), NULL, 0, + &bytes_in, NULL, NULL); + + return res == 0 ? 0 : _wsaErrorToErrno(res); +} + #endif /* _WIN32 */ diff --git a/sockcompat.h b/sockcompat.h index 85810e8..1aaf23f 100644 --- a/sockcompat.h +++ b/sockcompat.h @@ -50,6 +50,7 @@ #include <ws2tcpip.h> #include <stddef.h> #include <errno.h> +#include <Mstcpip.h> #ifdef _MSC_VER typedef long long ssize_t; @@ -71,6 +72,8 @@ ssize_t win32_send(SOCKET sockfd, const void *buf, size_t len, int flags); typedef ULONG nfds_t; int win32_poll(struct pollfd *fds, nfds_t nfds, int timeout); +int win32_redisKeepAlive(SOCKET sockfd, int interval_ms); + #ifndef REDIS_SOCKCOMPAT_IMPLEMENTATION #define getaddrinfo(node, service, hints, res) win32_getaddrinfo(node, service, hints, res) #undef gai_strerror @@ -405,6 +405,16 @@ static void test_append_formatted_commands(struct config config) { disconnect(c, 0); } +static void test_tcp_options(struct config cfg) { + redisContext *c; + + c = do_connect(cfg); + test("We can enable TCP_KEEPALIVE: "); + test_cond(redisEnableKeepAlive(c) == REDIS_OK); + + disconnect(c, 0); +} + static void test_reply_reader(void) { redisReader *reader; void *reply, *root; @@ -2261,6 +2271,7 @@ int main(int argc, char **argv) { test_blocking_io_errors(cfg); test_invalid_timeout_errors(cfg); test_append_formatted_commands(cfg); + test_tcp_options(cfg); if (throughput) test_throughput(cfg); printf("\nTesting against Unix socket connection (%s): ", cfg.unix_sock.path); |