fix: Enable TCP keepalive by default
Deskflow previously lacked support for TCP keepalive, which meant that dead connections (such as those resulting from a terminated SSH tunnel or an ungraceful network interruption) could remain in the system's connection table indefinitely. This commit adds the setKeepAliveOnSocket method to the IArchNetwork abstraction and implements it for both BSD/Unix and Winsock/Windows backends. Keepalive is now enabled by default in TCPSocket::init, allowing the operating system to eventually detect and clean up stale connections.
This commit is contained in:
parent
acd02a01e6
commit
7d78e55fcc
6 changed files with 33 additions and 0 deletions
|
|
@ -225,6 +225,12 @@ public:
|
|||
*/
|
||||
virtual bool setNoDelayOnSocket(ArchSocket, bool noDelay) = 0;
|
||||
|
||||
//! Turn keep-alive on or off on socket
|
||||
/*!
|
||||
Set socket to use keep-alive (true) or not (false).
|
||||
*/
|
||||
virtual void setKeepAliveOnSocket(ArchSocket, bool keepAlive) = 0;
|
||||
|
||||
//! Turn address reuse on or off on socket
|
||||
/*!
|
||||
Allows the address this socket is bound to to be reused while in the
|
||||
|
|
|
|||
|
|
@ -419,6 +419,17 @@ bool ArchNetworkBSD::setNoDelayOnSocket(ArchSocket s, bool noDelay)
|
|||
return (oflag != 0);
|
||||
}
|
||||
|
||||
void ArchNetworkBSD::setKeepAliveOnSocket(ArchSocket s, bool keepAlive)
|
||||
{
|
||||
if (!s) {
|
||||
throwError(EINVAL);
|
||||
}
|
||||
int opt = keepAlive;
|
||||
if (setsockopt(s->m_fd, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<const optval_t *>(&opt), sizeof(opt)) == -1) {
|
||||
throwError(errno);
|
||||
}
|
||||
}
|
||||
|
||||
bool ArchNetworkBSD::setReuseAddrOnSocket(ArchSocket s, bool reuse)
|
||||
{
|
||||
assert(s != nullptr);
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ public:
|
|||
size_t writeSocket(ArchSocket s, const void *buf, size_t len) override;
|
||||
void throwErrorOnSocket(ArchSocket) override;
|
||||
bool setNoDelayOnSocket(ArchSocket, bool noDelay) override;
|
||||
void setKeepAliveOnSocket(ArchSocket, bool keepAlive) override;
|
||||
bool setReuseAddrOnSocket(ArchSocket, bool reuse) override;
|
||||
ArchNetAddress newAnyAddr(AddressFamily) override;
|
||||
ArchNetAddress copyAddr(ArchNetAddress) override;
|
||||
|
|
|
|||
|
|
@ -605,6 +605,17 @@ bool ArchNetworkWinsock::setNoDelayOnSocket(ArchSocket s, bool noDelay)
|
|||
return (oflag != 0);
|
||||
}
|
||||
|
||||
void ArchNetworkWinsock::setKeepAliveOnSocket(ArchSocket s, bool keepAlive)
|
||||
{
|
||||
if (!s) {
|
||||
throwError(WSAEINVAL);
|
||||
}
|
||||
int opt = keepAlive;
|
||||
if (setsockopt_winsock(s->m_socket, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)) == SOCKET_ERROR) {
|
||||
throwError(getsockerror_winsock());
|
||||
}
|
||||
}
|
||||
|
||||
bool ArchNetworkWinsock::setReuseAddrOnSocket(ArchSocket s, bool reuse)
|
||||
{
|
||||
LOG_ERR("socket re-use not supported on windows");
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ public:
|
|||
size_t writeSocket(ArchSocket s, const void *buf, size_t len) override;
|
||||
void throwErrorOnSocket(ArchSocket) override;
|
||||
bool setNoDelayOnSocket(ArchSocket, bool noDelay) override;
|
||||
void setKeepAliveOnSocket(ArchSocket, bool keepAlive) override;
|
||||
bool setReuseAddrOnSocket(ArchSocket, bool reuse) override;
|
||||
ArchNetAddress newAnyAddr(AddressFamily) override;
|
||||
ArchNetAddress copyAddr(ArchNetAddress) override;
|
||||
|
|
|
|||
|
|
@ -283,6 +283,9 @@ void TCPSocket::init()
|
|||
// that should be sent without (much) delay. for example, the
|
||||
// mouse motion messages are much less useful if they're delayed.
|
||||
ARCH->setNoDelayOnSocket(m_socket, true);
|
||||
|
||||
// turn on keep-alive to avoid dead connections from lingering indefinitely
|
||||
ARCH->setKeepAliveOnSocket(m_socket, true);
|
||||
} catch (const ArchNetworkException &e) {
|
||||
try {
|
||||
ARCH->closeSocket(m_socket);
|
||||
|
|
|
|||
Loading…
Reference in a new issue