Merge pull request #76 from Boris-Barboris/keepalive_params

fix Keepalive on Linux, expose keepalive options, TCP_USER_TIMEOUT for linux.
This commit is contained in:
Sönke Ludwig 2018-08-29 23:16:23 +02:00 committed by GitHub
commit c404cc2e5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 5 deletions

View file

@ -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,20 @@ 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
// Some day we should siply import core.sys.linux.netinet.tcp;
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) {
@ -294,10 +310,45 @@ 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 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 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 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 on setsockopt TCP_KEEPCNT: %s", getSocketError);
}
}
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 on setsockopt TCP_USER_TIMEOUT %s", getSocketError);
}
}
final override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish)