From e5e41e6d3d3958cb20c9240c3cb87b700a59c5ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Sat, 25 Feb 2023 00:13:38 +0100 Subject: [PATCH] Terminate inactive server connections --- .../jsonrpc/tunnelproxyhandler.cpp | 1 + .../server/transportclient.cpp | 8 +++- libnymea-remoteproxy/server/transportclient.h | 3 ++ .../tunnelproxy/tunnelproxyclient.cpp | 37 +++++++++++++++---- .../tunnelproxy/tunnelproxyclient.h | 6 ++- .../tunnelproxy/tunnelproxyserver.cpp | 4 +- .../tunnelproxy/tunnelproxyserverconnection.h | 6 +-- 7 files changed, 49 insertions(+), 16 deletions(-) diff --git a/libnymea-remoteproxy/jsonrpc/tunnelproxyhandler.cpp b/libnymea-remoteproxy/jsonrpc/tunnelproxyhandler.cpp index 2e9bde6..cb62549 100644 --- a/libnymea-remoteproxy/jsonrpc/tunnelproxyhandler.cpp +++ b/libnymea-remoteproxy/jsonrpc/tunnelproxyhandler.cpp @@ -132,6 +132,7 @@ JsonReply *TunnelProxyHandler::DisconnectClient(const QVariantMap ¶ms, Trans JsonReply *TunnelProxyHandler::Ping(const QVariantMap ¶ms, TransportClient *transportClient) { qCDebug(dcJsonRpc()) << name() << "ping received" << params << transportClient; + QVariantMap response; response.insert("timestamp", params.value("timestamp")); return createReply("Ping", response); diff --git a/libnymea-remoteproxy/server/transportclient.cpp b/libnymea-remoteproxy/server/transportclient.cpp index aa4bcb6..e20d8e8 100644 --- a/libnymea-remoteproxy/server/transportclient.cpp +++ b/libnymea-remoteproxy/server/transportclient.cpp @@ -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 diff --git a/libnymea-remoteproxy/server/transportclient.h b/libnymea-remoteproxy/server/transportclient.h index 5146afe..f9dff12 100644 --- a/libnymea-remoteproxy/server/transportclient.h +++ b/libnymea-remoteproxy/server/transportclient.h @@ -86,6 +86,9 @@ public: virtual QList processData(const QByteArray &data) = 0; +signals: + void trafficOccurred(); + protected: TransportInterface *m_interface = nullptr; diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp index a9174ab..aece14b 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp @@ -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 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) diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.h b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.h index b772b3c..f036490 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.h +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.h @@ -27,13 +27,15 @@ public: // Json server methods QList 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; }; diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp index 7e141df..4c35412 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp @@ -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); diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.h b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.h index 1366faa..bb29b8a 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.h +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.h @@ -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 m_clientConnections; QHash m_clientConnectionsAddresses; + quint64 m_lastPingTimestamp = 0; + quint16 getFreeAddress(); };