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) JsonReply *TunnelProxyHandler::Ping(const QVariantMap &params, TransportClient *transportClient)
{ {
qCDebug(dcJsonRpc()) << name() << "ping received" << params << transportClient; qCDebug(dcJsonRpc()) << name() << "ping received" << params << transportClient;
QVariantMap response; QVariantMap response;
response.insert("timestamp", params.value("timestamp")); response.insert("timestamp", params.value("timestamp"));
return createReply("Ping", response); return createReply("Ping", response);

View File

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

View File

@ -86,6 +86,9 @@ public:
virtual QList<QByteArray> processData(const QByteArray &data) = 0; virtual QList<QByteArray> processData(const QByteArray &data) = 0;
signals:
void trafficOccurred();
protected: protected:
TransportInterface *m_interface = nullptr; 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. // 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. // 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. // The tunnelproxy server will call activateClient once registered successfully to stop this timer.
m_inactiveTimer.setInterval(Engine::instance()->configuration()->inactiveTimeout()); m_inactiveTimer = new QTimer(this);
connect(&m_inactiveTimer, &QTimer::timeout, this, [this](){ m_inactiveTimer->setInterval(Engine::instance()->configuration()->inactiveTimeout());
m_interface->killClientConnection(m_clientId, "Tunnelproxy timeout occurred. The socket was inactive."); 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 TunnelProxyClient::Type TunnelProxyClient::type() const
@ -78,9 +81,27 @@ QList<QByteArray> TunnelProxyClient::processData(const QByteArray &data)
return packets; 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) QDebug operator<<(QDebug debug, TunnelProxyClient *tunnelProxyClient)

View File

@ -27,13 +27,15 @@ public:
// Json server methods // Json server methods
QList<QByteArray> processData(const QByteArray &data) override; 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: signals:
void typeChanged(Type type); void typeChanged(Type type);
private: private:
QTimer m_inactiveTimer; QTimer *m_inactiveTimer = nullptr;
Type m_type = TypeNone; Type m_type = TypeNone;
}; };

View File

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

View File

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