Add server and client registration and prepare client data multiplexing
This commit is contained in:
parent
3174387e96
commit
56d32bed2b
@ -101,7 +101,7 @@ void Engine::start(ProxyConfiguration *configuration)
|
|||||||
|
|
||||||
// Tunnel proxy
|
// Tunnel proxy
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
m_tunnelProxyManager = new TunnelProxyManager(this);
|
m_tunnelProxyServer = new TunnelProxyServer(this);
|
||||||
m_webSocketServerTunnelProxy = new WebSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
|
m_webSocketServerTunnelProxy = new WebSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
|
||||||
m_tcpSocketServerTunnelProxy = new TcpSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
|
m_tcpSocketServerTunnelProxy = new TcpSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
|
||||||
|
|
||||||
@ -120,12 +120,12 @@ void Engine::start(ProxyConfiguration *configuration)
|
|||||||
m_tcpSocketServerTunnelProxy->setServerUrl(tcpSocketServerTunnelProxyUrl);
|
m_tcpSocketServerTunnelProxy->setServerUrl(tcpSocketServerTunnelProxyUrl);
|
||||||
|
|
||||||
// Register the transport interfaces in the proxy server
|
// Register the transport interfaces in the proxy server
|
||||||
m_tunnelProxyManager->registerTransportInterface(m_webSocketServerTunnelProxy);
|
m_tunnelProxyServer->registerTransportInterface(m_webSocketServerTunnelProxy);
|
||||||
m_tunnelProxyManager->registerTransportInterface(m_tcpSocketServerTunnelProxy);
|
m_tunnelProxyServer->registerTransportInterface(m_tcpSocketServerTunnelProxy);
|
||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
qCDebug(dcEngine()) << "Starting the tunnel proxy manager...";
|
qCDebug(dcEngine()) << "Starting the tunnel proxy manager...";
|
||||||
m_tunnelProxyManager->startServer();
|
m_tunnelProxyServer->startServer();
|
||||||
|
|
||||||
// Start the monitor server
|
// Start the monitor server
|
||||||
m_monitorServer = new MonitorServer(configuration->monitorSocketFileName(), this);
|
m_monitorServer = new MonitorServer(configuration->monitorSocketFileName(), this);
|
||||||
@ -195,9 +195,9 @@ ProxyServer *Engine::proxyServer() const
|
|||||||
return m_proxyServer;
|
return m_proxyServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelProxyManager *Engine::tunnelProxyManager() const
|
TunnelProxyServer *Engine::tunnelProxyServer() const
|
||||||
{
|
{
|
||||||
return m_tunnelProxyManager;
|
return m_tunnelProxyServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
TcpSocketServer *Engine::tcpSocketServerProxy() const
|
TcpSocketServer *Engine::tcpSocketServerProxy() const
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
#include "server/tcpsocketserver.h"
|
#include "server/tcpsocketserver.h"
|
||||||
#include "server/websocketserver.h"
|
#include "server/websocketserver.h"
|
||||||
#include "authentication/authenticator.h"
|
#include "authentication/authenticator.h"
|
||||||
#include "tunnelproxy/tunnelproxymanager.h"
|
#include "tunnelproxy/tunnelproxyserver.h"
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public:
|
|||||||
Authenticator *authenticator() const;
|
Authenticator *authenticator() const;
|
||||||
|
|
||||||
ProxyServer *proxyServer() const;
|
ProxyServer *proxyServer() const;
|
||||||
TunnelProxyManager *tunnelProxyManager() const;
|
TunnelProxyServer *tunnelProxyServer() const;
|
||||||
|
|
||||||
TcpSocketServer *tcpSocketServerProxy() const;
|
TcpSocketServer *tcpSocketServerProxy() const;
|
||||||
WebSocketServer *webSocketServerProxy() const;
|
WebSocketServer *webSocketServerProxy() const;
|
||||||
@ -101,7 +101,7 @@ private:
|
|||||||
Authenticator *m_authenticator = nullptr;
|
Authenticator *m_authenticator = nullptr;
|
||||||
|
|
||||||
ProxyServer *m_proxyServer = nullptr;
|
ProxyServer *m_proxyServer = nullptr;
|
||||||
TunnelProxyManager *m_tunnelProxyManager = nullptr;
|
TunnelProxyServer *m_tunnelProxyServer = nullptr;
|
||||||
|
|
||||||
TcpSocketServer *m_tcpSocketServerProxy = nullptr;
|
TcpSocketServer *m_tcpSocketServerProxy = nullptr;
|
||||||
WebSocketServer *m_webSocketServerProxy = nullptr;
|
WebSocketServer *m_webSocketServerProxy = nullptr;
|
||||||
|
|||||||
@ -63,7 +63,7 @@ QString AuthenticationHandler::name() const
|
|||||||
|
|
||||||
JsonReply *AuthenticationHandler::Authenticate(const QVariantMap ¶ms, TransportClient *transportClient)
|
JsonReply *AuthenticationHandler::Authenticate(const QVariantMap ¶ms, TransportClient *transportClient)
|
||||||
{
|
{
|
||||||
QString uuid = params.value("uuid").toString();
|
QUuid uuid = params.value("uuid").toUuid();
|
||||||
QString name = params.value("name").toString();
|
QString name = params.value("name").toString();
|
||||||
QString token = params.value("token").toString();
|
QString token = params.value("token").toString();
|
||||||
QString nonce = params.value("nonce").toString();
|
QString nonce = params.value("nonce").toString();
|
||||||
|
|||||||
@ -62,7 +62,7 @@ void JsonTypes::init()
|
|||||||
// Declare types
|
// Declare types
|
||||||
s_basicType = enumToStrings(JsonTypes::staticMetaObject, "BasicType");
|
s_basicType = enumToStrings(JsonTypes::staticMetaObject, "BasicType");
|
||||||
s_authenticationError = enumToStrings(Authenticator::staticMetaObject, "AuthenticationError");
|
s_authenticationError = enumToStrings(Authenticator::staticMetaObject, "AuthenticationError");
|
||||||
s_tunnelProxyError = enumToStrings(TunnelProxyManager::staticMetaObject, "Error");
|
s_tunnelProxyError = enumToStrings(TunnelProxyServer::staticMetaObject, "TunnelProxyError");
|
||||||
|
|
||||||
s_initialized = true;
|
s_initialized = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include "tunnelproxy/tunnelproxymanager.h"
|
#include "tunnelproxy/tunnelproxyserver.h"
|
||||||
#include "authentication/authenticator.h"
|
#include "authentication/authenticator.h"
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
// Declare types
|
// Declare types
|
||||||
DECLARE_TYPE(basicType, "BasicType", JsonTypes, BasicType)
|
DECLARE_TYPE(basicType, "BasicType", JsonTypes, BasicType)
|
||||||
DECLARE_TYPE(authenticationError, "AuthenticationError", Authenticator, AuthenticationError)
|
DECLARE_TYPE(authenticationError, "AuthenticationError", Authenticator, AuthenticationError)
|
||||||
DECLARE_TYPE(tunnelProxyError, "TunnelProxyError", TunnelProxyManager, Error)
|
DECLARE_TYPE(tunnelProxyError, "TunnelProxyError", TunnelProxyServer, TunnelProxyError)
|
||||||
|
|
||||||
// Declare objects
|
// Declare objects
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
#include "jsontypes.h"
|
#include "jsontypes.h"
|
||||||
#include "loggingcategories.h"
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
#include "tunnelproxy/tunnelproxymanager.h"
|
#include "tunnelproxy/tunnelproxyserver.h"
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
@ -42,12 +42,38 @@ TunnelProxyHandler::TunnelProxyHandler(QObject *parent) : JsonHandler(parent)
|
|||||||
|
|
||||||
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("uuid", JsonTypes::basicTypeToString(JsonTypes::String));
|
params.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||||
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String));
|
params.insert("serverUuid", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||||
setParams("RegisterServer", params);
|
setParams("RegisterServer", params);
|
||||||
returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef());
|
returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef());
|
||||||
setReturns("RegisterServer", returns);
|
setReturns("RegisterServer", returns);
|
||||||
|
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
setDescription("RegisterClient", "Register a new TunnelProxy client on TunnelProxy server with the given serverUuid..");
|
||||||
|
params.insert("clientName", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||||
|
params.insert("clientUuid", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||||
|
params.insert("serverUuid", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||||
|
setParams("RegisterClient", params);
|
||||||
|
returns.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorRef());
|
||||||
|
setReturns("RegisterClient", returns);
|
||||||
|
|
||||||
|
// Notifications
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
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.");
|
||||||
|
params.insert("clientId", JsonTypes::basicTypeToString(JsonTypes::UInt));
|
||||||
|
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||||
|
params.insert("address", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||||
|
setParams("ClientConnected", params);
|
||||||
|
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
setDescription("ClientDisconnected", "Emitted whenever a new client has been connected to a registered server. "
|
||||||
|
"Only tunnel proxy clients registered as server will receive this notification.");
|
||||||
|
params.insert("clientId", JsonTypes::basicTypeToString(JsonTypes::UInt));
|
||||||
|
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||||
|
params.insert("address", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||||
|
setParams("ClientDisconnected", params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TunnelProxyHandler::name() const
|
QString TunnelProxyHandler::name() const
|
||||||
@ -58,14 +84,46 @@ QString TunnelProxyHandler::name() const
|
|||||||
JsonReply *TunnelProxyHandler::RegisterServer(const QVariantMap ¶ms, TransportClient *transportClient)
|
JsonReply *TunnelProxyHandler::RegisterServer(const QVariantMap ¶ms, TransportClient *transportClient)
|
||||||
{
|
{
|
||||||
qCDebug(dcJsonRpc()) << name() << "register server" << params << transportClient;
|
qCDebug(dcJsonRpc()) << name() << "register server" << params << transportClient;
|
||||||
QUuid serverUuid = params.value("uuid").toUuid();
|
QUuid serverUuid = params.value("serverUuid").toUuid();
|
||||||
QString serverName = params.value("name").toString();
|
TunnelProxyServer::TunnelProxyError error = TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
if (serverUuid.isNull()) {
|
||||||
TunnelProxyManager::Error error = Engine::instance()->tunnelProxyManager()->registerServer(transportClient->clientId(), serverUuid, serverName);
|
qCWarning(dcJsonRpc()) << "Invalid uuid received" << params.value("serverUuid").toString() << serverUuid;
|
||||||
|
error = TunnelProxyServer::TunnelProxyErrorInvalidUuid;
|
||||||
|
} else {
|
||||||
|
QString serverName = params.value("serverName").toString();
|
||||||
|
error = Engine::instance()->tunnelProxyServer()->registerServer(transportClient->clientId(), serverUuid, serverName);
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap response;
|
QVariantMap response;
|
||||||
response.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorToString(error));
|
response.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorToString(error));
|
||||||
return createReply("RegisterServer", response);
|
return createReply("RegisterServer", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonReply *TunnelProxyHandler::RegisterClient(const QVariantMap ¶ms, TransportClient *transportClient)
|
||||||
|
{
|
||||||
|
qCDebug(dcJsonRpc()) << name() << "register client" << params << transportClient;
|
||||||
|
QString clientName = params.value("clientName").toString();
|
||||||
|
QUuid clientUuid = params.value("clientUuid").toUuid();
|
||||||
|
QUuid serverUuid = params.value("serverUuid").toUuid();
|
||||||
|
TunnelProxyServer::TunnelProxyError error = TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
if (serverUuid.isNull()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Invalid server uuid received" << params.value("serverUuid").toString() << serverUuid;
|
||||||
|
error = TunnelProxyServer::TunnelProxyErrorInvalidUuid;
|
||||||
|
} else if (clientUuid.isNull()) {
|
||||||
|
qCWarning(dcJsonRpc()) << "Invalid client uuid received" << params.value("clientUuid").toString() << clientUuid;
|
||||||
|
error = TunnelProxyServer::TunnelProxyErrorInvalidUuid;
|
||||||
|
} else {
|
||||||
|
error = Engine::instance()->tunnelProxyServer()->registerClient(transportClient->clientId(), clientUuid, clientName, serverUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap response;
|
||||||
|
response.insert("tunnelProxyError", JsonTypes::tunnelProxyErrorToString(error));
|
||||||
|
return createReply("RegisterServer", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
//JsonReply *TunnelProxyHandler::RemoveClient(const QVariantMap ¶ms, TransportClient *transportClient)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,9 +46,13 @@ public:
|
|||||||
QString name() const override;
|
QString name() const override;
|
||||||
|
|
||||||
Q_INVOKABLE JsonReply *RegisterServer(const QVariantMap ¶ms, TransportClient *transportClient);
|
Q_INVOKABLE JsonReply *RegisterServer(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
Q_INVOKABLE JsonReply *RegisterClient(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
|
||||||
|
// Q_INVOKABLE JsonReply *RemoveClient(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void ClientConnected(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
void ClientDisconnected(const QVariantMap ¶ms, TransportClient *transportClient);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -30,8 +30,9 @@ HEADERS += \
|
|||||||
server/jsonrpcserver.h \
|
server/jsonrpcserver.h \
|
||||||
server/transportclient.h \
|
server/transportclient.h \
|
||||||
server/monitorserver.h \
|
server/monitorserver.h \
|
||||||
|
tunnelproxy/tunnelproxyclient.h \
|
||||||
tunnelproxy/tunnelproxyclientconnection.h \
|
tunnelproxy/tunnelproxyclientconnection.h \
|
||||||
tunnelproxy/tunnelproxymanager.h \
|
tunnelproxy/tunnelproxyserver.h \
|
||||||
tunnelproxy/tunnelproxyserverconnection.h
|
tunnelproxy/tunnelproxyserverconnection.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -61,8 +62,9 @@ SOURCES += \
|
|||||||
server/websocketserver.cpp \
|
server/websocketserver.cpp \
|
||||||
server/jsonrpcserver.cpp \
|
server/jsonrpcserver.cpp \
|
||||||
server/monitorserver.cpp \
|
server/monitorserver.cpp \
|
||||||
|
tunnelproxy/tunnelproxyclient.cpp \
|
||||||
tunnelproxy/tunnelproxyclientconnection.cpp \
|
tunnelproxy/tunnelproxyclientconnection.cpp \
|
||||||
tunnelproxy/tunnelproxymanager.cpp \
|
tunnelproxy/tunnelproxyserver.cpp \
|
||||||
tunnelproxy/tunnelproxyserverconnection.cpp
|
tunnelproxy/tunnelproxyserverconnection.cpp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -39,9 +39,8 @@ Q_LOGGING_CATEGORY(dcWebSocketServerTraffic, "WebSocketServerTraffic")
|
|||||||
Q_LOGGING_CATEGORY(dcAuthentication, "Authentication")
|
Q_LOGGING_CATEGORY(dcAuthentication, "Authentication")
|
||||||
Q_LOGGING_CATEGORY(dcAuthenticationProcess, "AuthenticationProcess")
|
Q_LOGGING_CATEGORY(dcAuthenticationProcess, "AuthenticationProcess")
|
||||||
Q_LOGGING_CATEGORY(dcProxyServer, "ProxyServer")
|
Q_LOGGING_CATEGORY(dcProxyServer, "ProxyServer")
|
||||||
Q_LOGGING_CATEGORY(dcTunnelProxyManager, "TunnelProxyManager")
|
|
||||||
Q_LOGGING_CATEGORY(dcProxyTunnelClient, "ProxyTunnelClient")
|
|
||||||
Q_LOGGING_CATEGORY(dcTunnelProxyServer, "TunnelProxyServer")
|
Q_LOGGING_CATEGORY(dcTunnelProxyServer, "TunnelProxyServer")
|
||||||
|
Q_LOGGING_CATEGORY(dcTunnelProxyServerTraffic, "TunnelProxyServerTraffic")
|
||||||
Q_LOGGING_CATEGORY(dcProxyServerTraffic, "ProxyServerTraffic")
|
Q_LOGGING_CATEGORY(dcProxyServerTraffic, "ProxyServerTraffic")
|
||||||
Q_LOGGING_CATEGORY(dcMonitorServer, "MonitorServer")
|
Q_LOGGING_CATEGORY(dcMonitorServer, "MonitorServer")
|
||||||
Q_LOGGING_CATEGORY(dcAwsCredentialsProvider, "AwsCredentialsProvider")
|
Q_LOGGING_CATEGORY(dcAwsCredentialsProvider, "AwsCredentialsProvider")
|
||||||
|
|||||||
@ -43,10 +43,9 @@ Q_DECLARE_LOGGING_CATEGORY(dcTcpSocketServerTraffic)
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(dcAuthentication)
|
Q_DECLARE_LOGGING_CATEGORY(dcAuthentication)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcAuthenticationProcess)
|
Q_DECLARE_LOGGING_CATEGORY(dcAuthenticationProcess)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcProxyServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcProxyServer)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcTunnelProxyManager)
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcProxyTunnelClient)
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcTunnelProxyServer)
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcProxyServerTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcProxyServerTraffic)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcTunnelProxyServer)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcTunnelProxyServerTraffic)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcMonitorServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcMonitorServer)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcAwsCredentialsProvider)
|
Q_DECLARE_LOGGING_CATEGORY(dcAwsCredentialsProvider)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcAwsCredentialsProviderTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcAwsCredentialsProviderTraffic)
|
||||||
|
|||||||
@ -81,26 +81,6 @@ void ProxyClient::setUserName(const QString &userName)
|
|||||||
m_userName = userName;
|
m_userName = userName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ProxyClient::uuid() const
|
|
||||||
{
|
|
||||||
return m_uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyClient::setUuid(const QString &uuid)
|
|
||||||
{
|
|
||||||
m_uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ProxyClient::name() const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyClient::setName(const QString &name)
|
|
||||||
{
|
|
||||||
m_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ProxyClient::tunnelIdentifier() const
|
QString ProxyClient::tunnelIdentifier() const
|
||||||
{
|
{
|
||||||
return m_token + m_nonce;
|
return m_token + m_nonce;
|
||||||
|
|||||||
@ -60,13 +60,6 @@ public:
|
|||||||
QString userName() const;
|
QString userName() const;
|
||||||
void setUserName(const QString &userName);
|
void setUserName(const QString &userName);
|
||||||
|
|
||||||
// Properties from auth request
|
|
||||||
QString uuid() const;
|
|
||||||
void setUuid(const QString &uuid);
|
|
||||||
|
|
||||||
QString name() const;
|
|
||||||
void setName(const QString &name);
|
|
||||||
|
|
||||||
QString tunnelIdentifier() const;
|
QString tunnelIdentifier() const;
|
||||||
|
|
||||||
QString token() const;
|
QString token() const;
|
||||||
@ -89,8 +82,6 @@ private:
|
|||||||
bool m_authenticated = false;
|
bool m_authenticated = false;
|
||||||
bool m_tunnelConnected = false;
|
bool m_tunnelConnected = false;
|
||||||
|
|
||||||
QString m_uuid;
|
|
||||||
QString m_name;
|
|
||||||
QString m_token;
|
QString m_token;
|
||||||
QString m_nonce;
|
QString m_nonce;
|
||||||
|
|
||||||
|
|||||||
@ -306,6 +306,7 @@ void JsonRpcServer::unregisterClient(TransportClient *transportClient)
|
|||||||
qCWarning(dcJsonRpc()) << "Client was not registered" << transportClient;
|
qCWarning(dcJsonRpc()) << "Client was not registered" << transportClient;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clients.removeAll(transportClient);
|
m_clients.removeAll(transportClient);
|
||||||
|
|
||||||
if (m_asyncReplies.values().contains(transportClient)) {
|
if (m_asyncReplies.values().contains(transportClient)) {
|
||||||
|
|||||||
@ -66,6 +66,26 @@ TransportInterface *TransportClient::interface() const
|
|||||||
return m_interface;
|
return m_interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUuid TransportClient::uuid() const
|
||||||
|
{
|
||||||
|
return m_uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransportClient::setUuid(const QUuid &uuid)
|
||||||
|
{
|
||||||
|
m_uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransportClient::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransportClient::setName(const QString &name)
|
||||||
|
{
|
||||||
|
m_name = name;
|
||||||
|
}
|
||||||
|
|
||||||
quint64 TransportClient::rxDataCount() const
|
quint64 TransportClient::rxDataCount() const
|
||||||
{
|
{
|
||||||
return m_rxDataCount;
|
return m_rxDataCount;
|
||||||
|
|||||||
@ -52,6 +52,13 @@ public:
|
|||||||
|
|
||||||
TransportInterface *interface() const;
|
TransportInterface *interface() const;
|
||||||
|
|
||||||
|
// Properties from auth request
|
||||||
|
QUuid uuid() const;
|
||||||
|
void setUuid(const QUuid &uuid);
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
void setName(const QString &name);
|
||||||
|
|
||||||
quint64 rxDataCount() const;
|
quint64 rxDataCount() const;
|
||||||
void addRxDataCount(int dataCount);
|
void addRxDataCount(int dataCount);
|
||||||
|
|
||||||
@ -74,6 +81,10 @@ protected:
|
|||||||
QHostAddress m_peerAddress;
|
QHostAddress m_peerAddress;
|
||||||
uint m_creationTimeStamp = 0;
|
uint m_creationTimeStamp = 0;
|
||||||
|
|
||||||
|
// Eveyone has to register him self everywhere with a name and a uuid
|
||||||
|
QString m_name;
|
||||||
|
QUuid m_uuid;
|
||||||
|
|
||||||
QByteArray m_dataBuffers;
|
QByteArray m_dataBuffers;
|
||||||
|
|
||||||
// Json data information
|
// Json data information
|
||||||
|
|||||||
62
libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp
Normal file
62
libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include "tunnelproxyclient.h"
|
||||||
|
#include "server/transportinterface.h"
|
||||||
|
|
||||||
|
namespace remoteproxy {
|
||||||
|
|
||||||
|
TunnelProxyClient::TunnelProxyClient(TransportInterface *interface, const QUuid &clientId, const QHostAddress &address, QObject *parent) :
|
||||||
|
TransportClient(interface, clientId, address, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelProxyClient::Type TunnelProxyClient::type() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyClient::setType(Type type)
|
||||||
|
{
|
||||||
|
if (m_type == type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_type = type;
|
||||||
|
emit typeChanged(m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QByteArray> TunnelProxyClient::processData(const QByteArray &data)
|
||||||
|
{
|
||||||
|
// TODO: unescape if this data is for the json handler
|
||||||
|
QList<QByteArray> packages;
|
||||||
|
|
||||||
|
// Handle packet fragmentation
|
||||||
|
m_dataBuffers.append(data);
|
||||||
|
int splitIndex = m_dataBuffers.indexOf("}\n{");
|
||||||
|
while (splitIndex > -1) {
|
||||||
|
packages.append(m_dataBuffers.left(splitIndex + 1));
|
||||||
|
m_dataBuffers = m_dataBuffers.right(m_dataBuffers.length() - splitIndex - 2);
|
||||||
|
splitIndex = m_dataBuffers.indexOf("}\n{");
|
||||||
|
}
|
||||||
|
if (m_dataBuffers.trimmed().endsWith("}")) {
|
||||||
|
packages.append(m_dataBuffers);
|
||||||
|
m_dataBuffers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, TunnelProxyClient *tunnelProxyClient)
|
||||||
|
{
|
||||||
|
debug.nospace() << "TunnelProxyClient(";
|
||||||
|
if (!tunnelProxyClient->name().isEmpty()) {
|
||||||
|
debug.nospace() << tunnelProxyClient->name() << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.nospace() << tunnelProxyClient->interface()->serverName();
|
||||||
|
debug.nospace() << ", " << tunnelProxyClient->clientId().toString();
|
||||||
|
debug.nospace() << ", " << tunnelProxyClient->peerAddress().toString();
|
||||||
|
debug.nospace() << ", " << tunnelProxyClient->creationTimeString() << ")";
|
||||||
|
return debug.space();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.h
Normal file
41
libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef TUNNELPROXYCLIENT_H
|
||||||
|
#define TUNNELPROXYCLIENT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "server/transportclient.h"
|
||||||
|
|
||||||
|
namespace remoteproxy {
|
||||||
|
|
||||||
|
class TunnelProxyClient : public TransportClient
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
TypeNone,
|
||||||
|
TypeServer,
|
||||||
|
TypeClient
|
||||||
|
};
|
||||||
|
Q_ENUM(Type)
|
||||||
|
|
||||||
|
explicit TunnelProxyClient(TransportInterface *interface, const QUuid &clientId, const QHostAddress &address, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Type type() const;
|
||||||
|
void setType(Type type);
|
||||||
|
|
||||||
|
// Json server methods
|
||||||
|
QList<QByteArray> processData(const QByteArray &data) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void typeChanged(Type type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type m_type = TypeNone;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<< (QDebug debug, TunnelProxyClient *tunnelProxyClient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TUNNELPROXYCLIENT_H
|
||||||
@ -26,12 +26,38 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "tunnelproxyclientconnection.h"
|
#include "tunnelproxyclientconnection.h"
|
||||||
|
#include "server/transportclient.h"
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
TunnelProxyClientConnection::TunnelProxyClientConnection(QObject *parent) : QObject(parent)
|
TunnelProxyClientConnection::TunnelProxyClientConnection(TransportClient *transportClient, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_transportClient(transportClient),
|
||||||
|
m_clientUuid(clientUuid),
|
||||||
|
m_clientName(clientName),
|
||||||
|
m_serverUuid(serverUuid)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransportClient *TunnelProxyClientConnection::transportClient() const
|
||||||
|
{
|
||||||
|
return m_transportClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid TunnelProxyClientConnection::clientUuid() const
|
||||||
|
{
|
||||||
|
return m_clientUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TunnelProxyClientConnection::clientName() const
|
||||||
|
{
|
||||||
|
return m_clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid TunnelProxyClientConnection::serverUuid() const
|
||||||
|
{
|
||||||
|
return m_serverUuid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,18 +28,34 @@
|
|||||||
#ifndef TUNNELPROXYCLIENTCONNECTION_H
|
#ifndef TUNNELPROXYCLIENTCONNECTION_H
|
||||||
#define TUNNELPROXYCLIENTCONNECTION_H
|
#define TUNNELPROXYCLIENTCONNECTION_H
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
|
class TransportClient;
|
||||||
|
|
||||||
class TunnelProxyClientConnection : public QObject
|
class TunnelProxyClientConnection : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit TunnelProxyClientConnection(QObject *parent = nullptr);
|
explicit TunnelProxyClientConnection(TransportClient *transportClient, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
TransportClient *transportClient() const;
|
||||||
|
|
||||||
|
QUuid clientUuid() const;
|
||||||
|
QString clientName() const;
|
||||||
|
QUuid serverUuid() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
private:
|
||||||
|
TransportClient *m_transportClient = nullptr;
|
||||||
|
|
||||||
|
QUuid m_clientUuid;
|
||||||
|
QString m_clientName;
|
||||||
|
QUuid m_serverUuid;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,163 +0,0 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
*
|
|
||||||
* 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 General Public License Usage
|
|
||||||
* Alternatively, this project may be redistributed and/or modified under
|
|
||||||
* the terms of the GNU General Public License as published by the Free Software Foundation,
|
|
||||||
* GNU 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU 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 "tunnelproxymanager.h"
|
|
||||||
#include "loggingcategories.h"
|
|
||||||
|
|
||||||
#include "jsonrpc/tunnelproxyhandler.h"
|
|
||||||
|
|
||||||
namespace remoteproxy {
|
|
||||||
|
|
||||||
TunnelProxyManager::TunnelProxyManager(QObject *parent) :
|
|
||||||
QObject(parent)
|
|
||||||
{
|
|
||||||
m_jsonRpcServer = new JsonRpcServer(this);
|
|
||||||
m_jsonRpcServer->registerHandler(m_jsonRpcServer);
|
|
||||||
m_jsonRpcServer->registerHandler(new TunnelProxyHandler(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
TunnelProxyManager::~TunnelProxyManager()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TunnelProxyManager::running() const
|
|
||||||
{
|
|
||||||
return m_running;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::setRunning(bool running)
|
|
||||||
{
|
|
||||||
if (m_running == running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
qCDebug(dcTunnelProxyManager()) << "The proxy tunnel manager is" << (running ? "now up and running." : "not running any more.");
|
|
||||||
m_running = running;
|
|
||||||
emit runningChanged(m_running);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::registerTransportInterface(TransportInterface *interface)
|
|
||||||
{
|
|
||||||
qCDebug(dcTunnelProxyManager()) << "Register transport interface" << interface->serverName();
|
|
||||||
|
|
||||||
if (m_transportInterfaces.contains(interface)) {
|
|
||||||
qCWarning(dcTunnelProxyManager()) << "Transport interface already registerd.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(interface, &TransportInterface::clientConnected, this, &TunnelProxyManager::onClientConnected);
|
|
||||||
connect(interface, &TransportInterface::clientDisconnected, this, &TunnelProxyManager::onClientDisconnected);
|
|
||||||
connect(interface, &TransportInterface::dataAvailable, this, &TunnelProxyManager::onClientDataAvailable);
|
|
||||||
|
|
||||||
m_transportInterfaces.append(interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
TunnelProxyManager::Error TunnelProxyManager::registerServer(const QUuid &clientId, const QUuid &serverUuid, const QString &serverName)
|
|
||||||
{
|
|
||||||
qCDebug(dcTunnelProxyManager()) << "Register new server" << m_proxyClients.value(clientId) << serverName << serverUuid.toString();
|
|
||||||
|
|
||||||
// TODO: check if uuid already exists
|
|
||||||
|
|
||||||
// Check if requested already as client
|
|
||||||
|
|
||||||
|
|
||||||
TunnelProxyServerConnection *proxyServer = new TunnelProxyServerConnection(m_proxyClients.value(clientId), serverUuid, serverName);
|
|
||||||
m_proxyClientsTunnelServer.insert(clientId, proxyServer);
|
|
||||||
m_tunnelServers.insert(proxyServer->serverUuid(), proxyServer);
|
|
||||||
|
|
||||||
return ErrorNoError;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::startServer()
|
|
||||||
{
|
|
||||||
qCDebug(dcTunnelProxyManager()) << "Starting tunnel proxy...";
|
|
||||||
foreach (TransportInterface *interface, m_transportInterfaces) {
|
|
||||||
interface->startServer();
|
|
||||||
}
|
|
||||||
setRunning(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::stopServer()
|
|
||||||
{
|
|
||||||
qCDebug(dcTunnelProxyManager()) << "Stopping tunnel proxy...";
|
|
||||||
foreach (TransportInterface *interface, m_transportInterfaces) {
|
|
||||||
interface->stopServer();
|
|
||||||
}
|
|
||||||
setRunning(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::tick()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::onClientConnected(const QUuid &clientId, const QHostAddress &address)
|
|
||||||
{
|
|
||||||
TransportInterface *interface = static_cast<TransportInterface *>(sender());
|
|
||||||
|
|
||||||
qCDebug(dcTunnelProxyManager()) << "New client connected" << interface->serverName() << clientId.toString() << address.toString();
|
|
||||||
|
|
||||||
ProxyClient *proxyClient = new ProxyClient(interface, clientId, address, this);
|
|
||||||
|
|
||||||
m_proxyClients.insert(clientId, proxyClient);
|
|
||||||
m_jsonRpcServer->registerClient(proxyClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::onClientDisconnected(const QUuid &clientId)
|
|
||||||
{
|
|
||||||
TransportInterface *interface = static_cast<TransportInterface *>(sender());
|
|
||||||
qCDebug(dcProxyServer()) << "Client disconnected" << interface->serverName() << clientId.toString();
|
|
||||||
|
|
||||||
if (!m_proxyClients.contains(clientId)) {
|
|
||||||
qCWarning(dcProxyServer()) << "Unknown client disconnected from proxy server." << clientId.toString();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ProxyClient *proxyClient = m_proxyClients.take(clientId);
|
|
||||||
|
|
||||||
// Unregister from json rpc server
|
|
||||||
m_jsonRpcServer->unregisterClient(proxyClient);
|
|
||||||
|
|
||||||
// Delete the proxy client
|
|
||||||
proxyClient->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TunnelProxyManager::onClientDataAvailable(const QUuid &clientId, const QByteArray &data)
|
|
||||||
{
|
|
||||||
Q_UNUSED(clientId)
|
|
||||||
Q_UNUSED(data)
|
|
||||||
|
|
||||||
ProxyClient *proxyClient = m_proxyClients.value(clientId);
|
|
||||||
if (!proxyClient) {
|
|
||||||
qCWarning(dcProxyServer()) << "Could not find client for uuid" << clientId;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(dcProxyServerTraffic()) << "Client data available" << proxyClient << qUtf8Printable(data);
|
|
||||||
m_jsonRpcServer->processData(proxyClient, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
238
libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp
Normal file
238
libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under
|
||||||
|
* the terms of the GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU 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 "loggingcategories.h"
|
||||||
|
|
||||||
|
#include "jsonrpc/tunnelproxyhandler.h"
|
||||||
|
#include "tunnelproxyserverconnection.h"
|
||||||
|
#include "tunnelproxyclientconnection.h"
|
||||||
|
|
||||||
|
namespace remoteproxy {
|
||||||
|
|
||||||
|
TunnelProxyServer::TunnelProxyServer(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
m_jsonRpcServer = new JsonRpcServer(this);
|
||||||
|
m_jsonRpcServer->registerHandler(m_jsonRpcServer);
|
||||||
|
m_jsonRpcServer->registerHandler(new TunnelProxyHandler(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelProxyServer::~TunnelProxyServer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TunnelProxyServer::running() const
|
||||||
|
{
|
||||||
|
return m_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::setRunning(bool running)
|
||||||
|
{
|
||||||
|
if (m_running == running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "The proxy tunnel manager is" << (running ? "now up and running." : "not running any more.");
|
||||||
|
m_running = running;
|
||||||
|
emit runningChanged(m_running);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::registerTransportInterface(TransportInterface *interface)
|
||||||
|
{
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "Register transport interface" << interface->serverName();
|
||||||
|
|
||||||
|
if (m_transportInterfaces.contains(interface)) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Transport interface already registerd.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(interface, &TransportInterface::clientConnected, this, &TunnelProxyServer::onClientConnected);
|
||||||
|
connect(interface, &TransportInterface::clientDisconnected, this, &TunnelProxyServer::onClientDisconnected);
|
||||||
|
connect(interface, &TransportInterface::dataAvailable, this, &TunnelProxyServer::onClientDataAvailable);
|
||||||
|
|
||||||
|
m_transportInterfaces.append(interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerServer(const QUuid &clientId, const QUuid &serverUuid, const QString &serverName)
|
||||||
|
{
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "Register new server" << m_proxyClients.value(clientId) << serverName << serverUuid.toString();
|
||||||
|
|
||||||
|
// Check if requested already as client
|
||||||
|
TunnelProxyClient *tunnelProxyClient = m_proxyClients.value(clientId);
|
||||||
|
if (!tunnelProxyClient) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "There is no client with client uuid" << clientId.toString();
|
||||||
|
return TunnelProxyServer::TunnelProxyErrorInternalServerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure this client has not been registered as client or re-registration has been called...
|
||||||
|
if (tunnelProxyClient->type() != TunnelProxyClient::TypeNone) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Client tried to register as server but has already been registerd as" << tunnelProxyClient->type();
|
||||||
|
return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered;
|
||||||
|
}
|
||||||
|
|
||||||
|
tunnelProxyClient->setType(TunnelProxyClient::TypeServer);
|
||||||
|
tunnelProxyClient->setUuid(serverUuid);
|
||||||
|
tunnelProxyClient->setName(serverName);
|
||||||
|
|
||||||
|
TunnelProxyServerConnection *serverConnection = new TunnelProxyServerConnection(tunnelProxyClient, serverUuid, serverName, this);
|
||||||
|
m_tunnelProxyServerConnections.insert(serverUuid, serverConnection);
|
||||||
|
|
||||||
|
return TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerClient(const QUuid &clientId, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid)
|
||||||
|
{
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "Register new client" << m_proxyClients.value(clientId) << clientName << clientUuid.toString() << "--> server" << serverUuid.toString();
|
||||||
|
|
||||||
|
TunnelProxyClient *tunnelProxyClient = m_proxyClients.value(clientId);
|
||||||
|
if (!tunnelProxyClient) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "There is no client with client uuid" << clientId.toString();
|
||||||
|
return TunnelProxyServer::TunnelProxyErrorInternalServerError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure this client has not been registered as client or re-registration has been called...
|
||||||
|
if (tunnelProxyClient->type() != TunnelProxyClient::TypeNone) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Client tried to register as client but has already been registerd as" << tunnelProxyClient->type();
|
||||||
|
return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the desired server connection
|
||||||
|
TunnelProxyServerConnection *serverConnection = m_tunnelProxyServerConnections.value(serverUuid);
|
||||||
|
if (!serverConnection) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "There is no server registered with server uuid" << serverUuid.toString();
|
||||||
|
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
|
||||||
|
tunnelProxyClient->setType(TunnelProxyClient::TypeClient);
|
||||||
|
tunnelProxyClient->setUuid(clientUuid);
|
||||||
|
tunnelProxyClient->setName(clientName);
|
||||||
|
|
||||||
|
TunnelProxyClientConnection *clientConnection = new TunnelProxyClientConnection(tunnelProxyClient, clientUuid, clientName, serverUuid);
|
||||||
|
m_tunnelProxyClientConnections.insert(clientUuid, clientConnection);
|
||||||
|
|
||||||
|
// TODO: register on the server and wait for te aprovement from the server
|
||||||
|
|
||||||
|
return TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::startServer()
|
||||||
|
{
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "Starting tunnel proxy...";
|
||||||
|
foreach (TransportInterface *interface, m_transportInterfaces) {
|
||||||
|
interface->startServer();
|
||||||
|
}
|
||||||
|
setRunning(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::stopServer()
|
||||||
|
{
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "Stopping tunnel proxy...";
|
||||||
|
foreach (TransportInterface *interface, m_transportInterfaces) {
|
||||||
|
interface->stopServer();
|
||||||
|
}
|
||||||
|
setRunning(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::tick()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::onClientConnected(const QUuid &clientId, const QHostAddress &address)
|
||||||
|
{
|
||||||
|
TransportInterface *interface = static_cast<TransportInterface *>(sender());
|
||||||
|
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "New client connected" << interface->serverName() << clientId.toString() << address.toString();
|
||||||
|
TunnelProxyClient *tunnelProxyClient = new TunnelProxyClient(interface, clientId, address, this);
|
||||||
|
m_proxyClients.insert(clientId, tunnelProxyClient);
|
||||||
|
m_jsonRpcServer->registerClient(tunnelProxyClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::onClientDisconnected(const QUuid &clientId)
|
||||||
|
{
|
||||||
|
TransportInterface *interface = static_cast<TransportInterface *>(sender());
|
||||||
|
qCDebug(dcTunnelProxyServer()) << "Client disconnected" << interface->serverName() << clientId.toString();
|
||||||
|
|
||||||
|
TunnelProxyClient *tunnelProxyClient = m_proxyClients.take(clientId);
|
||||||
|
if (!tunnelProxyClient) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Unknown client disconnected from proxy server." << clientId.toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tunnelProxyClient->type() == TunnelProxyClient::TypeServer) {
|
||||||
|
TunnelProxyServerConnection *serverConnection = m_tunnelProxyServerConnections.take(tunnelProxyClient->uuid());
|
||||||
|
if (!serverConnection) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Could not find server connection for disconnected tunnel proxy client claiming to be a server.";
|
||||||
|
} else {
|
||||||
|
// TODO: kill all related clients
|
||||||
|
|
||||||
|
serverConnection->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tunnelProxyClient->type() == TunnelProxyClient::TypeClient) {
|
||||||
|
TunnelProxyClientConnection *clientConnection = m_tunnelProxyClientConnections.take(tunnelProxyClient->uuid());
|
||||||
|
|
||||||
|
if (!clientConnection) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Could not find client connection for disconnected tunnel proxy client claiming to be a client.";
|
||||||
|
} else {
|
||||||
|
// TODO: remove from server
|
||||||
|
|
||||||
|
clientConnection->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregister from json rpc server
|
||||||
|
m_jsonRpcServer->unregisterClient(tunnelProxyClient);
|
||||||
|
|
||||||
|
// Delete the proxy client
|
||||||
|
tunnelProxyClient->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelProxyServer::onClientDataAvailable(const QUuid &clientId, const QByteArray &data)
|
||||||
|
{
|
||||||
|
TunnelProxyClient *tunnelProxyClient = m_proxyClients.value(clientId);
|
||||||
|
if (!tunnelProxyClient) {
|
||||||
|
qCWarning(dcTunnelProxyServer()) << "Data received but could not find client for uuid" << clientId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcTunnelProxyServerTraffic()) << "Client data available" << tunnelProxyClient << qUtf8Printable(data);
|
||||||
|
|
||||||
|
// TODO: verify if encoded and for whom this data is... 0x0000 is for the json rpc handler...
|
||||||
|
|
||||||
|
m_jsonRpcServer->processData(tunnelProxyClient, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -25,37 +25,43 @@
|
|||||||
*
|
*
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#ifndef TUNNELPROXYMANAGER_H
|
#ifndef TUNNELPROXYSERVER_H
|
||||||
#define TUNNELPROXYMANAGER_H
|
#define TUNNELPROXYSERVER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "server/jsonrpcserver.h"
|
#include "server/jsonrpcserver.h"
|
||||||
#include "server/transportinterface.h"
|
#include "server/transportinterface.h"
|
||||||
|
#include "tunnelproxyclient.h"
|
||||||
#include "tunnelproxyserverconnection.h"
|
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
class TunnelProxyManager : public QObject
|
class TunnelProxyServerConnection;
|
||||||
|
class TunnelProxyClientConnection;
|
||||||
|
|
||||||
|
class TunnelProxyServer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum Error {
|
enum TunnelProxyError {
|
||||||
ErrorNoError,
|
TunnelProxyErrorNoError,
|
||||||
ErrorServerNotFound
|
TunnelProxyErrorInvalidUuid,
|
||||||
|
TunnelProxyErrorInternalServerError,
|
||||||
|
TunnelProxyErrorServerNotFound,
|
||||||
|
TunnelProxyErrorAlreadyRegistered
|
||||||
};
|
};
|
||||||
Q_ENUM(Error)
|
Q_ENUM(TunnelProxyError)
|
||||||
|
|
||||||
explicit TunnelProxyManager(QObject *parent = nullptr);
|
explicit TunnelProxyServer(QObject *parent = nullptr);
|
||||||
~TunnelProxyManager();
|
~TunnelProxyServer();
|
||||||
|
|
||||||
bool running() const;
|
bool running() const;
|
||||||
void setRunning(bool running);
|
void setRunning(bool running);
|
||||||
|
|
||||||
void registerTransportInterface(TransportInterface *interface);
|
void registerTransportInterface(TransportInterface *interface);
|
||||||
|
|
||||||
TunnelProxyManager::Error registerServer(const QUuid &clientId, const QUuid &serverUuid, const QString &serverName);
|
TunnelProxyServer::TunnelProxyError registerServer(const QUuid &clientId, const QUuid &serverUuid, const QString &serverName);
|
||||||
|
TunnelProxyServer::TunnelProxyError registerClient(const QUuid &clientId, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startServer();
|
void startServer();
|
||||||
@ -71,23 +77,20 @@ private slots:
|
|||||||
void onClientDisconnected(const QUuid &clientId);
|
void onClientDisconnected(const QUuid &clientId);
|
||||||
void onClientDataAvailable(const QUuid &clientId, const QByteArray &data);
|
void onClientDataAvailable(const QUuid &clientId, const QByteArray &data);
|
||||||
|
|
||||||
// void onTunnelProxyServerRegistered();
|
|
||||||
// void onProxyTunnelClientRegistered();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonRpcServer *m_jsonRpcServer = nullptr;
|
JsonRpcServer *m_jsonRpcServer = nullptr;
|
||||||
QList<TransportInterface *> m_transportInterfaces;
|
QList<TransportInterface *> m_transportInterfaces;
|
||||||
|
|
||||||
bool m_running = false;
|
bool m_running = false;
|
||||||
|
|
||||||
QHash<QUuid, ProxyClient *> m_proxyClients; // clients
|
QHash<QUuid, TunnelProxyClient *> m_proxyClients; // clientId, object
|
||||||
|
|
||||||
// Server connections
|
// Server connections
|
||||||
QHash<QUuid, TunnelProxyServerConnection *> m_proxyClientsTunnelServer; // clientUuid, object
|
QHash<QUuid, TunnelProxyServerConnection *> m_tunnelProxyServerConnections; // server uuid, object
|
||||||
QHash<QUuid, TunnelProxyServerConnection *> m_tunnelServers; // server uuid, object
|
QHash<QUuid, TunnelProxyClientConnection *> m_tunnelProxyClientConnections; // client uuid, object
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TUNNELPROXYMANAGER_H
|
#endif // TUNNELPROXYSERVER_H
|
||||||
@ -26,21 +26,22 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "tunnelproxyserverconnection.h"
|
#include "tunnelproxyserverconnection.h"
|
||||||
|
#include "server/transportclient.h"
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
TunnelProxyServerConnection::TunnelProxyServerConnection(ProxyClient *proxyClient, const QUuid &serverUuid, const QString &serverName, QObject *parent) :
|
TunnelProxyServerConnection::TunnelProxyServerConnection(TransportClient *transportClient, const QUuid &serverUuid, const QString &serverName, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_proxyClient(proxyClient),
|
m_transportClient(transportClient),
|
||||||
m_serverUuid(serverUuid),
|
m_serverUuid(serverUuid),
|
||||||
m_serverName(serverName)
|
m_serverName(serverName)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyClient *TunnelProxyServerConnection::proxyClient() const
|
TransportClient *TunnelProxyServerConnection::transportClient() const
|
||||||
{
|
{
|
||||||
return m_proxyClient;
|
return m_transportClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid TunnelProxyServerConnection::serverUuid() const
|
QUuid TunnelProxyServerConnection::serverUuid() const
|
||||||
|
|||||||
@ -28,27 +28,30 @@
|
|||||||
#ifndef TUNNELPROXYSERVERCONNECTION_H
|
#ifndef TUNNELPROXYSERVERCONNECTION_H
|
||||||
#define TUNNELPROXYSERVERCONNECTION_H
|
#define TUNNELPROXYSERVERCONNECTION_H
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "proxy/proxyclient.h"
|
|
||||||
|
|
||||||
namespace remoteproxy {
|
namespace remoteproxy {
|
||||||
|
|
||||||
|
class TransportClient;
|
||||||
|
|
||||||
class TunnelProxyServerConnection : public QObject
|
class TunnelProxyServerConnection : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit TunnelProxyServerConnection(ProxyClient *proxyClient, const QUuid &serverUuid, const QString &serverName, QObject *parent = nullptr);
|
explicit TunnelProxyServerConnection(TransportClient *transportClient, const QUuid &serverUuid, const QString &serverName, QObject *parent = nullptr);
|
||||||
|
|
||||||
ProxyClient *proxyClient() const;
|
TransportClient *transportClient() const;
|
||||||
|
|
||||||
QUuid serverUuid() const;
|
QUuid serverUuid() const;
|
||||||
QString serverName() const;
|
QString serverName() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProxyClient *m_proxyClient = nullptr;
|
TransportClient *m_transportClient = nullptr;
|
||||||
|
|
||||||
QUuid m_serverUuid;
|
QUuid m_serverUuid;
|
||||||
QString m_serverName;
|
QString m_serverName;
|
||||||
|
|||||||
@ -199,4 +199,140 @@ void RemoteProxyTestsTunnelProxy::apiBasicCalls()
|
|||||||
stopServer();
|
stopServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RemoteProxyTestsTunnelProxy::registerServer_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("name");
|
||||||
|
QTest::addColumn<QString>("uuid");
|
||||||
|
QTest::addColumn<TunnelProxyServer::TunnelProxyError>("expectedError");
|
||||||
|
|
||||||
|
QTest::newRow("valid call") << "valid server" << QUuid::createUuid().toString() << TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
QTest::newRow("valid uuid with brackets") << "valid server" << "{00323a95-d1ab-4752-88d4-dbc8b9015b0f}" << TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
QTest::newRow("valid uuid without brackets") << "valid server" << "00323a95-d1ab-4752-88d4-dbc8b9015b0f" << TunnelProxyServer::TunnelProxyErrorNoError;
|
||||||
|
QTest::newRow("invalid null uuid") << "valid server" << QUuid().toString() << TunnelProxyServer::TunnelProxyErrorInvalidUuid;
|
||||||
|
QTest::newRow("invalid null uuid") << "valid server" << "foo" << TunnelProxyServer::TunnelProxyErrorInvalidUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RemoteProxyTestsTunnelProxy::registerServer()
|
||||||
|
{
|
||||||
|
QFETCH(QString, name);
|
||||||
|
QFETCH(QString, uuid);
|
||||||
|
QFETCH(TunnelProxyServer::TunnelProxyError, expectedError);
|
||||||
|
|
||||||
|
// Start the server
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
resetDebugCategories();
|
||||||
|
addDebugCategory("TunnelProxyServer.debug=true");
|
||||||
|
|
||||||
|
// Register a new server
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("serverName", name);
|
||||||
|
params.insert("serverUuid", uuid);
|
||||||
|
|
||||||
|
// Websocket
|
||||||
|
QVariantMap response = invokeWebSocketTunnelProxyApiCall("TunnelProxy.RegisterServer", params).toMap();
|
||||||
|
|
||||||
|
QVERIFY(!response.isEmpty());
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response, expectedError);
|
||||||
|
|
||||||
|
// TCP Socket
|
||||||
|
response = invokeTcpSocketTunnelProxyApiCall("TunnelProxy.RegisterServer", params).toMap();
|
||||||
|
QVERIFY(!response.isEmpty());
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response, expectedError);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteProxyTestsTunnelProxy::registerServerDuplicated()
|
||||||
|
{
|
||||||
|
// Start the server
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
resetDebugCategories();
|
||||||
|
addDebugCategory("TunnelProxyServer.debug=true");
|
||||||
|
|
||||||
|
// Register a new server
|
||||||
|
QString serverName = "tunnel proxy server awesome nymea installation";
|
||||||
|
QUuid serverUuid = QUuid::createUuid();
|
||||||
|
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("serverName", serverName);
|
||||||
|
params.insert("serverUuid", serverUuid.toString());
|
||||||
|
|
||||||
|
// TCP socket
|
||||||
|
QPair<QVariant, QSslSocket *> result = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", params);
|
||||||
|
QVariantMap response = result.first.toMap();
|
||||||
|
QSslSocket *socket = result.second;
|
||||||
|
|
||||||
|
QVERIFY(!response.isEmpty());
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response);
|
||||||
|
|
||||||
|
// Try to register again with the same uuid on the same socket
|
||||||
|
result = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", params, socket);
|
||||||
|
response = result.first.toMap();
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response, TunnelProxyServer::TunnelProxyErrorAlreadyRegistered);
|
||||||
|
|
||||||
|
// Try to register an invalid server uuid
|
||||||
|
QVariantMap paramsInvalidUuid;
|
||||||
|
paramsInvalidUuid.insert("serverName", serverName);
|
||||||
|
paramsInvalidUuid.insert("serverUuid", QUuid().toString());
|
||||||
|
result = invokeTcpSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", paramsInvalidUuid, socket);
|
||||||
|
response = result.first.toMap();
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response, TunnelProxyServer::TunnelProxyErrorInvalidUuid);
|
||||||
|
|
||||||
|
// Close the tcp socket
|
||||||
|
socket->close();
|
||||||
|
delete socket;
|
||||||
|
|
||||||
|
QTest::qWait(100);
|
||||||
|
|
||||||
|
// WebSocket
|
||||||
|
// Try to register from a websocket with the same uuid
|
||||||
|
QPair<QVariant, QWebSocket *> resultWebSocket = invokeWebSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", params);
|
||||||
|
response = resultWebSocket.first.toMap();
|
||||||
|
QWebSocket *webSocket = resultWebSocket.second;
|
||||||
|
QVERIFY(!response.isEmpty());
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response);
|
||||||
|
|
||||||
|
// Try to register again with the same uuid on the same socket
|
||||||
|
resultWebSocket = invokeWebSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", params, webSocket);
|
||||||
|
response = resultWebSocket.first.toMap();
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response, TunnelProxyServer::TunnelProxyErrorAlreadyRegistered);
|
||||||
|
|
||||||
|
// Try to register an invalid server uuid
|
||||||
|
resultWebSocket = invokeWebSocketTunnelProxyApiCallPersistant("TunnelProxy.RegisterServer", paramsInvalidUuid, webSocket);
|
||||||
|
response = resultWebSocket.first.toMap();
|
||||||
|
QVERIFY(response.value("status").toString() == "success");
|
||||||
|
QVERIFY(response.value("params").toMap().contains("tunnelProxyError"));
|
||||||
|
verifyTunnelProxyError(response, TunnelProxyServer::TunnelProxyErrorInvalidUuid);
|
||||||
|
|
||||||
|
webSocket->close();
|
||||||
|
delete webSocket;
|
||||||
|
|
||||||
|
QTest::qWait(100);
|
||||||
|
|
||||||
|
resetDebugCategories();
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QTEST_MAIN(RemoteProxyTestsTunnelProxy)
|
QTEST_MAIN(RemoteProxyTestsTunnelProxy)
|
||||||
|
|||||||
@ -54,6 +54,12 @@ private slots:
|
|||||||
void apiBasicCallsTcp_data();
|
void apiBasicCallsTcp_data();
|
||||||
void apiBasicCallsTcp();
|
void apiBasicCallsTcp();
|
||||||
|
|
||||||
|
void registerServer_data();
|
||||||
|
void registerServer();
|
||||||
|
|
||||||
|
void registerServerDuplicated();
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // REMOTEPROXYTESTSTUNNELPROXY_H
|
#endif // REMOTEPROXYTESTSTUNNELPROXY_H
|
||||||
|
|||||||
@ -42,7 +42,7 @@
|
|||||||
BaseTest::BaseTest(QObject *parent) :
|
BaseTest::BaseTest(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
|
resetDebugCategories();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTest::loadConfiguration(const QString &fileName)
|
void BaseTest::loadConfiguration(const QString &fileName)
|
||||||
@ -52,6 +52,19 @@ void BaseTest::loadConfiguration(const QString &fileName)
|
|||||||
//restartEngine();
|
//restartEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseTest::resetDebugCategories()
|
||||||
|
{
|
||||||
|
m_currentDebugCategories = m_defaultDebugCategories;
|
||||||
|
QLoggingCategory::setFilterRules(m_currentDebugCategories);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseTest::addDebugCategory(const QString &debugCategory)
|
||||||
|
{
|
||||||
|
m_currentDebugCategories += debugCategory + "\n";
|
||||||
|
//qDebug() << m_currentDebugCategories;
|
||||||
|
QLoggingCategory::setFilterRules(m_currentDebugCategories);
|
||||||
|
}
|
||||||
|
|
||||||
void BaseTest::cleanUpEngine()
|
void BaseTest::cleanUpEngine()
|
||||||
{
|
{
|
||||||
qDebug() << "Clean up engine";
|
qDebug() << "Clean up engine";
|
||||||
@ -87,8 +100,6 @@ void BaseTest::restartEngine()
|
|||||||
|
|
||||||
void BaseTest::startEngine()
|
void BaseTest::startEngine()
|
||||||
{
|
{
|
||||||
QLoggingCategory::setFilterRules("*.debug=false\ndefault.debug=true\nApplication.debug=true");
|
|
||||||
|
|
||||||
m_configuration = new ProxyConfiguration(this);
|
m_configuration = new ProxyConfiguration(this);
|
||||||
loadConfiguration(":/test-configuration.conf");
|
loadConfiguration(":/test-configuration.conf");
|
||||||
|
|
||||||
@ -302,8 +313,8 @@ bool BaseTest::createRemoteConnection(const QString &token, const QString &nonce
|
|||||||
QString nameConnectionTwo = "Test client two";
|
QString nameConnectionTwo = "Test client two";
|
||||||
QUuid uuidConnectionTwo = QUuid::createUuid();
|
QUuid uuidConnectionTwo = QUuid::createUuid();
|
||||||
|
|
||||||
// QByteArray dataOne = "Hello from client one :-)";
|
// QByteArray dataOne = "Hello from client one :-)";
|
||||||
// QByteArray dataTwo = "Hello from client two :-)";
|
// QByteArray dataTwo = "Hello from client two :-)";
|
||||||
|
|
||||||
// Create two connection
|
// Create two connection
|
||||||
RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, parent);
|
RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, parent);
|
||||||
@ -466,6 +477,7 @@ QVariant BaseTest::invokeWebSocketTunnelProxyApiCall(const QString &method, cons
|
|||||||
socket->open(Engine::instance()->webSocketServerTunnelProxy()->serverUrl());
|
socket->open(Engine::instance()->webSocketServerTunnelProxy()->serverUrl());
|
||||||
spyConnection.wait();
|
spyConnection.wait();
|
||||||
if (spyConnection.count() == 0) {
|
if (spyConnection.count() == 0) {
|
||||||
|
qWarning() << "Failed to connect websocket on tunnel proxy";
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,8 +485,10 @@ 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();
|
||||||
|
|
||||||
socket->close();
|
if (!remainsConnected) {
|
||||||
socket->deleteLater();
|
socket->close();
|
||||||
|
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'
|
||||||
@ -651,6 +665,125 @@ QVariant BaseTest::injectTcpSocketTunnelProxyData(const QByteArray &data)
|
|||||||
return jsonDoc.toVariant();
|
return jsonDoc.toVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPair<QVariant, QSslSocket *> BaseTest::invokeTcpSocketTunnelProxyApiCallPersistant(const QString &method, const QVariantMap params, QSslSocket *existingSocket)
|
||||||
|
{
|
||||||
|
QSslSocket *socket = nullptr;
|
||||||
|
if (!existingSocket) {
|
||||||
|
socket = new QSslSocket(this);
|
||||||
|
typedef void (QSslSocket:: *sslErrorsSignal)(const QList<QSslError> &);
|
||||||
|
QObject::connect(socket, static_cast<sslErrorsSignal>(&QSslSocket::sslErrors), this, &BaseTest::sslSocketSslErrors);
|
||||||
|
|
||||||
|
QSignalSpy spyConnection(socket, &QSslSocket::connected);
|
||||||
|
socket->connectToHostEncrypted(Engine::instance()->tcpSocketServerTunnelProxy()->serverUrl().host(),
|
||||||
|
static_cast<quint16>(Engine::instance()->tcpSocketServerTunnelProxy()->serverUrl().port()));
|
||||||
|
spyConnection.wait();
|
||||||
|
if (spyConnection.count() == 0) {
|
||||||
|
return QPair<QVariant, QSslSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
socket = existingSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap request;
|
||||||
|
request.insert("id", m_commandCounter);
|
||||||
|
request.insert("method", method);
|
||||||
|
request.insert("params", params);
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(request);
|
||||||
|
|
||||||
|
|
||||||
|
QSignalSpy dataSpy(socket, &QSslSocket::readyRead);
|
||||||
|
socket->write(jsonDoc.toJson(QJsonDocument::Compact) + '\n');
|
||||||
|
// FIXME: check why it waits the full time here
|
||||||
|
dataSpy.wait(500);
|
||||||
|
if (dataSpy.count() != 1) {
|
||||||
|
qWarning() << "No data received";
|
||||||
|
return QPair<QVariant, QSslSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray data = socket->readAll();
|
||||||
|
|
||||||
|
// Make sure the response ends with '}\n'
|
||||||
|
if (!data.endsWith("}\n")) {
|
||||||
|
qWarning() << "JSON data does not end with \"}\n\"";
|
||||||
|
return QPair<QVariant, QSslSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the response it a valid JSON string
|
||||||
|
QJsonParseError error;
|
||||||
|
jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "JSON parser error" << error.errorString();
|
||||||
|
return QPair<QVariant, QSslSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||||
|
|
||||||
|
if (response.value("id").toInt() == m_commandCounter) {
|
||||||
|
m_commandCounter++;
|
||||||
|
return QPair<QVariant, QSslSocket *>(jsonDoc.toVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_commandCounter++;
|
||||||
|
return QPair<QVariant, QSslSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QVariant, QWebSocket *> BaseTest::invokeWebSocketTunnelProxyApiCallPersistant(const QString &method, const QVariantMap params, QWebSocket *existingSocket)
|
||||||
|
{
|
||||||
|
QWebSocket *socket = nullptr;
|
||||||
|
if (!existingSocket) {
|
||||||
|
socket = new QWebSocket("tunnelproxy-testclient", QWebSocketProtocol::Version13);
|
||||||
|
connect(socket, &QWebSocket::sslErrors, this, &BaseTest::sslErrors);
|
||||||
|
QSignalSpy spyConnection(socket, SIGNAL(connected()));
|
||||||
|
socket->open(Engine::instance()->webSocketServerTunnelProxy()->serverUrl());
|
||||||
|
spyConnection.wait();
|
||||||
|
if (spyConnection.count() == 0) {
|
||||||
|
qWarning() << "Failed to connect websocket on tunnel proxy";
|
||||||
|
return QPair<QVariant, QWebSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
socket = existingSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap request;
|
||||||
|
request.insert("id", m_commandCounter);
|
||||||
|
request.insert("method", method);
|
||||||
|
request.insert("params", params);
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(request);
|
||||||
|
|
||||||
|
QSignalSpy dataSpy(socket, SIGNAL(textMessageReceived(QString)));
|
||||||
|
socket->sendTextMessage(QString(jsonDoc.toJson(QJsonDocument::Compact)));
|
||||||
|
dataSpy.wait();
|
||||||
|
|
||||||
|
for (int i = 0; i < dataSpy.count(); i++) {
|
||||||
|
// Make sure the response ends with '}\n'
|
||||||
|
if (!dataSpy.at(i).last().toByteArray().endsWith("}\n")) {
|
||||||
|
qWarning() << "JSON data does not end with \"}\n\"";
|
||||||
|
return QPair<QVariant, QWebSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the response it a valid JSON string
|
||||||
|
QJsonParseError error;
|
||||||
|
jsonDoc = QJsonDocument::fromJson(dataSpy.at(i).last().toByteArray(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "JSON parser error" << error.errorString();
|
||||||
|
return QPair<QVariant, QWebSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||||
|
|
||||||
|
// skip notifications
|
||||||
|
if (response.contains("notification"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (response.value("id").toInt() == m_commandCounter) {
|
||||||
|
m_commandCounter++;
|
||||||
|
return QPair<QVariant, QWebSocket *>(jsonDoc.toVariant(), socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_commandCounter++;
|
||||||
|
return QPair<QVariant, QWebSocket *>(QVariant(), socket);
|
||||||
|
}
|
||||||
|
|
||||||
void BaseTest::initTestCase()
|
void BaseTest::initTestCase()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<RemoteProxyConnection::State>();
|
qRegisterMetaType<RemoteProxyConnection::State>();
|
||||||
|
|||||||
@ -76,6 +76,9 @@ protected:
|
|||||||
void loadConfiguration(const QString &fileName);
|
void loadConfiguration(const QString &fileName);
|
||||||
void setAuthenticator(Authenticator *authenticator);
|
void setAuthenticator(Authenticator *authenticator);
|
||||||
|
|
||||||
|
void resetDebugCategories();
|
||||||
|
void addDebugCategory(const QString &debugCategory);
|
||||||
|
|
||||||
void cleanUpEngine();
|
void cleanUpEngine();
|
||||||
void restartEngine();
|
void restartEngine();
|
||||||
void startEngine();
|
void startEngine();
|
||||||
@ -94,6 +97,9 @@ protected:
|
|||||||
QVariant invokeTcpSocketTunnelProxyApiCall(const QString &method, const QVariantMap params = QVariantMap(), bool remainsConnected = true);
|
QVariant invokeTcpSocketTunnelProxyApiCall(const QString &method, const QVariantMap params = QVariantMap(), bool remainsConnected = true);
|
||||||
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, QWebSocket *> invokeWebSocketTunnelProxyApiCallPersistant(const QString &method, const QVariantMap params = QVariantMap(), QWebSocket *existingSocket = nullptr);
|
||||||
|
|
||||||
|
|
||||||
bool createRemoteConnection(const QString &token, const QString &nonce, QObject *parent);
|
bool createRemoteConnection(const QString &token, const QString &nonce, QObject *parent);
|
||||||
|
|
||||||
@ -137,6 +143,13 @@ public slots:
|
|||||||
verifyError(response, "authenticationError", JsonTypes::authenticationErrorToString(error));
|
verifyError(response, "authenticationError", JsonTypes::authenticationErrorToString(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void verifyTunnelProxyError(const QVariant &response, TunnelProxyServer::TunnelProxyError error = TunnelProxyServer::TunnelProxyErrorNoError) {
|
||||||
|
verifyError(response, "tunnelProxyError", JsonTypes::tunnelProxyErrorToString(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_defaultDebugCategories = "*.debug=false\ndefault.debug=true\nApplication.debug=true\n";
|
||||||
|
QString m_currentDebugCategories;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BASETEST_H
|
#endif // BASETEST_H
|
||||||
|
|||||||
Reference in New Issue
Block a user