Prepare client library for tunnel proxy

This commit is contained in:
Simon Stürz 2021-07-30 13:12:42 +02:00
parent 56d32bed2b
commit f0cdb2706b
29 changed files with 777 additions and 94 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 104 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,33 +1,39 @@
title Remote tunnel proxy title Remote tunnel proxy
nymea->proxy: RegisterProxyTunnelServer(uuid, name) nymea->proxy: TunnelProxy.RegisterServer(serverUuid, serverName)
note over proxy: Register the server using the uuid note over proxy: Register the server using the uuid
nymea<-proxy: Success nymea<-proxy: TunnelProxyErrorNoError
note over nymea, proxy: Protocol from now on SLIP\nThe proxy is client 0x0000 note over nymea, proxy: Protocol from now on SLIP\nThe proxy is client 0x0000
note over nymea, proxy: SLIP encoded data: 2 Bytes address + data note over nymea, proxy: SLIP encoded data: 2 Bytes address + data
proxy<-client: ConnectProxyTunnelClient(uuid, name, serverUuid) proxy<-client: TunnelProxy.RegisterClient(clientUuid, clientName, serverUuid)
note over proxy: Search server using uuid note over proxy: Search server with given uuid
note over proxy: Server: Assign address 0x0001 for this client socket note over proxy: Server: Assign address for this client socket (0x0001)
proxy->nymea: SLIP:0x0000: ProxyTunnelClientConnected (address: 0x0001) proxy->nymea: SLIP:0x0000: ProxyTunnel.ClientConnected (address: 0x0001)
proxy<-nymea: SLIP:0x0000: AckProxyTunnelClient (address: 0x0001) proxy<-nymea: SLIP:0x0000: ProxyTunnel.AcceptClient (address: 0x0001)
proxy->client: ProxyTunnelEstablished(uuid, name, serverUuid) proxy->nymea: TunnelProxyErrorNoError
note over proxy, client: Protocol from now on SLIP encoded\nThe proxy is client 0x0000\nThe connected server is 0xFFFF proxy->client: ProxyTunnel.ConfirmClient(uuid, name, serverUuid)
note over proxy, client: SLIP encoded data: 2 Bytes address + data note over client: Connected\nAny incomming and outgoing data will\nbe from the connected nymea instance\nuntil disconnected.
note over nymea, client: Connected: The client can now communicate with nymea directly. note over nymea, client: Connected: The client can now communicate with nymea directly.\nThe proxy will not interpret any data from the client, and from the server only\nthe transmission frame (SLIP + 2 bytes of address)
note over nymea, client: nymea sends SLIP encoded data with address 0x0001 -> client
note over nymea, client: client sends SLIP endcoded data with address 0xFFFF -> nymea
proxy<-client: "data"
nymea<-proxy: SLIP:0x0001 "data"
nymea->proxy: SLIP:0x0001 "data"
proxy->client: "data"

View File

@ -294,12 +294,34 @@ void Engine::clean()
m_proxyServer = nullptr; m_proxyServer = nullptr;
} }
if (m_tunnelProxyServer) {
m_tunnelProxyServer->stopServer();
delete m_tunnelProxyServer;
m_tunnelProxyServer = nullptr;
}
if (m_tcpSocketServerProxy) {
delete m_tcpSocketServerProxy;
m_tcpSocketServerProxy = nullptr;
}
if (m_webSocketServerProxy) { if (m_webSocketServerProxy) {
delete m_webSocketServerProxy; delete m_webSocketServerProxy;
m_webSocketServerProxy = nullptr; m_webSocketServerProxy = nullptr;
} }
if (m_tcpSocketServerTunnelProxy) {
delete m_tcpSocketServerTunnelProxy;
m_tcpSocketServerTunnelProxy = nullptr;
}
if (m_webSocketServerTunnelProxy) {
delete m_webSocketServerTunnelProxy;
m_webSocketServerTunnelProxy = nullptr;
}
if (m_configuration) { if (m_configuration) {
delete m_configuration;
m_configuration = nullptr; m_configuration = nullptr;
} }
} }

View File

@ -83,7 +83,6 @@ public:
MonitorServer *monitorServer() const; MonitorServer *monitorServer() const;
LogEngine *logEngine() const; LogEngine *logEngine() const;
private: private:
explicit Engine(QObject *parent = nullptr); explicit Engine(QObject *parent = nullptr);
~Engine(); ~Engine();

View File

@ -40,6 +40,7 @@ TunnelProxyHandler::TunnelProxyHandler(QObject *parent) : JsonHandler(parent)
// Methods // Methods
QVariantMap params; QVariantMap returns; QVariantMap params; QVariantMap returns;
// Server
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RegisterServer", "Register a new TunnelProxy server on this instance. Multiple TunnelProxy clients can be connected to the registered server on success."); setDescription("RegisterServer", "Register a new TunnelProxy server on this instance. Multiple TunnelProxy clients can be connected to the registered server on success.");
params.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String));
@ -48,6 +49,7 @@ TunnelProxyHandler::TunnelProxyHandler(QObject *parent) : JsonHandler(parent)
returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef()); returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef());
setReturns("RegisterServer", returns); setReturns("RegisterServer", returns);
// Client
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RegisterClient", "Register a new TunnelProxy client on TunnelProxy server with the given serverUuid.."); setDescription("RegisterClient", "Register a new TunnelProxy client on TunnelProxy server with the given serverUuid..");
params.insert("clientName", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("clientName", JsonTypes::basicTypeToString(JsonTypes::String));
@ -58,6 +60,8 @@ TunnelProxyHandler::TunnelProxyHandler(QObject *parent) : JsonHandler(parent)
setReturns("RegisterClient", returns); setReturns("RegisterClient", returns);
// Notifications // Notifications
// Server
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ClientConnected", "Emitted whenever a new client has been connected to a registered server. " setDescription("ClientConnected", "Emitted whenever a new client has been connected to a registered server. "
"Only tunnel proxy clients registered as server will receive this notification."); "Only tunnel proxy clients registered as server will receive this notification.");

View File

@ -247,6 +247,9 @@ void JsonRpcServer::processDataPackage(TransportClient *transportClient, const Q
reply->setClientId(transportClient->clientId()); reply->setClientId(transportClient->clientId());
reply->setCommandId(commandId); reply->setCommandId(commandId);
sendResponse(transportClient, commandId, reply->data()); sendResponse(transportClient, commandId, reply->data());
// TODO: check if the client should be disconnected after this response
reply->deleteLater(); reply->deleteLater();
} }
} }

View File

@ -65,6 +65,7 @@ void TcpSocketServer::killClientConnection(const QUuid &clientId, const QString
return; return;
qCWarning(dcTcpSocketServer()) << "Killing client connection" << clientId.toString() << "Reason:" << killReason; qCWarning(dcTcpSocketServer()) << "Killing client connection" << clientId.toString() << "Reason:" << killReason;
client->flush();
client->close(); client->close();
} }
@ -139,7 +140,6 @@ SslServer::SslServer(bool sslEnabled, const QSslConfiguration &config, QObject *
QTcpServer(parent), QTcpServer(parent),
m_sslEnabled(sslEnabled), m_sslEnabled(sslEnabled),
m_config(config) m_config(config)
{ {
} }

View File

@ -77,6 +77,7 @@ void WebSocketServer::killClientConnection(const QUuid &clientId, const QString
return; return;
qCWarning(dcWebSocketServer()) << "Killing client connection" << clientId.toString() << "Reason:" << killReason; qCWarning(dcWebSocketServer()) << "Killing client connection" << clientId.toString() << "Reason:" << killReason;
client->flush();
client->close(QWebSocketProtocol::CloseCodeBadOperation, killReason); client->close(QWebSocketProtocol::CloseCodeBadOperation, killReason);
} }

View File

@ -23,22 +23,36 @@ void TunnelProxyClient::setType(Type type)
emit typeChanged(m_type); emit typeChanged(m_type);
} }
bool TunnelProxyClient::slipEnabled() const
{
return m_slipEnabled;
}
void TunnelProxyClient::setSlipEnabled(bool slipEnabled)
{
m_slipEnabled = slipEnabled;
}
QList<QByteArray> TunnelProxyClient::processData(const QByteArray &data) QList<QByteArray> TunnelProxyClient::processData(const QByteArray &data)
{ {
// TODO: unescape if this data is for the json handler // TODO: unescape if this data is for the json handler
QList<QByteArray> packages; QList<QByteArray> packages;
// Handle packet fragmentation if (m_slipEnabled) {
m_dataBuffers.append(data);
int splitIndex = m_dataBuffers.indexOf("}\n{"); } else {
while (splitIndex > -1) { // Handle json packet fragmentation
packages.append(m_dataBuffers.left(splitIndex + 1)); m_dataBuffers.append(data);
m_dataBuffers = m_dataBuffers.right(m_dataBuffers.length() - splitIndex - 2); int splitIndex = m_dataBuffers.indexOf("}\n{");
splitIndex = m_dataBuffers.indexOf("}\n{"); while (splitIndex > -1) {
} packages.append(m_dataBuffers.left(splitIndex + 1));
if (m_dataBuffers.trimmed().endsWith("}")) { m_dataBuffers = m_dataBuffers.right(m_dataBuffers.length() - splitIndex - 2);
packages.append(m_dataBuffers); splitIndex = m_dataBuffers.indexOf("}\n{");
m_dataBuffers.clear(); }
if (m_dataBuffers.trimmed().endsWith("}")) {
packages.append(m_dataBuffers);
m_dataBuffers.clear();
}
} }
return packages; return packages;
@ -47,16 +61,12 @@ QList<QByteArray> TunnelProxyClient::processData(const QByteArray &data)
QDebug operator<<(QDebug debug, TunnelProxyClient *tunnelProxyClient) QDebug operator<<(QDebug debug, TunnelProxyClient *tunnelProxyClient)
{ {
debug.nospace() << "TunnelProxyClient("; debug.nospace() << "TunnelProxyClient(";
if (!tunnelProxyClient->name().isEmpty()) { debug.nospace() << tunnelProxyClient->name() << ", ";
debug.nospace() << tunnelProxyClient->name() << ", "; debug.nospace() << tunnelProxyClient->interface()->serverName()<< ", ";
} debug.nospace() << tunnelProxyClient->clientId().toString()<< ", ";
debug.nospace() << tunnelProxyClient->peerAddress().toString() << ", ";
debug.nospace() << tunnelProxyClient->interface()->serverName(); debug.nospace() << tunnelProxyClient->creationTimeString() << ")";
debug.nospace() << ", " << tunnelProxyClient->clientId().toString();
debug.nospace() << ", " << tunnelProxyClient->peerAddress().toString();
debug.nospace() << ", " << tunnelProxyClient->creationTimeString() << ")";
return debug.space(); return debug.space();
} }
} }

View File

@ -23,6 +23,9 @@ public:
Type type() const; Type type() const;
void setType(Type type); void setType(Type type);
bool slipEnabled() const;
void setSlipEnabled(bool slipEnabled);
// Json server methods // Json server methods
QList<QByteArray> processData(const QByteArray &data) override; QList<QByteArray> processData(const QByteArray &data) override;
@ -31,6 +34,7 @@ signals:
private: private:
Type m_type = TypeNone; Type m_type = TypeNone;
bool m_slipEnabled = false;
}; };

View File

@ -30,9 +30,10 @@
namespace remoteproxy { namespace remoteproxy {
TunnelProxyClientConnection::TunnelProxyClientConnection(TransportClient *transportClient, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid, QObject *parent) : TunnelProxyClientConnection::TunnelProxyClientConnection(TransportClient *transportClient, TunnelProxyServerConnection *serverConnection, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid, QObject *parent) :
QObject(parent), QObject(parent),
m_transportClient(transportClient), m_transportClient(transportClient),
m_serverConnection(serverConnection),
m_clientUuid(clientUuid), m_clientUuid(clientUuid),
m_clientName(clientName), m_clientName(clientName),
m_serverUuid(serverUuid) m_serverUuid(serverUuid)
@ -45,6 +46,11 @@ TransportClient *TunnelProxyClientConnection::transportClient() const
return m_transportClient; return m_transportClient;
} }
TunnelProxyServerConnection *TunnelProxyClientConnection::serverConnection() const
{
return m_serverConnection;
}
QUuid TunnelProxyClientConnection::clientUuid() const QUuid TunnelProxyClientConnection::clientUuid() const
{ {
return m_clientUuid; return m_clientUuid;
@ -60,4 +66,13 @@ QUuid TunnelProxyClientConnection::serverUuid() const
return m_serverUuid; return m_serverUuid;
} }
QDebug operator<<(QDebug debug, TunnelProxyClientConnection *clientConnection)
{
debug.nospace() << "TunnelProxyClientConnection(";
debug.nospace() << clientConnection->clientName() << ", ";
debug.nospace() << clientConnection->clientUuid().toString() << ", ";
debug.nospace() << clientConnection->transportClient() << ")";
return debug.space();
}
} }

View File

@ -30,27 +30,30 @@
#include <QUuid> #include <QUuid>
#include <QObject> #include <QObject>
#include <QDebug>
namespace remoteproxy { namespace remoteproxy {
class TransportClient; class TransportClient;
class TunnelProxyServerConnection;
class TunnelProxyClientConnection : public QObject class TunnelProxyClientConnection : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TunnelProxyClientConnection(TransportClient *transportClient, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid, QObject *parent = nullptr); explicit TunnelProxyClientConnection(TransportClient *transportClient, TunnelProxyServerConnection *serverConnection, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid, QObject *parent = nullptr);
TransportClient *transportClient() const; TransportClient *transportClient() const;
TunnelProxyServerConnection *serverConnection() const;
QUuid clientUuid() const; QUuid clientUuid() const;
QString clientName() const; QString clientName() const;
QUuid serverUuid() const; QUuid serverUuid() const;
signals:
private: private:
TransportClient *m_transportClient = nullptr; TransportClient *m_transportClient = nullptr;
TunnelProxyServerConnection *m_serverConnection = nullptr;
QUuid m_clientUuid; QUuid m_clientUuid;
QString m_clientName; QString m_clientName;
@ -58,6 +61,8 @@ private:
}; };
QDebug operator<<(QDebug debug, TunnelProxyClientConnection *clientConnection);
} }
#endif // TUNNELPROXYCLIENTCONNECTION_H #endif // TUNNELPROXYCLIENTCONNECTION_H

View File

@ -99,6 +99,9 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerServer(const QUui
tunnelProxyClient->setUuid(serverUuid); tunnelProxyClient->setUuid(serverUuid);
tunnelProxyClient->setName(serverName); tunnelProxyClient->setName(serverName);
// Enable SLIP from now on
// tunnelProxyClient->setSlipEnabled(true);
TunnelProxyServerConnection *serverConnection = new TunnelProxyServerConnection(tunnelProxyClient, serverUuid, serverName, this); TunnelProxyServerConnection *serverConnection = new TunnelProxyServerConnection(tunnelProxyClient, serverUuid, serverName, this);
m_tunnelProxyServerConnections.insert(serverUuid, serverConnection); m_tunnelProxyServerConnections.insert(serverUuid, serverConnection);
@ -121,6 +124,11 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerClient(const QUui
return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered; return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered;
} }
if (m_tunnelProxyClientConnections.contains(clientUuid)) {
qCWarning(dcTunnelProxyServer()) << "There is a client already registered with client uuid" << clientUuid.toString();
return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered;
}
// Get the desired server connection // Get the desired server connection
TunnelProxyServerConnection *serverConnection = m_tunnelProxyServerConnections.value(serverUuid); TunnelProxyServerConnection *serverConnection = m_tunnelProxyServerConnections.value(serverUuid);
if (!serverConnection) { if (!serverConnection) {
@ -128,20 +136,18 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerClient(const QUui
return TunnelProxyServer::TunnelProxyErrorServerNotFound; return TunnelProxyServer::TunnelProxyErrorServerNotFound;
} }
if (m_tunnelProxyClientConnections.contains(clientUuid)) {
qCWarning(dcTunnelProxyServer()) << "There is a client already registered with client uuid" << clientUuid.toString();
return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered;
}
// 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);
tunnelProxyClient->setUuid(clientUuid); tunnelProxyClient->setUuid(clientUuid);
tunnelProxyClient->setName(clientName); tunnelProxyClient->setName(clientName);
TunnelProxyClientConnection *clientConnection = new TunnelProxyClientConnection(tunnelProxyClient, clientUuid, clientName, serverUuid); TunnelProxyClientConnection *clientConnection = new TunnelProxyClientConnection(tunnelProxyClient, serverConnection, clientUuid, clientName, serverUuid);
m_tunnelProxyClientConnections.insert(clientUuid, clientConnection); m_tunnelProxyClientConnections.insert(clientUuid, clientConnection);
// TODO: register on the server and wait for te aprovement from the server qCDebug(dcTunnelProxyServer()) << "Register client" << clientConnection << "-->" << serverConnection;
serverConnection->registerClientConnection(clientConnection);
// TODO: wait for te aprovement from the server
return TunnelProxyServer::TunnelProxyErrorNoError; return TunnelProxyServer::TunnelProxyErrorNoError;
} }
@ -195,6 +201,8 @@ void TunnelProxyServer::onClientDisconnected(const QUuid &clientId)
if (!serverConnection) { if (!serverConnection) {
qCWarning(dcTunnelProxyServer()) << "Could not find server connection for disconnected tunnel proxy client claiming to be a server."; qCWarning(dcTunnelProxyServer()) << "Could not find server connection for disconnected tunnel proxy client claiming to be a server.";
} else { } else {
// TODO: kill all related clients // TODO: kill all related clients
serverConnection->deleteLater(); serverConnection->deleteLater();
@ -203,11 +211,13 @@ void TunnelProxyServer::onClientDisconnected(const QUuid &clientId)
if (tunnelProxyClient->type() == TunnelProxyClient::TypeClient) { if (tunnelProxyClient->type() == TunnelProxyClient::TypeClient) {
TunnelProxyClientConnection *clientConnection = m_tunnelProxyClientConnections.take(tunnelProxyClient->uuid()); TunnelProxyClientConnection *clientConnection = m_tunnelProxyClientConnections.take(tunnelProxyClient->uuid());
if (!clientConnection) { if (!clientConnection) {
qCWarning(dcTunnelProxyServer()) << "Could not find client connection for disconnected tunnel proxy client claiming to be a client."; qCWarning(dcTunnelProxyServer()) << "Could not find client connection for disconnected tunnel proxy client claiming to be a client.";
} else { } else {
// TODO: remove from server if (clientConnection->serverConnection()) {
clientConnection->serverConnection()->unregisterClientConnection(clientConnection);
// TODO: Send client disconnected to the server
}
clientConnection->deleteLater(); clientConnection->deleteLater();
} }
@ -229,10 +239,23 @@ void TunnelProxyServer::onClientDataAvailable(const QUuid &clientId, const QByte
} }
qCDebug(dcTunnelProxyServerTraffic()) << "Client data available" << tunnelProxyClient << qUtf8Printable(data); qCDebug(dcTunnelProxyServerTraffic()) << "Client data available" << tunnelProxyClient << qUtf8Printable(data);
if (tunnelProxyClient->type() == TunnelProxyClient::TypeClient) {
// Send the data to the server using slip + frame
// TODO: verify if encoded and for whom this data is... 0x0000 is for the json rpc handler...
m_jsonRpcServer->processData(tunnelProxyClient, data); } else if (tunnelProxyClient->type() == TunnelProxyClient::TypeServer) {
if (tunnelProxyClient->slipEnabled()) {
} else {
m_jsonRpcServer->processData(tunnelProxyClient, data);
}
// Unpack SLIP data, get address, pipe to client or give it to the json rpc server if address 0x0000
} else {
// Not registered yet or doing other stuff...let the JSON RPC handle this data
m_jsonRpcServer->processData(tunnelProxyClient, data);
}
} }
} }

View File

@ -27,6 +27,7 @@
#include "tunnelproxyserverconnection.h" #include "tunnelproxyserverconnection.h"
#include "server/transportclient.h" #include "server/transportclient.h"
#include "tunnelproxyclientconnection.h"
namespace remoteproxy { namespace remoteproxy {
@ -54,4 +55,23 @@ QString TunnelProxyServerConnection::serverName() const
return m_serverName; return m_serverName;
} }
void TunnelProxyServerConnection::registerClientConnection(TunnelProxyClientConnection *clientConnection)
{
m_clientConnections.insert(clientConnection->clientUuid(), clientConnection);
}
void TunnelProxyServerConnection::unregisterClientConnection(TunnelProxyClientConnection *clientConnection)
{
m_clientConnections.remove(clientConnection->clientUuid());
}
QDebug operator<<(QDebug debug, TunnelProxyServerConnection *serverConnection)
{
debug.nospace() << "TunnelProxyServerConnection(";
debug.nospace() << serverConnection->serverName() << ", ";
debug.nospace() << serverConnection->serverUuid().toString() << ", ";
debug.nospace() << serverConnection->transportClient() << ")";
return debug.space();
}
} }

View File

@ -30,10 +30,12 @@
#include <QUuid> #include <QUuid>
#include <QObject> #include <QObject>
#include <QDebug>
namespace remoteproxy { namespace remoteproxy {
class TransportClient; class TransportClient;
class TunnelProxyClientConnection;
class TunnelProxyServerConnection : public QObject class TunnelProxyServerConnection : public QObject
{ {
@ -46,17 +48,22 @@ public:
QUuid serverUuid() const; QUuid serverUuid() const;
QString serverName() const; QString serverName() const;
void registerClientConnection(TunnelProxyClientConnection *clientConnection);
void unregisterClientConnection(TunnelProxyClientConnection *clientConnection);
signals: signals:
private: private:
TransportClient *m_transportClient = nullptr; TransportClient *m_transportClient = nullptr;
QUuid m_serverUuid; QUuid m_serverUuid;
QString m_serverName; QString m_serverName;
QHash<QUuid, TunnelProxyClientConnection *> m_clientConnections;
}; };
QDebug operator<<(QDebug debug, TunnelProxyServerConnection *serverConnection);
} }
#endif // TUNNELPROXYSERVERCONNECTION_H #endif // TUNNELPROXYSERVERCONNECTION_H

View File

@ -1,18 +1,24 @@
INCLUDEPATH += $${PWD} INCLUDEPATH += $$PWD
HEADERS += \ HEADERS += \
$${PWD}/tcpsocketconnection.h \ $$PWD/tunnelproxy/tunnelproxyjsonrpcclient.h \
$${PWD}/proxyjsonrpcclient.h \ $$PWD/tunnelproxy/tunnelproxysocket.h \
$${PWD}/jsonreply.h \ $$PWD/tunnelproxy/tunnelproxyserver.h \
$${PWD}/remoteproxyconnection.h \ $$PWD/tcpsocketconnection.h \
$${PWD}/proxyconnection.h \ $$PWD/proxyjsonrpcclient.h \
$${PWD}/websocketconnection.h $$PWD/jsonreply.h \
$$PWD/remoteproxyconnection.h \
$$PWD/proxyconnection.h \
$$PWD/websocketconnection.h
SOURCES += \ SOURCES += \
$${PWD}/tcpsocketconnection.cpp \ $$PWD/tunnelproxy/tunnelproxyjsonrpcclient.cpp \
$${PWD}/proxyjsonrpcclient.cpp \ $$PWD/tunnelproxy/tunnelproxysocket.cpp \
$${PWD}/jsonreply.cpp \ $$PWD/tunnelproxy/tunnelproxyserver.cpp \
$${PWD}/remoteproxyconnection.cpp \ $$PWD/tcpsocketconnection.cpp \
$${PWD}/proxyconnection.cpp \ $$PWD/proxyjsonrpcclient.cpp \
$${PWD}/websocketconnection.cpp $$PWD/jsonreply.cpp \
$$PWD/remoteproxyconnection.cpp \
$$PWD/proxyconnection.cpp \
$$PWD/websocketconnection.cpp

View File

@ -0,0 +1,37 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "tunnelproxyjsonrpcclient.h"
namespace remoteproxyclient {
TunnelProxyJsonRpcClient::TunnelProxyJsonRpcClient(QObject *parent) : QObject(parent)
{
}
}

View File

@ -0,0 +1,48 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TUNNELPROXYJSONRPCCLIENT_H
#define TUNNELPROXYJSONRPCCLIENT_H
#include <QObject>
namespace remoteproxyclient {
class TunnelProxyJsonRpcClient : public QObject
{
Q_OBJECT
public:
explicit TunnelProxyJsonRpcClient(QObject *parent = nullptr);
signals:
};
}
#endif // TUNNELPROXYJSONRPCCLIENT_H

View File

@ -0,0 +1,84 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "tunnelproxyserver.h"
#include "proxyconnection.h"
#include "tcpsocketconnection.h"
#include "websocketconnection.h"
namespace remoteproxyclient {
TunnelProxyServer::TunnelProxyServer(const QUuid &serverUuid, const QString &serverName, QObject *parent) :
QObject(parent),
m_serverUuid(serverUuid),
m_serverName(serverName)
{
}
TunnelProxyServer::TunnelProxyServer(const QUuid &serverUuid, const QString &serverName, ConnectionType connectionType, QObject *parent) :
QObject(parent),
m_serverUuid(serverUuid),
m_serverName(serverName),
m_connectionType(connectionType)
{
}
TunnelProxyServer::~TunnelProxyServer()
{
}
bool TunnelProxyServer::running() const
{
return m_running;
}
void TunnelProxyServer::ignoreSslErrors()
{
m_connection->ignoreSslErrors();
}
void TunnelProxyServer::ignoreSslErrors(const QList<QSslError> &errors)
{
m_connection->ignoreSslErrors(errors);
}
void remoteproxyclient::TunnelProxyServer::startServer(const QUrl &serverUrl)
{
// Register as server to the remote proxy
m_serverUrl = serverUrl;
}
void remoteproxyclient::TunnelProxyServer::stopServer()
{
// Close the server connection and all related sockets
}
}

View File

@ -0,0 +1,90 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TUNNELPROXYSERVER_H
#define TUNNELPROXYSERVER_H
#include <QUuid>
#include <QObject>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(dcRemoteProxyTunnelProxyServer)
#include "proxyconnection.h"
#include "tunnelproxysocket.h"
namespace remoteproxyclient {
class ProxyConnection;
class TunnelProxyJsonRpcClient;
class TunnelProxyServer : public QObject
{
Q_OBJECT
public:
enum ConnectionType {
ConnectionTypeWebSocket,
ConnectionTypeTcpSocket
};
Q_ENUM(ConnectionType)
explicit TunnelProxyServer(const QUuid &serverUuid, const QString &serverName, QObject *parent = nullptr);
explicit TunnelProxyServer(const QUuid &serverUuid, const QString &serverName, ConnectionType connectionType, QObject *parent = nullptr);
~TunnelProxyServer();
bool running() const;
QAbstractSocket::SocketError error() const;
void ignoreSslErrors();
void ignoreSslErrors(const QList<QSslError> &errors);
public slots:
void startServer(const QUrl &serverUrl);
void stopServer();
signals:
void runningChanged(bool running);
void sslErrors(const QList<QSslError> &errors);
private:
QUuid m_serverUuid;
QString m_serverName;
ConnectionType m_connectionType = ConnectionTypeTcpSocket;
bool m_running = false;
QUrl m_serverUrl;
QAbstractSocket::SocketError m_error = QAbstractSocket::UnknownSocketError;
ProxyConnection *m_connection = nullptr;
TunnelProxyJsonRpcClient *m_jsonClient = nullptr;
};
}
#endif // TUNNELPROXYSERVER_H

View File

@ -0,0 +1,37 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "tunnelproxysocket.h"
namespace remoteproxyclient {
TunnelProxySocket::TunnelProxySocket(QObject *parent) : QObject(parent)
{
}
}

View File

@ -0,0 +1,47 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TUNNELPROXYSOCKET_H
#define TUNNELPROXYSOCKET_H
#include <QObject>
namespace remoteproxyclient {
class TunnelProxySocket : public QObject
{
Q_OBJECT
public:
explicit TunnelProxySocket(QObject *parent = nullptr);
signals:
};
}
#endif // TUNNELPROXYSOCKET_H

View File

@ -4,7 +4,7 @@ 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=3 API_VERSION_MINOR=4
SERVER_VERSION=0.2.0 SERVER_VERSION=0.2.0
DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \ DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \

View File

@ -45,12 +45,24 @@ RemoteProxyTestsProxy::RemoteProxyTestsProxy(QObject *parent) :
void RemoteProxyTestsProxy::startStopServer() void RemoteProxyTestsProxy::startStopServer()
{ {
resetDebugCategories();
addDebugCategory("ProxyServer.debug=true");
addDebugCategory("Engine.debug=true");
addDebugCategory("JsonRpc.debug=true");
addDebugCategory("TcpSocketServer.debug=true");
addDebugCategory("WebSocketServer.debug=true");
startServer(); startServer();
stopServer(); stopServer();
resetDebugCategories();
} }
void RemoteProxyTestsProxy::dummyAuthenticator() void RemoteProxyTestsProxy::dummyAuthenticator()
{ {
resetDebugCategories();
addDebugCategory("ProxyServer.debug=true");
cleanUpEngine(); cleanUpEngine();
m_configuration = new ProxyConfiguration(this); m_configuration = new ProxyConfiguration(this);
@ -411,7 +423,7 @@ void RemoteProxyTestsProxy::getHello()
// WebSocket // WebSocket
response = invokeWebSocketProxyApiCall("RemoteProxy.Hello").toMap(); response = invokeWebSocketProxyApiCall("RemoteProxy.Hello").toMap();
//qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
// Verify data // Verify data
QVERIFY(!response.isEmpty()); QVERIFY(!response.isEmpty());
@ -423,7 +435,7 @@ void RemoteProxyTestsProxy::getHello()
// TCP // TCP
response.clear(); response.clear();
response = invokeTcpSocketProxyApiCall("RemoteProxy.Hello").toMap(); response = invokeTcpSocketProxyApiCall("RemoteProxy.Hello").toMap();
//qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
// Verify data // Verify data
QVERIFY(!response.isEmpty()); QVERIFY(!response.isEmpty());

View File

@ -122,10 +122,9 @@ void RemoteProxyTestsTunnelProxy::getHello()
{ {
// Start the server // Start the server
startServer(); startServer();
QVariantMap response;
// WebSocket // WebSocket
response = invokeWebSocketTunnelProxyApiCall("RemoteProxy.Hello").toMap(); QVariantMap response = invokeWebSocketTunnelProxyApiCall("RemoteProxy.Hello").toMap();
qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented)); qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
// Verify data // Verify data
@ -147,7 +146,6 @@ void RemoteProxyTestsTunnelProxy::getHello()
QCOMPARE(response.value("params").toMap().value("version").toString(), QString(SERVER_VERSION_STRING)); QCOMPARE(response.value("params").toMap().value("version").toString(), QString(SERVER_VERSION_STRING));
QCOMPARE(response.value("params").toMap().value("apiVersion").toString(), QString(API_VERSION_STRING)); QCOMPARE(response.value("params").toMap().value("apiVersion").toString(), QString(API_VERSION_STRING));
// Clean up // Clean up
stopServer(); stopServer();
} }
@ -250,6 +248,88 @@ void RemoteProxyTestsTunnelProxy::registerServer()
stopServer(); stopServer();
} }
void RemoteProxyTestsTunnelProxy::registerClient_data()
{
QTest::addColumn<QString>("name");
QTest::addColumn<QString>("uuid");
QTest::addColumn<TunnelProxyServer::TunnelProxyError>("expectedError");
QTest::addColumn<bool>("serverExists");
QTest::addColumn<QString>("serverUuid");
QTest::addColumn<TunnelProxyServer::TunnelProxyError>("expectedServerError");
QTest::newRow("valid client: valid server") << "Friendly client" << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorNoError << true << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorNoError;
QTest::newRow("valid client: no server") << "Friendly client" << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorServerNotFound << false << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorNoError;
QTest::newRow("valid client: invalid server uuid") << "Friendly client" << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorInvalidUuid << true << QUuid().toString() << TunnelProxyServer::TunnelProxyErrorInvalidUuid;
QTest::newRow("invalid client uuid: valid server uuid") << "Friendly client" << QUuid().toString() << TunnelProxyServer::TunnelProxyErrorInvalidUuid << true << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorNoError;
QTest::newRow("invalid client uuid: invalid server uuid") << "Friendly client" << "hello again" << TunnelProxyServer::TunnelProxyErrorInvalidUuid << true << "it's me" << TunnelProxyServer::TunnelProxyErrorInvalidUuid;
}
void RemoteProxyTestsTunnelProxy::registerClient()
{
QFETCH(QString, name);
QFETCH(QString, uuid);
QFETCH(TunnelProxyServer::TunnelProxyError, expectedError);
QFETCH(bool, serverExists);
QFETCH(QString, serverUuid);
QFETCH(TunnelProxyServer::TunnelProxyError, expectedServerError);
// Start the server
startServer();
resetDebugCategories();
addDebugCategory("TunnelProxyServer.debug=true");
QSslSocket *socket = nullptr;
if (serverExists) {
QVariantMap serverParams;
serverParams.insert("serverName", "dummy server");
serverParams.insert("serverUuid", serverUuid);
// TCP socket
QPair<QVariant, QSslSocket *> result = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", serverParams);
QVariantMap response = result.first.toMap();
socket = result.second;
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response, expectedServerError);
}
// Register a new client
QVariantMap params;
params.insert("clientName", name);
params.insert("clientUuid", uuid);
params.insert("serverUuid", serverUuid);
// Websocket
QVariantMap response = invokeWebSocketTunnelProxyApiCall("TunnelProxy.RegisterClient", params).toMap();
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response, expectedError);
QTest::qWait(100);
// TCP Socket
response = invokeTcpSocketTunnelProxyApiCall("TunnelProxy.RegisterClient", params).toMap();
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response, expectedError);
QTest::qWait(100);
if (socket) {
// Close the tcp socket
socket->close();
delete socket;
}
// Clean up
stopServer();
}
void RemoteProxyTestsTunnelProxy::registerServerDuplicated() void RemoteProxyTestsTunnelProxy::registerServerDuplicated()
{ {
// Start the server // Start the server
@ -257,6 +337,7 @@ void RemoteProxyTestsTunnelProxy::registerServerDuplicated()
resetDebugCategories(); resetDebugCategories();
addDebugCategory("TunnelProxyServer.debug=true"); addDebugCategory("TunnelProxyServer.debug=true");
addDebugCategory("JsonRpcTraffic.debug=true");
// Register a new server // Register a new server
QString serverName = "tunnel proxy server awesome nymea installation"; QString serverName = "tunnel proxy server awesome nymea installation";
@ -334,5 +415,131 @@ void RemoteProxyTestsTunnelProxy::registerServerDuplicated()
stopServer(); stopServer();
} }
void RemoteProxyTestsTunnelProxy::registerClientDuplicated()
{
// Start the server
startServer();
resetDebugCategories();
addDebugCategory("TunnelProxyServer.debug=true");
addDebugCategory("JsonRpcTraffic.debug=true");
// Create the server and keep it up
QString serverName = "creative server name";
QUuid serverUuid = QUuid::createUuid();
QVariantMap serverParams;
serverParams.insert("serverName", serverName);
serverParams.insert("serverUuid", serverUuid.toString());
// TCP socket
QPair<QVariant, QSslSocket *> serverResult = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", serverParams);
QVariantMap response = serverResult.first.toMap();
QSslSocket *serverSocket = serverResult.second;
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response);
// Connect a client TCP
QString clientName = "creative server name";
QUuid clientUuid = QUuid::createUuid();
QVariantMap clientParams;
clientParams.insert("clientName", serverName);
clientParams.insert("clientUuid", clientUuid.toString());
clientParams.insert("serverUuid", serverUuid.toString());
QPair<QVariant, QSslSocket *> clientResult = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterClient", clientParams);
response = clientResult.first.toMap();
QSslSocket *clientSocketTcp = clientResult.second;
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response);
// Connect another client WebSocket
QPair<QVariant, QSslSocket *> clientResultWS = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterClient", clientParams);
response = clientResultWS.first.toMap();
QSslSocket *clientSocketWs = clientResultWS.second;
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response, TunnelProxyServer::TunnelProxyErrorAlreadyRegistered);
// CleanUp
if (clientSocketTcp) {
// Close the tcp socket
clientSocketTcp->close();
delete clientSocketTcp;
}
if (clientSocketWs) {
// Close the tcp socket
clientSocketWs->close();
delete clientSocketWs;
}
if (serverSocket) {
// Close the tcp socket
serverSocket->close();
delete serverSocket;
}
resetDebugCategories();
// Clean up
stopServer();
}
void RemoteProxyTestsTunnelProxy::crossRegisterServerClient()
{
// Start the server
startServer();
resetDebugCategories();
addDebugCategory("TunnelProxyServer.debug=true");
addDebugCategory("JsonRpcTraffic.debug=true");
// Create the server and keep it up
QString serverName = "creative server name";
QUuid serverUuid = QUuid::createUuid();
QVariantMap serverParams;
serverParams.insert("serverName", serverName);
serverParams.insert("serverUuid", serverUuid.toString());
// TCP socket
QPair<QVariant, QSslSocket *> serverResult = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", serverParams);
QVariantMap response = serverResult.first.toMap();
QSslSocket *serverSocket = serverResult.second;
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response);
// Now try to register as client
QVariantMap clientParams;
clientParams.insert("clientName", "creative client name");
clientParams.insert("clientUuid", QUuid::createUuid().toString());
clientParams.insert("serverUuid", serverUuid.toString());
QPair<QVariant, QSslSocket *> result = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterClient", clientParams, serverSocket);
response = result.first.toMap();
QVERIFY(!response.isEmpty());
QVERIFY(response.value("status").toString() == "success");
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
verifyTunnelProxyError(response, TunnelProxyServer::TunnelProxyErrorAlreadyRegistered);
serverSocket->close();
delete serverSocket;
resetDebugCategories();
// Clean up
stopServer();
}
QTEST_MAIN(RemoteProxyTestsTunnelProxy) QTEST_MAIN(RemoteProxyTestsTunnelProxy)

View File

@ -57,9 +57,14 @@ private slots:
void registerServer_data(); void registerServer_data();
void registerServer(); void registerServer();
void registerServerDuplicated(); void registerClient_data();
void registerClient();
void registerServerDuplicated();
void registerClientDuplicated();
void crossRegisterServerClient();
}; };
#endif // REMOTEPROXYTESTSTUNNELPROXY_H #endif // REMOTEPROXYTESTSTUNNELPROXY_H

View File

@ -87,7 +87,6 @@ void BaseTest::cleanUpEngine()
m_authenticator = nullptr; m_authenticator = nullptr;
if (m_configuration) { if (m_configuration) {
delete m_configuration;
m_configuration = nullptr; m_configuration = nullptr;
} }
} }
@ -132,6 +131,8 @@ void BaseTest::startServer()
QVERIFY(Engine::instance()->tcpSocketServerProxy()->running()); QVERIFY(Engine::instance()->tcpSocketServerProxy()->running());
QVERIFY(Engine::instance()->webSocketServerTunnelProxy()->running()); QVERIFY(Engine::instance()->webSocketServerTunnelProxy()->running());
QVERIFY(Engine::instance()->tcpSocketServerTunnelProxy()->running()); QVERIFY(Engine::instance()->tcpSocketServerTunnelProxy()->running());
QVERIFY(Engine::instance()->proxyServer()->running());
QVERIFY(Engine::instance()->tunnelProxyServer()->running());
QVERIFY(Engine::instance()->monitorServer()->running()); QVERIFY(Engine::instance()->monitorServer()->running());
} }
@ -146,10 +147,8 @@ void BaseTest::stopServer()
cleanUpEngine(); cleanUpEngine();
} }
QVariant BaseTest::invokeWebSocketProxyApiCall(const QString &method, const QVariantMap params, bool remainsConnected) QVariant BaseTest::invokeWebSocketProxyApiCall(const QString &method, const QVariantMap params)
{ {
Q_UNUSED(remainsConnected)
QVariantMap request; QVariantMap request;
request.insert("id", m_commandCounter); request.insert("id", m_commandCounter);
request.insert("method", method); request.insert("method", method);
@ -241,10 +240,8 @@ QVariant BaseTest::injectWebSocketProxyData(const QByteArray &data)
return QVariant(); return QVariant();
} }
QVariant BaseTest::invokeTcpSocketProxyApiCall(const QString &method, const QVariantMap params, bool remainsConnected) QVariant BaseTest::invokeTcpSocketProxyApiCall(const QString &method, const QVariantMap params)
{ {
Q_UNUSED(remainsConnected)
QVariantMap request; QVariantMap request;
request.insert("id", m_commandCounter); request.insert("id", m_commandCounter);
request.insert("method", method); request.insert("method", method);
@ -461,10 +458,8 @@ QVariant BaseTest::injectTcpSocketProxyData(const QByteArray &data)
return jsonDoc.toVariant(); return jsonDoc.toVariant();
} }
QVariant BaseTest::invokeWebSocketTunnelProxyApiCall(const QString &method, const QVariantMap params, bool remainsConnected) QVariant BaseTest::invokeWebSocketTunnelProxyApiCall(const QString &method, const QVariantMap params)
{ {
Q_UNUSED(remainsConnected)
QVariantMap request; QVariantMap request;
request.insert("id", m_commandCounter); request.insert("id", m_commandCounter);
request.insert("method", method); request.insert("method", method);
@ -485,10 +480,8 @@ QVariant BaseTest::invokeWebSocketTunnelProxyApiCall(const QString &method, cons
socket->sendTextMessage(QString(jsonDoc.toJson(QJsonDocument::Compact))); socket->sendTextMessage(QString(jsonDoc.toJson(QJsonDocument::Compact)));
dataSpy.wait(); dataSpy.wait();
if (!remainsConnected) { socket->close();
socket->close(); socket->deleteLater();
socket->deleteLater();
}
for (int i = 0; i < dataSpy.count(); i++) { for (int i = 0; i < dataSpy.count(); i++) {
// Make sure the response ends with '}\n' // Make sure the response ends with '}\n'
@ -559,10 +552,8 @@ QVariant BaseTest::injectWebSocketTunnelProxyData(const QByteArray &data)
return QVariant(); return QVariant();
} }
QVariant BaseTest::invokeTcpSocketTunnelProxyApiCall(const QString &method, const QVariantMap params, bool remainsConnected) QVariant BaseTest::invokeTcpSocketTunnelProxyApiCall(const QString &method, const QVariantMap params)
{ {
Q_UNUSED(remainsConnected)
QVariantMap request; QVariantMap request;
request.insert("id", m_commandCounter); request.insert("id", m_commandCounter);
request.insert("method", method); request.insert("method", method);

View File

@ -85,16 +85,16 @@ protected:
void startServer(); void startServer();
void stopServer(); void stopServer();
QVariant invokeWebSocketProxyApiCall(const QString &method, const QVariantMap params = QVariantMap(), bool remainsConnected = true); QVariant invokeWebSocketProxyApiCall(const QString &method, const QVariantMap params = QVariantMap());
QVariant injectWebSocketProxyData(const QByteArray &data); QVariant injectWebSocketProxyData(const QByteArray &data);
QVariant invokeTcpSocketProxyApiCall(const QString &method, const QVariantMap params = QVariantMap(), bool remainsConnected = true); QVariant invokeTcpSocketProxyApiCall(const QString &method, const QVariantMap params = QVariantMap());
QVariant injectTcpSocketProxyData(const QByteArray &data); QVariant injectTcpSocketProxyData(const QByteArray &data);
QVariant invokeWebSocketTunnelProxyApiCall(const QString &method, const QVariantMap params = QVariantMap(), bool remainsConnected = true); QVariant invokeWebSocketTunnelProxyApiCall(const QString &method, const QVariantMap params = QVariantMap());
QVariant injectWebSocketTunnelProxyData(const QByteArray &data); QVariant injectWebSocketTunnelProxyData(const QByteArray &data);
QVariant invokeTcpSocketTunnelProxyApiCall(const QString &method, const QVariantMap params = QVariantMap(), bool remainsConnected = true); QVariant invokeTcpSocketTunnelProxyApiCall(const QString &method, const QVariantMap params = QVariantMap());
QVariant injectTcpSocketTunnelProxyData(const QByteArray &data); QVariant injectTcpSocketTunnelProxyData(const QByteArray &data);
QPair<QVariant, QSslSocket *> invokeTcpSocketTunnelProxyApiCallPersistant(const QString &method, const QVariantMap params = QVariantMap(), QSslSocket *existingSocket = nullptr); QPair<QVariant, QSslSocket *> invokeTcpSocketTunnelProxyApiCallPersistant(const QString &method, const QVariantMap params = QVariantMap(), QSslSocket *existingSocket = nullptr);