Introduce ping for keeping the connection alive
This commit is contained in:
parent
1ca3119995
commit
accb6ec166
@ -79,7 +79,6 @@ public:
|
|||||||
TcpSocketServer *tcpSocketServerTunnelProxy() const;
|
TcpSocketServer *tcpSocketServerTunnelProxy() const;
|
||||||
WebSocketServer *webSocketServerTunnelProxy() const;
|
WebSocketServer *webSocketServerTunnelProxy() const;
|
||||||
|
|
||||||
|
|
||||||
MonitorServer *monitorServer() const;
|
MonitorServer *monitorServer() const;
|
||||||
LogEngine *logEngine() const;
|
LogEngine *logEngine() const;
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,13 @@ TunnelProxyHandler::TunnelProxyHandler(QObject *parent) : JsonHandler(parent)
|
|||||||
returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef());
|
returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef());
|
||||||
setReturns("DisconnectClient", returns);
|
setReturns("DisconnectClient", returns);
|
||||||
|
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
setDescription("Ping", "In order to keep a connection alive when no client is connected, this Ping method can be used. The sent timestamp will be returned as sent in the response for speed measuements on the client side.");
|
||||||
|
params.insert("timestamp", JsonTypes::basicTypeToString(JsonTypes::UInt));
|
||||||
|
setParams("Ping", params);
|
||||||
|
returns.insert("timestamp", JsonTypes::basicTypeToString(JsonTypes::UInt));
|
||||||
|
setReturns("Ping", returns);
|
||||||
|
|
||||||
|
|
||||||
// Client
|
// Client
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
@ -123,6 +130,14 @@ JsonReply *TunnelProxyHandler::DisconnectClient(const QVariantMap ¶ms, Trans
|
|||||||
return createReply("DisconnectClient", response);
|
return createReply("DisconnectClient", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
JsonReply *TunnelProxyHandler::RegisterClient(const QVariantMap ¶ms, TransportClient *transportClient)
|
JsonReply *TunnelProxyHandler::RegisterClient(const QVariantMap ¶ms, TransportClient *transportClient)
|
||||||
{
|
{
|
||||||
qCDebug(dcJsonRpc()) << name() << "register client" << params << transportClient;
|
qCDebug(dcJsonRpc()) << name() << "register client" << params << transportClient;
|
||||||
|
|||||||
@ -48,6 +48,7 @@ public:
|
|||||||
// Server
|
// Server
|
||||||
Q_INVOKABLE JsonReply *RegisterServer(const QVariantMap ¶ms, TransportClient *transportClient);
|
Q_INVOKABLE JsonReply *RegisterServer(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
Q_INVOKABLE JsonReply *DisconnectClient(const QVariantMap ¶ms, TransportClient *transportClient);
|
Q_INVOKABLE JsonReply *DisconnectClient(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
Q_INVOKABLE JsonReply *Ping(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
|
||||||
// Client
|
// Client
|
||||||
Q_INVOKABLE JsonReply *RegisterClient(const QVariantMap ¶ms, TransportClient *transportClient);
|
Q_INVOKABLE JsonReply *RegisterClient(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
|||||||
@ -106,6 +106,18 @@ JsonReply *JsonRpcClient::callDisconnectClient(quint16 socketAddress)
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonReply *JsonRpcClient::callPing(uint timestamp)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("timestamp", timestamp);
|
||||||
|
|
||||||
|
JsonReply *reply = new JsonReply(m_commandId, "TunnelProxy", "Ping", params, this);
|
||||||
|
qCDebug(dcRemoteProxyClientJsonRpc()) << "Calling" << QString("%1.%2").arg(reply->nameSpace()).arg(reply->method());
|
||||||
|
sendRequest(reply->requestMap(), true);
|
||||||
|
m_replies.insert(m_commandId, reply);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
void JsonRpcClient::sendRequest(const QVariantMap &request, bool slipEnabled)
|
void JsonRpcClient::sendRequest(const QVariantMap &request, bool slipEnabled)
|
||||||
{
|
{
|
||||||
QByteArray data = QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + '\n';
|
QByteArray data = QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + '\n';
|
||||||
|
|||||||
@ -57,6 +57,7 @@ public:
|
|||||||
JsonReply *callRegisterServer(const QUuid &serverUuid, const QString &serverName);
|
JsonReply *callRegisterServer(const QUuid &serverUuid, const QString &serverName);
|
||||||
JsonReply *callRegisterClient(const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid);
|
JsonReply *callRegisterClient(const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid);
|
||||||
JsonReply *callDisconnectClient(quint16 socketAddress);
|
JsonReply *callDisconnectClient(quint16 socketAddress);
|
||||||
|
JsonReply *callPing(uint timestamp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProxyConnection *m_connection = nullptr;
|
ProxyConnection *m_connection = nullptr;
|
||||||
|
|||||||
@ -42,7 +42,7 @@ TunnelProxySocketServer::TunnelProxySocketServer(const QUuid &serverUuid, const
|
|||||||
m_serverUuid(serverUuid),
|
m_serverUuid(serverUuid),
|
||||||
m_serverName(serverName)
|
m_serverName(serverName)
|
||||||
{
|
{
|
||||||
setupReconnectTimer();
|
setupTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelProxySocketServer::TunnelProxySocketServer(const QUuid &serverUuid, const QString &serverName, ConnectionType connectionType, QObject *parent) :
|
TunnelProxySocketServer::TunnelProxySocketServer(const QUuid &serverUuid, const QString &serverName, ConnectionType connectionType, QObject *parent) :
|
||||||
@ -51,7 +51,7 @@ TunnelProxySocketServer::TunnelProxySocketServer(const QUuid &serverUuid, const
|
|||||||
m_serverName(serverName),
|
m_serverName(serverName),
|
||||||
m_connectionType(connectionType)
|
m_connectionType(connectionType)
|
||||||
{
|
{
|
||||||
setupReconnectTimer();
|
setupTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelProxySocketServer::~TunnelProxySocketServer()
|
TunnelProxySocketServer::~TunnelProxySocketServer()
|
||||||
@ -189,6 +189,9 @@ void TunnelProxySocketServer::onConnectionDataAvailable(const QByteArray &data)
|
|||||||
{
|
{
|
||||||
qCDebug(dcTunnelProxySocketServerTraffic()) << "Data received" << qUtf8Printable(data);
|
qCDebug(dcTunnelProxySocketServerTraffic()) << "Data received" << qUtf8Printable(data);
|
||||||
|
|
||||||
|
// We recived data, let's reset the keep alive timer
|
||||||
|
m_keepAliveTimer.start();
|
||||||
|
|
||||||
if (m_state != StateRunning) {
|
if (m_state != StateRunning) {
|
||||||
m_jsonClient->processData(data);
|
m_jsonClient->processData(data);
|
||||||
m_dataBuffer.clear();
|
m_dataBuffer.clear();
|
||||||
@ -345,13 +348,13 @@ void TunnelProxySocketServer::requestSocketDisconnect(quint16 socketAddress)
|
|||||||
|
|
||||||
JsonReply *reply = m_jsonClient->callDisconnectClient(socketAddress);
|
JsonReply *reply = m_jsonClient->callDisconnectClient(socketAddress);
|
||||||
connect(reply, &JsonReply::finished, this, [=](){
|
connect(reply, &JsonReply::finished, this, [=](){
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
// TODO: handle errors
|
// TODO: handle errors
|
||||||
qCDebug(dcTunnelProxySocketServer()) << "Request to disconnect client finished" << reply->response();
|
qCDebug(dcTunnelProxySocketServer()) << "Request to disconnect client finished" << reply->response();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelProxySocketServer::setupReconnectTimer()
|
void TunnelProxySocketServer::setupTimers()
|
||||||
{
|
{
|
||||||
m_reconnectTimer.setInterval(5000);
|
m_reconnectTimer.setInterval(5000);
|
||||||
m_reconnectTimer.setSingleShot(false);
|
m_reconnectTimer.setSingleShot(false);
|
||||||
@ -367,6 +370,24 @@ void TunnelProxySocketServer::setupReconnectTimer()
|
|||||||
startServer(m_serverUrl);
|
startServer(m_serverUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_keepAliveTimer.setInterval(30000);
|
||||||
|
m_keepAliveTimer.setSingleShot(false);
|
||||||
|
connect(&m_keepAliveTimer, &QTimer::timeout, this, [this](){
|
||||||
|
if (m_state == StateRunning) {
|
||||||
|
qCDebug(dcTunnelProxySocketServer()) << "Ping the proxy server to keep the connection alive";
|
||||||
|
quint64 requestTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
JsonReply *reply = m_jsonClient->callPing(QDateTime::currentMSecsSinceEpoch() / 1000);
|
||||||
|
connect(reply, &JsonReply::finished, this, [=](){
|
||||||
|
quint64 pingDuration = QDateTime::currentMSecsSinceEpoch() - requestTimestamp;
|
||||||
|
reply->deleteLater();
|
||||||
|
qCDebug(dcTunnelProxySocketServer()) << "Ping response received" << reply->response() << "Duration:" << pingDuration << "ms";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// The server is not running any more
|
||||||
|
m_keepAliveTimer.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelProxySocketServer::setState(State state)
|
void TunnelProxySocketServer::setState(State state)
|
||||||
@ -383,6 +404,7 @@ void TunnelProxySocketServer::setState(State state)
|
|||||||
if (m_state == StateDisconnected && m_enabled) {
|
if (m_state == StateDisconnected && m_enabled) {
|
||||||
qCDebug(dcTunnelProxySocketServer()) << "Starting reconnect timer...";
|
qCDebug(dcTunnelProxySocketServer()) << "Starting reconnect timer...";
|
||||||
m_reconnectTimer.start();
|
m_reconnectTimer.start();
|
||||||
|
m_keepAliveTimer.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,6 +416,13 @@ void TunnelProxySocketServer::setRunning(bool running)
|
|||||||
qCDebug(dcTunnelProxySocketServer()) << "The TunnelProxy server" << (running ? "is now up and running. Listening for remote clients" : "not running any more.");
|
qCDebug(dcTunnelProxySocketServer()) << "The TunnelProxy server" << (running ? "is now up and running. Listening for remote clients" : "not running any more.");
|
||||||
m_running = running;
|
m_running = running;
|
||||||
emit runningChanged(m_running);
|
emit runningChanged(m_running);
|
||||||
|
|
||||||
|
if (m_running) {
|
||||||
|
qCDebug(dcTunnelProxySocketServer()) << "Starting the keep alive timer";
|
||||||
|
m_keepAliveTimer.start();
|
||||||
|
} else {
|
||||||
|
m_keepAliveTimer.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelProxySocketServer::setError(QAbstractSocket::SocketError error)
|
void TunnelProxySocketServer::setError(QAbstractSocket::SocketError error)
|
||||||
|
|||||||
@ -149,6 +149,7 @@ private:
|
|||||||
State m_state = StateDisconnected;
|
State m_state = StateDisconnected;
|
||||||
|
|
||||||
QTimer m_reconnectTimer;
|
QTimer m_reconnectTimer;
|
||||||
|
QTimer m_keepAliveTimer;
|
||||||
bool m_enabled = false;
|
bool m_enabled = false;
|
||||||
|
|
||||||
ProxyConnection *m_connection = nullptr;
|
ProxyConnection *m_connection = nullptr;
|
||||||
@ -159,7 +160,7 @@ private:
|
|||||||
QByteArray m_dataBuffer;
|
QByteArray m_dataBuffer;
|
||||||
|
|
||||||
void requestSocketDisconnect(quint16 socketAddress);
|
void requestSocketDisconnect(quint16 socketAddress);
|
||||||
void setupReconnectTimer();
|
void setupTimers();
|
||||||
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void setRunning(bool running);
|
void setRunning(bool running);
|
||||||
|
|||||||
@ -4,8 +4,8 @@ QT -= gui
|
|||||||
# Define versions
|
# Define versions
|
||||||
SERVER_NAME=nymea-remoteproxy
|
SERVER_NAME=nymea-remoteproxy
|
||||||
API_VERSION_MAJOR=0
|
API_VERSION_MAJOR=0
|
||||||
API_VERSION_MINOR=4
|
API_VERSION_MINOR=5
|
||||||
SERVER_VERSION=0.2.0
|
SERVER_VERSION=0.2.1
|
||||||
|
|
||||||
DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \
|
DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \
|
||||||
SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \
|
SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \
|
||||||
|
|||||||
Reference in New Issue
Block a user