TCP_USER_TIMEOUT
This commit is contained in:
parent
cdb141ba4a
commit
322438697c
|
@ -228,6 +228,9 @@ interface EventDriverSockets {
|
||||||
*/
|
*/
|
||||||
void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount = 5);
|
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.
|
/** Reads data from a stream socket.
|
||||||
|
|
||||||
Note that only a single read operation is allowed at once. The caller
|
Note that only a single read operation is allowed at once. The caller
|
||||||
|
|
|
@ -50,10 +50,12 @@ version (linux) {
|
||||||
|
|
||||||
// Linux-specific TCP options
|
// Linux-specific TCP options
|
||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/tcp.h#L95
|
// 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 SOL_TCP = 6;
|
||||||
enum TCP_KEEPIDLE = 4;
|
enum TCP_KEEPIDLE = 4;
|
||||||
enum TCP_KEEPINTVL = 5;
|
enum TCP_KEEPINTVL = 5;
|
||||||
enum TCP_KEEPCNT = 6;
|
enum TCP_KEEPCNT = 6;
|
||||||
|
enum TCP_USER_TIMEOUT = 18;
|
||||||
}
|
}
|
||||||
version(OSX) {
|
version(OSX) {
|
||||||
static if (__VERSION__ < 2077) {
|
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); } ();
|
() @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;
|
int opt = enable;
|
||||||
() @trusted { setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, cast(char*)&opt, opt.sizeof); } ();
|
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
|
override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted
|
||||||
{
|
{
|
||||||
version (linux) {
|
version (linux) {
|
||||||
ubyte opt = 1;
|
setKeepAlive(socket, true);
|
||||||
setsockopt(cast(sock_t)socket, SOL_SOCKET, SO_KEEPALIVE, cast(char*)&opt, opt.sizeof);
|
|
||||||
int int_opt = cast(int) idle.total!"seconds"();
|
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"();
|
int_opt = cast(int) interval.total!"seconds"();
|
||||||
setsockopt(cast(sock_t)socket, SOL_TCP, TCP_KEEPINTVL, &int_opt, int.sizeof);
|
err = 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);
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,15 +223,17 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
|
|
||||||
override void setKeepAliveParams(StreamSocketFD socket, Duration idle, Duration interval, int probeCount) @trusted
|
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"(),
|
tcp_keepalive opts = tcp_keepalive(1, cast(ulong) idle.total!"msecs"(),
|
||||||
cast(ulong) interval.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, 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)
|
override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue