From: Bruno Jesus <00cpxxx@gmail.com> Subject: ws2_32: Fix support for SIO_KEEPALIVE_VALS Message-Id: Date: Wed, 7 Sep 2011 21:53:22 -0300 From a683e3703bc42124bbf919979b0497b210236f43 Mon Sep 17 00:00:00 2001 From: Bruno Jesus <00cpxxx@gmail.com> Date: Wed, 7 Sep 2011 21:20:37 -0300 Subject: ws2_32: Fix support for SIO_KEEPALIVE_VALS Fix the ms to seconds conversion allowing the function to work if values < 1000 are passed. Set keepalive time and interval only if keep alive is enabled. Fixes bug #21271 Bibliography: http://msdn.microsoft.com/en-us/library/dd877220%28v=vs.85%29.aspx http://linux.die.net/man/7/tcp http://www.yolinux.com/TUTORIALS/Sockets.html http://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/TCP.7P.html http://www.faqs.org/rfcs/rfc1122.html --- dlls/ws2_32/socket.c | 16 ++++++++++++---- dlls/ws2_32/tests/sock.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index ff3c282..4ed4227 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3379,16 +3379,24 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID keepidle = k->keepalivetime / 1000; keepintvl = k->keepaliveinterval / 1000; + /* round values lower than 1000ms to 1 second */ + if (!keepidle && k->keepalivetime) keepidle = 1; + if (!keepintvl && k->keepaliveinterval) keepintvl = 1; + TRACE("onoff: %d, keepalivetime: %d, keepaliveinterval: %d\n", keepalive, keepidle, keepintvl); fd = get_sock_fd(s, 0, NULL); if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(int)) == -1) status = WSAEINVAL; #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) - else if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1) - status = WSAEINVAL; - else if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1) - status = WSAEINVAL; + /* these values need to be set only if SO_KEEPALIVE is enabled */ + else if(keepalive) + { + if (keepidle && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1) + status = WSAEINVAL; + else if (keepintvl && setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1) + status = WSAEINVAL; + } #else else FIXME("ignoring keepalive interval and timeout\n"); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index fd6b8c2..3766186 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -53,6 +53,11 @@ ok ( cond tmp, msg, GetCurrentThreadId(), err); \ } while (0); +#define make_keepalive(k, enable, time, interval) \ + k.onoff = enable; \ + k.keepalivetime = time; \ + k.keepaliveinterval = interval; + /* Function pointers */ static void (WINAPI *pFreeAddrInfoW)(PADDRINFOW) = 0; static int (WINAPI *pGetAddrInfoW)(LPCWSTR,LPCWSTR,const ADDRINFOW *,PADDRINFOW *) = 0; @@ -2933,6 +2938,7 @@ static void test_addr_to_print(void) static void test_ioctlsocket(void) { SOCKET sock; + struct tcp_keepalive kalive; int ret; static const LONG cmds[] = {FIONBIO, FIONREAD, SIOCATMARK}; UINT i; @@ -2972,6 +2978,31 @@ static void test_ioctlsocket(void) ret = WSAGetLastError(); ok(ret == WSAEFAULT || broken(ret == WSAEINVAL), "expected WSAEFAULT, got %d instead\n", ret); + /* broken used to catch W95, W98, NT4 */ + make_keepalive(kalive, 0, 0, 0); + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(struct tcp_keepalive), NULL, 0, &arg, NULL, NULL); + ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n"); + + make_keepalive(kalive, 1, 0, 0); + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(struct tcp_keepalive), NULL, 0, &arg, NULL, NULL); + ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n"); + + make_keepalive(kalive, 1, 1000, 1000); + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(struct tcp_keepalive), NULL, 0, &arg, NULL, NULL); + ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n"); + + make_keepalive(kalive, 1, 10000, 10000); + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(struct tcp_keepalive), NULL, 0, &arg, NULL, NULL); + ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n"); + + make_keepalive(kalive, 1, 100, 100); + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(struct tcp_keepalive), NULL, 0, &arg, NULL, NULL); + ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n"); + + make_keepalive(kalive, 0, 100, 100); + ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(struct tcp_keepalive), NULL, 0, &arg, NULL, NULL); + ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n"); + closesocket(sock); } -- 1.7.5.4