Terminate inactive server connections

This commit is contained in:
Simon Stürz 2023-02-25 00:13:38 +01:00
parent 45dcf5e62a
commit e5e41e6d3d
7 changed files with 49 additions and 16 deletions

View File

@ -132,6 +132,7 @@ JsonReply *TunnelProxyHandler::DisconnectClient(const QVariantMap &params, Trans
JsonReply *TunnelProxyHandler::Ping(const QVariantMap &params, TransportClient *transportClient)
{
qCDebug(dcJsonRpc()) << name() << "ping received" << params << transportClient;
QVariantMap response;
response.insert("timestamp", params.value("timestamp"));
return createReply("Ping", response);

View File

@ -1,4 +1,4 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
@ -130,6 +130,9 @@ quint64 TransportClient::rxDataCount() const
void TransportClient::addRxDataCount(int dataCount)
{
m_rxDataCount += dataCount;
if (dataCount > 0) {
emit trafficOccurred();
}
}
quint64 TransportClient::txDataCount() const
@ -140,6 +143,9 @@ quint64 TransportClient::txDataCount() const
void TransportClient::addTxDataCount(int dataCount)
{
m_txDataCount += dataCount;
if (dataCount > 0) {
emit trafficOccurred();
}
}
int TransportClient::bufferSize() const

View File

@ -86,6 +86,9 @@ public:
virtual QList<QByteArray> processData(const QByteArray &data) = 0;
signals:
void trafficOccurred();
protected:
TransportInterface *m_interface = nullptr;

View File

@ -11,13 +11,16 @@ TunnelProxyClient::TunnelProxyClient(TransportInterface *interface, const QUuid
{
// Note: a client is not inactive any more once registered successfully as client or server.
// This makes sure we have not any inactive sockets connected to the proxy blocking resources.
// The tunnelproxy server will call makeClientActive once registered successfuly to stop this timer.
m_inactiveTimer.setInterval(Engine::instance()->configuration()->inactiveTimeout());
connect(&m_inactiveTimer, &QTimer::timeout, this, [this](){
m_interface->killClientConnection(m_clientId, "Tunnelproxy timeout occurred. The socket was inactive.");
// The tunnelproxy server will call activateClient once registered successfully to stop this timer.
m_inactiveTimer = new QTimer(this);
m_inactiveTimer->setInterval(Engine::instance()->configuration()->inactiveTimeout());
m_inactiveTimer->setSingleShot(true);
connect(m_inactiveTimer, &QTimer::timeout, this, [this](){
m_interface->killClientConnection(m_clientId, "Tunnelproxy client timeout occurred. The socket was inactive.");
});
m_inactiveTimer.setSingleShot(true);
m_inactiveTimer.start();
m_inactiveTimer->start();
}
TunnelProxyClient::Type TunnelProxyClient::type() const
@ -78,9 +81,27 @@ QList<QByteArray> TunnelProxyClient::processData(const QByteArray &data)
return packets;
}
void TunnelProxyClient::makeClientActive()
void TunnelProxyClient::activateClient()
{
m_inactiveTimer.stop();
// This connection has been registered as TypeServer or TypeClient
m_inactiveTimer->stop();
// We use the inactive timer from now on only for server connections
// to see if the connection is still alive. Server connection ping the
// tunnelproxy every 30 seconds if no other data has been exchanged to
// keep the connection up. If there is no data for more than one minute,
// we consider the connection as dead and terminate the connection.
if (m_type != TypeServer)
return;
connect(this, &TransportClient::trafficOccurred, this, [this](){
m_inactiveTimer->start();
});
m_inactiveTimer->setInterval(60000);
m_inactiveTimer->setSingleShot(true);
m_inactiveTimer->start();
}
QDebug operator<<(QDebug debug, TunnelProxyClient *tunnelProxyClient)

View File

@ -27,13 +27,15 @@ public:
// Json server methods
QList<QByteArray> processData(const QByteArray &data) override;
void makeClientActive();
// This method will be called from the proxy server once the client is
// registered correctly as server or client connection and is now active
void activateClient();
signals:
void typeChanged(Type type);
private:
QTimer m_inactiveTimer;
QTimer *m_inactiveTimer = nullptr;
Type m_type = TypeNone;
};

View File

@ -115,7 +115,7 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerServer(const QUui
// This client has been registered successfully.
// Make sure it does not get disconnected any more because of inactivity.
tunnelProxyClient->makeClientActive();
tunnelProxyClient->activateClient();
tunnelProxyClient->setType(TunnelProxyClient::TypeServer);
tunnelProxyClient->setUuid(serverUuid);
@ -176,7 +176,7 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerClient(const QUui
// This client has been registered successfully.
// Make sure it does not get disconnected any more because due to inactivity.
tunnelProxyClient->makeClientActive();
tunnelProxyClient->activateClient();
// Not registered yet, we have a connected server for the requested server uuid
tunnelProxyClient->setType(TunnelProxyClient::TypeClient);

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Copyright 2013 - 2023, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@ -55,8 +55,6 @@ public:
TunnelProxyClientConnection *getClientConnection(quint16 socketAddress);
signals:
private:
TransportClient *m_transportClient = nullptr;
QUuid m_serverUuid;
@ -68,6 +66,8 @@ private:
QHash<QUuid, TunnelProxyClientConnection *> m_clientConnections;
QHash<quint16, TunnelProxyClientConnection *> m_clientConnectionsAddresses;
quint64 m_lastPingTimestamp = 0;
quint16 getFreeAddress();
};