From cdb141ba4a07f1bd79f8e713f5612220de884a1a Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Mon, 2 Apr 2018 11:11:28 +0000 Subject: [PATCH 1/4] add setKeepAliveParams method --- source/eventcore/driver.d | 13 ++++++++++++ source/eventcore/drivers/posix/sockets.d | 22 +++++++++++++++++++++ source/eventcore/drivers/winapi/sockets.d | 12 ++++++++++++ source/eventcore/internal/win32.d | 24 +++++++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/source/eventcore/driver.d b/source/eventcore/driver.d index ddd196b..2c95492 100644 --- a/source/eventcore/driver.d +++ b/source/eventcore/driver.d @@ -215,6 +215,19 @@ interface EventDriverSockets { /// Sets to `SO_KEEPALIVE` socket option on a socket. void setKeepAlive(StreamSocketFD socket, bool enable); + /** Enables keepalive for the TCP socket and sets additional parameters. + Silently ignores unsupported systems. + + Params: + socket = Socket file descriptor to set options on. + idle = The time the connection needs to remain idle + before TCP starts sending keepalive probes. + interval = The time between individual keepalive probes. + probeCount = The maximum number of keepalive probes TCP should send + before dropping the connection. Has no effect on Windows. + */ + void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount = 5); + /** Reads data from a stream socket. Note that only a single read operation is allowed at once. The caller diff --git a/source/eventcore/drivers/posix/sockets.d b/source/eventcore/drivers/posix/sockets.d index 1dc381f..1abeb66 100644 --- a/source/eventcore/drivers/posix/sockets.d +++ b/source/eventcore/drivers/posix/sockets.d @@ -8,6 +8,8 @@ import eventcore.internal.utils; import std.algorithm.comparison : among, min, max; import std.socket : Address, AddressFamily, InternetAddress, Internet6Address, UnknownAddress; +import core.time: Duration; + version (Posix) { import std.socket : UnixAddress; import core.sys.posix.netdb : AI_ADDRCONFIG, AI_V4MAPPED, addrinfo, freeaddrinfo, getaddrinfo; @@ -45,6 +47,13 @@ version (linux) { } else import core.sys.linux.netinet.in_ : IP_ADD_MEMBERSHIP, IP_MULTICAST_LOOP; + + // Linux-specific TCP options + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/tcp.h#L95 + enum SOL_TCP = 6; + enum TCP_KEEPIDLE = 4; + enum TCP_KEEPINTVL = 5; + enum TCP_KEEPCNT = 6; } version(OSX) { static if (__VERSION__ < 2077) { @@ -300,6 +309,19 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets () @trusted { setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, cast(char*)&opt, opt.sizeof); } (); } + override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted + { + version (linux) { + ubyte opt = 1; + setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, cast(char*)&opt, opt.sizeof); + int int_opt = cast(int) idle.total!"seconds"(); + setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPIDLE, &int_opt, int.sizeof); + int_opt = cast(int) interval.total!"seconds"(); + setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPINTVL, &int_opt, int.sizeof); + setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPCNT, &probeCount, int.sizeof); + } + } + final override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish) { /*if (buffer.length == 0) { diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index 7200dd9..8ffeb57 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -221,6 +221,18 @@ final class WinAPIEventDriverSockets : EventDriverSockets { setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &eni, eni.sizeof); } + override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted + { + if (idle < Duration.zero) + assert(0, "negative idle duration"); + if (interval < Duration.zero) + assert(0, "negative interval duration"); + tcp_keepalive opts = tcp_keepalive(1, cast(ulong) idle.total!"msecs"(), + cast(ulong) interval.total!"msecs"); + int result = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &opts, tcp_keepalive.sizeof, null, 0, null, null); + assert(result == 0); + } + override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish) { auto slot = () @trusted { return &m_sockets[socket].streamSocket(); } (); diff --git a/source/eventcore/internal/win32.d b/source/eventcore/internal/win32.d index af068b3..69c99a3 100644 --- a/source/eventcore/internal/win32.d +++ b/source/eventcore/internal/win32.d @@ -104,6 +104,29 @@ struct ADDRINFOW { ADDRINFOW* ai_next; } +// https://msdn.microsoft.com/en-us/library/windows/desktop/dd877220(v=vs.85).aspx +struct tcp_keepalive { + ulong onoff; + ulong keepalivetime; + ulong keepaliveinterval; +}; + +// https://gist.github.com/piscisaureus/906386#file-winsock2-h-L1099 +enum : ulong { + IOC_VENDOR = 0x18000000, + IOC_OUT = 0x40000000, + IOC_IN = 0x80000000 +} + +ulong _WSAIOW(ulong x, ulong y) pure @safe +{ + return IOC_IN | x | y; +} + +enum : ulong { + SIO_KEEPALIVE_VALS = _WSAIOW(IOC_VENDOR, 4) +} + struct WSAPROTOCOL_INFO { DWORD dwServiceFlags1; DWORD dwServiceFlags2; @@ -154,6 +177,7 @@ void FreeAddrInfoExW(ADDRINFOEXW* pAddrInfo); void freeaddrinfo(ADDRINFOA* ai); BOOL TransmitFile(SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, OVERLAPPED* lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags); BOOL CancelIoEx(HANDLE hFile, LPOVERLAPPED lpOverlapped); +int WSAIoctl(SOCKET s, DWORD dwIoControlCode, void* lpvInBuffer, DWORD cbInBuffer, void* lpvOutBuffer, DWORD cbOutBuffer, DWORD* lpcbBytesReturned, in WSAOVERLAPPEDX* lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINEX lpCompletionRoutine); /*struct WSAOVERLAPPEDX { ULONG_PTR Internal; From 322438697cad5b23d2722c91900e123e4bbc8c63 Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Mon, 2 Apr 2018 14:02:09 +0000 Subject: [PATCH 2/4] TCP_USER_TIMEOUT --- source/eventcore/driver.d | 3 ++ source/eventcore/drivers/posix/sockets.d | 50 +++++++++++++++++++---- source/eventcore/drivers/winapi/sockets.d | 12 +++--- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/source/eventcore/driver.d b/source/eventcore/driver.d index 2c95492..eab444f 100644 --- a/source/eventcore/driver.d +++ b/source/eventcore/driver.d @@ -228,6 +228,9 @@ interface EventDriverSockets { */ void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount = 5); + /// Sets `TCP_USER_TIMEOUT` socket option (linux only). https://tools.ietf.org/html/rfc5482 + void setUserTimeout(StreamSocketFD socket, Duration timeout); + /** Reads data from a stream socket. Note that only a single read operation is allowed at once. The caller diff --git a/source/eventcore/drivers/posix/sockets.d b/source/eventcore/drivers/posix/sockets.d index 1abeb66..3d0c1fd 100644 --- a/source/eventcore/drivers/posix/sockets.d +++ b/source/eventcore/drivers/posix/sockets.d @@ -50,10 +50,12 @@ version (linux) { // Linux-specific TCP options // https://github.com/torvalds/linux/blob/master/include/uapi/linux/tcp.h#L95 + // Some day we should siply import core.sys.linux.netinet.tcp; enum SOL_TCP = 6; enum TCP_KEEPIDLE = 4; enum TCP_KEEPINTVL = 5; enum TCP_KEEPCNT = 6; + enum TCP_USER_TIMEOUT = 18; } version(OSX) { static if (__VERSION__ < 2077) { @@ -303,22 +305,54 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets () @trusted { setsockopt(cast(sock_t)socket, IPPROTO_TCP, TCP_NODELAY, cast(char*)&opt, opt.sizeof); } (); } - final override void setKeepAlive(StreamSocketFD socket, bool enable) + override void setKeepAlive(StreamSocketFD socket, bool enable) @trusted { - ubyte opt = enable; - () @trusted { setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, cast(char*)&opt, opt.sizeof); } (); + int opt = enable; + int err = setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, &opt, int.sizeof); + if (err != 0) + { + print("sock error %s", getSocketError); + assert(0, "unable to set SO_KEEPALIVE option"); + } } override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted { version (linux) { - ubyte opt = 1; - setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, cast(char*)&opt, opt.sizeof); + setKeepAlive(socket, true); int int_opt = cast(int) idle.total!"seconds"(); - setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPIDLE, &int_opt, int.sizeof); + int err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPIDLE, &int_opt, int.sizeof); + if (err != 0) + { + print("sock error %s", getSocketError); + assert(0, "unable to set TCP_KEEPIDLE option"); + } int_opt = cast(int) interval.total!"seconds"(); - setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPINTVL, &int_opt, int.sizeof); - setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPCNT, &probeCount, int.sizeof); + err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPINTVL, &int_opt, int.sizeof); + if (err != 0) + { + print("sock error %s", getSocketError); + assert(0, "unable to set TCP_KEEPINTVL option"); + } + err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPCNT, &probeCount, int.sizeof); + if (err != 0) + { + print("sock error %s", getSocketError); + assert(0, "unable to set TCP_KEEPCNT option"); + } + } + } + + override void setUserTimeout(StreamSocketFD socket, Duration timeout) @trusted + { + version (linux) { + uint tmsecs = cast(uint) timeout.total!"msecs"; + int err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_USER_TIMEOUT, &tmsecs, uint.sizeof); + if (err != 0) + { + print("sock error %s", getSocketError); + assert(0, "unable to set TCP_USER_TIMEOUT option"); + } } } diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index 8ffeb57..4b59e32 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -223,16 +223,18 @@ final class WinAPIEventDriverSockets : EventDriverSockets { override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted { - if (idle < Duration.zero) - assert(0, "negative idle duration"); - if (interval < Duration.zero) - assert(0, "negative interval duration"); tcp_keepalive opts = tcp_keepalive(1, cast(ulong) idle.total!"msecs"(), cast(ulong) interval.total!"msecs"); int result = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &opts, tcp_keepalive.sizeof, null, 0, null, null); - assert(result == 0); + if (result != 0) + { + print("WSAIoctl SIO_KEEPALIVE_VALS returned %d", result); + assert(0, "unable to set TCP keepAlive parameters"); + } } + override void setUserTimeout(StreamSocketFD socket, Duration timeout) {} + override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish) { auto slot = () @trusted { return &m_sockets[socket].streamSocket(); } (); From a2d96f18314c2211505b95a62ab976afcb5c3f69 Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Mon, 2 Apr 2018 18:06:00 +0300 Subject: [PATCH 3/4] fix setKeepAliveParams on Windows --- source/eventcore/drivers/winapi/sockets.d | 5 ++++- source/eventcore/internal/win32.d | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index 4b59e32..fb31517 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -8,6 +8,8 @@ import eventcore.internal.win32; import eventcore.internal.utils : AlgebraicChoppedVector, print, nogc_assert; import std.socket : Address; +import core.time: Duration; + private enum WM_USER_SOCKET = WM_USER + 1; @@ -225,7 +227,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets { { tcp_keepalive opts = tcp_keepalive(1, cast(ulong) idle.total!"msecs"(), cast(ulong) interval.total!"msecs"); - int result = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &opts, tcp_keepalive.sizeof, null, 0, null, null); + int result = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &opts, cast(uint) tcp_keepalive.sizeof, + null, 0, null, null, null); if (result != 0) { print("WSAIoctl SIO_KEEPALIVE_VALS returned %d", result); diff --git a/source/eventcore/internal/win32.d b/source/eventcore/internal/win32.d index 69c99a3..2662502 100644 --- a/source/eventcore/internal/win32.d +++ b/source/eventcore/internal/win32.d @@ -112,18 +112,18 @@ struct tcp_keepalive { }; // https://gist.github.com/piscisaureus/906386#file-winsock2-h-L1099 -enum : ulong { +enum : DWORD { IOC_VENDOR = 0x18000000, IOC_OUT = 0x40000000, IOC_IN = 0x80000000 } -ulong _WSAIOW(ulong x, ulong y) pure @safe +DWORD _WSAIOW(DWORD x, DWORD y) pure @safe { return IOC_IN | x | y; } -enum : ulong { +enum : DWORD { SIO_KEEPALIVE_VALS = _WSAIOW(IOC_VENDOR, 4) } From ed9fdcd467a739e3767e08c9a07b0008d1c454be Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Wed, 6 Jun 2018 10:41:20 +0000 Subject: [PATCH 4/4] ease asserting, constants wrapped for future robustness --- source/eventcore/driver.d | 2 +- source/eventcore/drivers/posix/sockets.d | 45 ++++++++++------------- source/eventcore/drivers/winapi/sockets.d | 11 ++---- source/eventcore/internal/win32.d | 7 ++-- source/eventcore/socket.d | 6 +++ tests/0-tcp-readwait.d | 2 +- tests/0-tcp.d | 6 ++- 7 files changed, 41 insertions(+), 38 deletions(-) diff --git a/source/eventcore/driver.d b/source/eventcore/driver.d index eab444f..ed9059c 100644 --- a/source/eventcore/driver.d +++ b/source/eventcore/driver.d @@ -216,7 +216,7 @@ interface EventDriverSockets { void setKeepAlive(StreamSocketFD socket, bool enable); /** Enables keepalive for the TCP socket and sets additional parameters. - Silently ignores unsupported systems. + Silently ignores unsupported systems (anything but Windows and Linux). Params: socket = Socket file descriptor to set options on. diff --git a/source/eventcore/drivers/posix/sockets.d b/source/eventcore/drivers/posix/sockets.d index 3d0c1fd..53361d0 100644 --- a/source/eventcore/drivers/posix/sockets.d +++ b/source/eventcore/drivers/posix/sockets.d @@ -51,11 +51,16 @@ version (linux) { // Linux-specific TCP options // https://github.com/torvalds/linux/blob/master/include/uapi/linux/tcp.h#L95 // Some day we should siply import core.sys.linux.netinet.tcp; - enum SOL_TCP = 6; - enum TCP_KEEPIDLE = 4; - enum TCP_KEEPINTVL = 5; - enum TCP_KEEPCNT = 6; - enum TCP_USER_TIMEOUT = 18; + static if (!is(typeof(SOL_TCP))) + enum SOL_TCP = 6; + static if (!is(typeof(TCP_KEEPIDLE))) + enum TCP_KEEPIDLE = 4; + static if (!is(typeof(TCP_KEEPINTVL))) + enum TCP_KEEPINTVL = 5; + static if (!is(typeof(TCP_KEEPCNT))) + enum TCP_KEEPCNT = 6; + static if (!is(typeof(TCP_USER_TIMEOUT))) + enum TCP_USER_TIMEOUT = 18; } version(OSX) { static if (__VERSION__ < 2077) { @@ -310,36 +315,29 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets int opt = enable; int err = setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, &opt, int.sizeof); if (err != 0) - { - print("sock error %s", getSocketError); - assert(0, "unable to set SO_KEEPALIVE option"); - } + print("sock error in setKeepAlive: %s", getSocketError); } override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted { + // dunnno about BSD\OSX, maybe someone should fix it for them later version (linux) { setKeepAlive(socket, true); int int_opt = cast(int) idle.total!"seconds"(); int err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPIDLE, &int_opt, int.sizeof); - if (err != 0) - { - print("sock error %s", getSocketError); - assert(0, "unable to set TCP_KEEPIDLE option"); + if (err != 0) { + print("sock error on setsockopt TCP_KEEPIDLE: %s", getSocketError); + return; } int_opt = cast(int) interval.total!"seconds"(); err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPINTVL, &int_opt, int.sizeof); - if (err != 0) - { - print("sock error %s", getSocketError); - assert(0, "unable to set TCP_KEEPINTVL option"); + if (err != 0) { + print("sock error on setsockopt TCP_KEEPINTVL: %s", getSocketError); + return; } err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPCNT, &probeCount, int.sizeof); if (err != 0) - { - print("sock error %s", getSocketError); - assert(0, "unable to set TCP_KEEPCNT option"); - } + print("sock error on setsockopt TCP_KEEPCNT: %s", getSocketError); } } @@ -349,10 +347,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets uint tmsecs = cast(uint) timeout.total!"msecs"; int err = setsockopt(cast(sock_t)socket, SOL_TCP, TCP_USER_TIMEOUT, &tmsecs, uint.sizeof); if (err != 0) - { - print("sock error %s", getSocketError); - assert(0, "unable to set TCP_USER_TIMEOUT option"); - } + print("sock error on setsockopt TCP_USER_TIMEOUT %s", getSocketError); } } diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index fb31517..28512d3 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -225,15 +225,12 @@ final class WinAPIEventDriverSockets : EventDriverSockets { override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted { - tcp_keepalive opts = tcp_keepalive(1, cast(ulong) idle.total!"msecs"(), - cast(ulong) interval.total!"msecs"); - int result = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &opts, cast(uint) tcp_keepalive.sizeof, + tcp_keepalive opts = tcp_keepalive(1, cast(c_ulong) idle.total!"msecs"(), + cast(c_ulong) interval.total!"msecs"); + int result = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &opts, cast(DWORD) tcp_keepalive.sizeof, null, 0, null, null, null); if (result != 0) - { - print("WSAIoctl SIO_KEEPALIVE_VALS returned %d", result); - assert(0, "unable to set TCP keepAlive parameters"); - } + print("WSAIoctl error on SIO_KEEPALIVE_VALS: %d", WSAGetLastError()); } override void setUserTimeout(StreamSocketFD socket, Duration timeout) {} diff --git a/source/eventcore/internal/win32.d b/source/eventcore/internal/win32.d index 2662502..9a4a599 100644 --- a/source/eventcore/internal/win32.d +++ b/source/eventcore/internal/win32.d @@ -4,6 +4,7 @@ version(Windows): public import core.sys.windows.windows; public import core.sys.windows.winsock2; +public import core.stdc.config: c_ulong; extern(System) nothrow: @@ -106,9 +107,9 @@ struct ADDRINFOW { // https://msdn.microsoft.com/en-us/library/windows/desktop/dd877220(v=vs.85).aspx struct tcp_keepalive { - ulong onoff; - ulong keepalivetime; - ulong keepaliveinterval; + c_ulong onoff; + c_ulong keepalivetime; + c_ulong keepaliveinterval; }; // https://gist.github.com/piscisaureus/906386#file-winsock2-h-L1099 diff --git a/source/eventcore/socket.d b/source/eventcore/socket.d index 837cded..0dc573f 100644 --- a/source/eventcore/socket.d +++ b/source/eventcore/socket.d @@ -2,6 +2,7 @@ module eventcore.socket; import eventcore.core : eventDriver; import eventcore.driver; +import core.time: Duration; import std.exception : enforce; import std.socket : Address; @@ -49,6 +50,11 @@ struct StreamSocket { @property ConnectionState state() { return eventDriver.sockets.getConnectionState(m_fd); } @property void tcpNoDelay(bool enable) { eventDriver.sockets.setTCPNoDelay(m_fd, enable); } + void setKeepAlive(bool enable) { eventDriver.sockets.setKeepAlive(m_fd, enable); } + void setKeepAliveParams(Duration idle, Duration interval, int probeCount = 5) { + eventDriver.sockets.setKeepAliveParams(m_fd, idle, interval, probeCount); + } + void setUserTimeout(Duration timeout) { eventDriver.sockets.setUserTimeout(m_fd, timeout); } } void read(alias callback)(ref StreamSocket socket, ubyte[] buffer, IOMode mode) diff --git a/tests/0-tcp-readwait.d b/tests/0-tcp-readwait.d index 3b8bfae..e668280 100644 --- a/tests/0-tcp-readwait.d +++ b/tests/0-tcp-readwait.d @@ -19,7 +19,7 @@ void main() writeln("This doesn't work on macOS. Skipping this test until it is determined that this special case should stay supported."); return; } else { - + static ubyte[] pack1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; auto baddr = new InternetAddress(0x7F000001, 40002); diff --git a/tests/0-tcp.d b/tests/0-tcp.d index 75cc479..e7f1760 100644 --- a/tests/0-tcp.d +++ b/tests/0-tcp.d @@ -8,7 +8,7 @@ import eventcore.core; import eventcore.socket; import eventcore.internal.utils : print; import std.socket : InternetAddress; -import core.time : Duration, msecs; +import core.time : Duration, msecs, seconds; ubyte[256] s_rbuf; bool s_done; @@ -69,6 +69,10 @@ void main() client = sock; assert(status == ConnectStatus.connected); assert(sock.state == ConnectionState.connected); + print("Setting keepalive and timeout options"); + client.setKeepAlive(true); + client.setKeepAliveParams(10.seconds, 10.seconds, 4); + client.setUserTimeout(5.seconds); print("Initial write"); client.write!((wstatus, bytes) { print("Initial write done");