First tunnel connection
This commit is contained in:
parent
ca54d5b44d
commit
c40aac6808
@ -17,7 +17,7 @@ QString AwsAuthenticator::name() const
|
||||
|
||||
AuthenticationReply *AwsAuthenticator::authenticate(ProxyClient *proxyClient)
|
||||
{
|
||||
qCDebug(dcAuthenticator()) << name() << "Start authenticating" << proxyClient << "using token" << proxyClient->token();
|
||||
qCDebug(dcAuthenticator()) << name() << "Start authenticating" << proxyClient << "using token" << proxyClient->token();
|
||||
AuthenticationReply *reply = createAuthenticationReply(proxyClient, this);
|
||||
return reply;
|
||||
}
|
||||
|
||||
@ -35,26 +35,17 @@ void Engine::start()
|
||||
if (!m_running)
|
||||
qCDebug(dcEngine()) << "Start server engine";
|
||||
|
||||
// Init proxy server
|
||||
if (m_proxyServer) {
|
||||
delete m_proxyServer;
|
||||
m_proxyServer = nullptr;
|
||||
}
|
||||
// Clean up
|
||||
clean();
|
||||
|
||||
m_configuration = new ProxyConfiguration(this);
|
||||
m_proxyServer = new ProxyServer(this);
|
||||
|
||||
// Init WebSocketServer
|
||||
if (m_webSocketServer) {
|
||||
delete m_webSocketServer;
|
||||
m_webSocketServer = nullptr;
|
||||
}
|
||||
m_webSocketServer = new WebSocketServer(m_sslConfiguration, this);
|
||||
|
||||
QUrl websocketServerUrl;
|
||||
websocketServerUrl.setScheme("wss");
|
||||
websocketServerUrl.setHost(m_webSocketServerHostAddress.toString());
|
||||
websocketServerUrl.setPort(m_webSocketServerPort);
|
||||
|
||||
m_webSocketServer = new WebSocketServer(m_sslConfiguration, this);
|
||||
m_webSocketServer->setServerUrl(websocketServerUrl);
|
||||
|
||||
m_proxyServer->registerTransportInterface(m_webSocketServer);
|
||||
@ -65,7 +56,8 @@ void Engine::start()
|
||||
qCDebug(dcEngine()) << "Starting proxy server";
|
||||
m_proxyServer->startServer();
|
||||
|
||||
QTimer::singleShot(0, this, &Engine::run);
|
||||
// Set tunning true in the next event loop
|
||||
QMetaObject::invokeMethod(this, QString("setRunning").toLatin1().data(), Qt::QueuedConnection, Q_ARG(bool, true));
|
||||
}
|
||||
|
||||
void Engine::stop()
|
||||
@ -73,17 +65,7 @@ void Engine::stop()
|
||||
if (m_running)
|
||||
qCDebug(dcEngine()) << "Stop server engine";
|
||||
|
||||
if (m_proxyServer) {
|
||||
m_proxyServer->stopServer();
|
||||
delete m_proxyServer;
|
||||
m_proxyServer = nullptr;
|
||||
}
|
||||
|
||||
if (m_webSocketServer) {
|
||||
delete m_webSocketServer;
|
||||
m_webSocketServer = nullptr;
|
||||
}
|
||||
|
||||
clean();
|
||||
setRunning(false);
|
||||
}
|
||||
|
||||
@ -176,6 +158,26 @@ Engine::~Engine()
|
||||
stop();
|
||||
}
|
||||
|
||||
void Engine::clean()
|
||||
{
|
||||
if (m_proxyServer) {
|
||||
m_proxyServer->stopServer();
|
||||
delete m_proxyServer;
|
||||
m_proxyServer = nullptr;
|
||||
}
|
||||
|
||||
if (m_webSocketServer) {
|
||||
delete m_webSocketServer;
|
||||
m_webSocketServer = nullptr;
|
||||
}
|
||||
|
||||
if (m_configuration) {
|
||||
delete m_configuration;
|
||||
m_configuration = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Engine::setRunning(bool running)
|
||||
{
|
||||
if (m_running == running)
|
||||
@ -186,9 +188,5 @@ void Engine::setRunning(bool running)
|
||||
emit runningChanged(m_running);
|
||||
}
|
||||
|
||||
void Engine::run()
|
||||
{
|
||||
setRunning(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
#include "proxyserver.h"
|
||||
#include "websocketserver.h"
|
||||
#include "proxyconfiguration.h"
|
||||
#include "authentication/authenticator.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
@ -53,18 +54,18 @@ private:
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
QUrl m_authenticationServerUrl;
|
||||
|
||||
ProxyConfiguration *m_configuration = nullptr;
|
||||
Authenticator *m_authenticator = nullptr;
|
||||
ProxyServer *m_proxyServer = nullptr;
|
||||
WebSocketServer *m_webSocketServer = nullptr;
|
||||
|
||||
void setRunning(bool running);
|
||||
|
||||
private slots:
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void runningChanged(bool running);
|
||||
|
||||
private slots:
|
||||
void clean();
|
||||
void setRunning(bool running);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -66,15 +66,16 @@ void AuthenticationHandler::onAuthenticationFinished()
|
||||
if (authenticationReply->error() != Authenticator::AuthenticationErrorNoError) {
|
||||
qCWarning(dcJsonRpc()) << "Authentication error occured" << authenticationReply->error();
|
||||
jsonReply->setSuccess(false);
|
||||
authenticationReply->proxyClient()->setAuthenticated(false);
|
||||
} else {
|
||||
// Successfully authenticated
|
||||
authenticationReply->proxyClient()->setAuthenticated(true);
|
||||
jsonReply->setSuccess(true);
|
||||
}
|
||||
|
||||
jsonReply->setData(errorToReply(authenticationReply->error()));
|
||||
jsonReply->finished();
|
||||
|
||||
// Set client authenticated
|
||||
authenticationReply->proxyClient()->setAuthenticated(authenticationReply->error() == Authenticator::AuthenticationErrorNoError);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -100,18 +100,6 @@ JsonReply *JsonRpcServer::Introspect(const QVariantMap ¶ms, ProxyClient *pro
|
||||
return createReply(data);
|
||||
}
|
||||
|
||||
void JsonRpcServer::sendNotification(const QString &nameSpace, const QString &method, const QVariantMap ¶ms, ProxyClient *proxyClient)
|
||||
{
|
||||
QVariantMap notification;
|
||||
notification.insert("id", m_notificationId++);
|
||||
notification.insert("notification", nameSpace + "." + method);
|
||||
notification.insert("params", params);
|
||||
|
||||
QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact);
|
||||
qCDebug(dcJsonRpcTraffic()) << "Sending notification:" << data;
|
||||
proxyClient->interface()->sendData(proxyClient->clientId(), data);
|
||||
}
|
||||
|
||||
void JsonRpcServer::sendResponse(ProxyClient *client, int commandId, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap response;
|
||||
@ -290,4 +278,16 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
|
||||
}
|
||||
}
|
||||
|
||||
void JsonRpcServer::sendNotification(const QString &nameSpace, const QString &method, const QVariantMap ¶ms, ProxyClient *proxyClient)
|
||||
{
|
||||
QVariantMap notification;
|
||||
notification.insert("id", m_notificationId++);
|
||||
notification.insert("notification", nameSpace + "." + method);
|
||||
notification.insert("params", params);
|
||||
|
||||
QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact);
|
||||
qCDebug(dcJsonRpcTraffic()) << "Sending notification:" << data;
|
||||
proxyClient->interface()->sendData(proxyClient->clientId(), data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -24,8 +24,6 @@ public:
|
||||
Q_INVOKABLE JsonReply *Hello(const QVariantMap ¶ms, ProxyClient *proxyClient = nullptr) const;
|
||||
Q_INVOKABLE JsonReply *Introspect(const QVariantMap ¶ms, ProxyClient *proxyClient = nullptr) const;
|
||||
|
||||
void sendNotification(const QString &nameSpace, const QString &method, const QVariantMap ¶ms, ProxyClient *proxyClient = nullptr);
|
||||
|
||||
signals:
|
||||
void TunnelEstablished(const QVariantMap ¶ms);
|
||||
|
||||
@ -33,7 +31,7 @@ private:
|
||||
QHash<QString, JsonHandler *> m_handlers;
|
||||
QHash<JsonReply *, ProxyClient *> m_asyncReplies;
|
||||
QList<ProxyClient *> m_clients;
|
||||
int m_notificationId;
|
||||
int m_notificationId = 0;
|
||||
|
||||
void sendResponse(ProxyClient *client, int commandId, const QVariantMap ¶ms = QVariantMap());
|
||||
void sendErrorResponse(ProxyClient *client, int commandId, const QString &error);
|
||||
@ -54,6 +52,7 @@ public slots:
|
||||
|
||||
// Process data from client
|
||||
void processData(ProxyClient *proxyClient, const QByteArray &data);
|
||||
void sendNotification(const QString &nameSpace, const QString &method, const QVariantMap ¶ms, ProxyClient *proxyClient = nullptr);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -18,7 +18,8 @@ HEADERS += \
|
||||
authentication/authenticator.h \
|
||||
authentication/awsauthenticator.h \
|
||||
authentication/authenticationreply.h \
|
||||
proxyconfiguration.h
|
||||
proxyconfiguration.h \
|
||||
tunnelconnection.h
|
||||
|
||||
SOURCES += \
|
||||
engine.cpp \
|
||||
@ -35,7 +36,8 @@ SOURCES += \
|
||||
authentication/authenticator.cpp \
|
||||
authentication/awsauthenticator.cpp \
|
||||
authentication/authenticationreply.cpp \
|
||||
proxyconfiguration.cpp
|
||||
proxyconfiguration.cpp \
|
||||
tunnelconnection.cpp
|
||||
|
||||
|
||||
# install header file with relative subdirectory
|
||||
|
||||
@ -8,4 +8,5 @@ Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
||||
Q_LOGGING_CATEGORY(dcWebSocketServerTraffic, "WebSocketServerTraffic")
|
||||
Q_LOGGING_CATEGORY(dcAuthenticator, "Authenticator")
|
||||
Q_LOGGING_CATEGORY(dcProxyServer, "ProxyServer")
|
||||
Q_LOGGING_CATEGORY(dcProxyServerTraffic, "ProxyServerTraffic")
|
||||
|
||||
|
||||
@ -12,5 +12,6 @@ Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServerTraffic)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcAuthenticator)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcProxyServer)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcProxyServerTraffic)
|
||||
|
||||
#endif // LOGGINGCATEGORIES_H
|
||||
|
||||
@ -81,15 +81,7 @@ void ProxyClient::setToken(const QString &token)
|
||||
QDebug operator<<(QDebug debug, ProxyClient *proxyClient)
|
||||
{
|
||||
debug.nospace() << "ProxyClient(" << proxyClient->interface()->serverName();
|
||||
debug.nospace() << ", " << proxyClient->clientId().toString() << ") :" << endl;
|
||||
debug.nospace() << " tunnel: " << proxyClient->isTunnelConnected() << endl;
|
||||
debug.nospace() << " authenticated: " << proxyClient->isAuthenticated() << endl;
|
||||
if (!proxyClient->name().isEmpty() && !proxyClient->token().isEmpty() && !proxyClient->uuid().isEmpty()) {
|
||||
debug.nospace() << " name: " << proxyClient->name() << endl;
|
||||
debug.nospace() << " uuid: " << proxyClient->uuid() << endl;
|
||||
debug.nospace() << " token: " << proxyClient->token() << endl;
|
||||
|
||||
}
|
||||
debug.nospace() << ", " << proxyClient->clientId().toString() << ") ";
|
||||
return debug;
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
#include "proxyserver.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QMetaObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace remoteproxy {
|
||||
|
||||
ProxyServer::ProxyServer(QObject *parent) : QObject(parent)
|
||||
{
|
||||
qRegisterMetaType<ProxyClient *>("ProxyClient *");
|
||||
m_jsonRpcServer = new JsonRpcServer(this);
|
||||
|
||||
}
|
||||
|
||||
ProxyServer::~ProxyServer()
|
||||
@ -16,6 +17,11 @@ ProxyServer::~ProxyServer()
|
||||
qCDebug(dcProxyServer()) << "Shutting down proxy server";
|
||||
}
|
||||
|
||||
bool ProxyServer::running() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
|
||||
void ProxyServer::registerTransportInterface(TransportInterface *interface)
|
||||
{
|
||||
qCDebug(dcProxyServer()) << "Register transport interface" << interface->serverName();
|
||||
@ -32,6 +38,30 @@ void ProxyServer::registerTransportInterface(TransportInterface *interface)
|
||||
m_transportInterfaces.append(interface);
|
||||
}
|
||||
|
||||
void ProxyServer::setRunning(bool running)
|
||||
{
|
||||
if (m_running == running)
|
||||
return;
|
||||
|
||||
qCDebug(dcProxyServer()) << "The proxy server is now up and running";
|
||||
m_running = running;
|
||||
emit runningChanged();
|
||||
}
|
||||
|
||||
ProxyClient *ProxyServer::getRemoteClient(ProxyClient *proxyClient)
|
||||
{
|
||||
if (!m_tunnels.contains(proxyClient->token()))
|
||||
return nullptr;
|
||||
|
||||
if (proxyClient == m_tunnels.value(proxyClient->token()).clientOne()) {
|
||||
return m_tunnels.value(proxyClient->token()).clientTwo();
|
||||
} else if (proxyClient == m_tunnels.value(proxyClient->token()).clientTwo()) {
|
||||
return m_tunnels.value(proxyClient->token()).clientOne();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ProxyServer::sendResponse(TransportInterface *interface, const QUuid &clientId, const QVariantMap &response)
|
||||
{
|
||||
QByteArray data = QJsonDocument::fromVariant(response).toJson(QJsonDocument::Compact);
|
||||
@ -39,6 +69,48 @@ void ProxyServer::sendResponse(TransportInterface *interface, const QUuid &clien
|
||||
interface->sendData(clientId, data);
|
||||
}
|
||||
|
||||
void ProxyServer::establishTunnel(ProxyClient *firstClient, ProxyClient *secondClient)
|
||||
{
|
||||
qCDebug(dcProxyServer()) << "Create tunnel between authenticated clients:";
|
||||
qCDebug(dcProxyServer()) << " -->" << firstClient << firstClient->name();
|
||||
qCDebug(dcProxyServer()) << " -->" << secondClient << secondClient->name();
|
||||
|
||||
TunnelConnection tunnel(firstClient, secondClient);
|
||||
if (!tunnel.isValid()) {
|
||||
qCWarning(dcProxyServer()) << "Invalid tunnel. Could not establish connection.";
|
||||
// FIXME
|
||||
}
|
||||
|
||||
m_tunnels.insert(tunnel.token(), tunnel);
|
||||
|
||||
// Tell both clients the tunnel has been established
|
||||
QVariantMap notificationParamsFirst;
|
||||
notificationParamsFirst.insert("name", tunnel.clientTwo()->name());
|
||||
notificationParamsFirst.insert("uuid", tunnel.clientTwo()->uuid());
|
||||
|
||||
QVariantMap notificationParamsSecond;
|
||||
notificationParamsSecond.insert("name", tunnel.clientOne()->name());
|
||||
notificationParamsSecond.insert("uuid", tunnel.clientOne()->uuid());
|
||||
|
||||
// Make sure the proxy is the first one who knows that the tunnel is connected
|
||||
firstClient->setTunnelConnected(true);
|
||||
secondClient->setTunnelConnected(true);
|
||||
|
||||
// Notify the clients in the next event loop
|
||||
QMetaObject::invokeMethod(m_jsonRpcServer, QString("sendNotification").toLatin1().data(), Qt::QueuedConnection,
|
||||
Q_ARG(QString, "ProxyServer"),
|
||||
Q_ARG(QString, "TunnelEstablished"),
|
||||
Q_ARG(QVariantMap, notificationParamsFirst),
|
||||
Q_ARG(ProxyClient *, tunnel.clientOne()));
|
||||
|
||||
|
||||
QMetaObject::invokeMethod(m_jsonRpcServer, QString("sendNotification").toLatin1().data(), Qt::QueuedConnection,
|
||||
Q_ARG(QString, "ProxyServer"),
|
||||
Q_ARG(QString, "TunnelEstablished"),
|
||||
Q_ARG(QVariantMap, notificationParamsSecond),
|
||||
Q_ARG(ProxyClient *, tunnel.clientTwo()));
|
||||
}
|
||||
|
||||
void ProxyServer::onClientConnected(const QUuid &clientId)
|
||||
{
|
||||
TransportInterface *interface = static_cast<TransportInterface *>(sender());
|
||||
@ -86,10 +158,9 @@ void ProxyServer::onClientDataAvailable(const QUuid &clientId, const QByteArray
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcProxyServer()) << "Client data available" << proxyClient << qUtf8Printable(data);
|
||||
|
||||
// If this client is not authenticated yet, and not tunnel connected, pipe the traffic into the json rpc server
|
||||
if (!proxyClient->isAuthenticated() && !proxyClient->isTunnelConnected()) {
|
||||
qCDebug(dcProxyServerTraffic()) << "Client data available" << proxyClient << qUtf8Printable(data);
|
||||
m_jsonRpcServer->processData(proxyClient, data);
|
||||
return;
|
||||
}
|
||||
@ -105,15 +176,42 @@ void ProxyServer::onClientDataAvailable(const QUuid &clientId, const QByteArray
|
||||
}
|
||||
|
||||
if (proxyClient->isAuthenticated() && proxyClient->isTunnelConnected()) {
|
||||
// TODO: Pipe the traffic to the tunnel client
|
||||
// Check if there is realy a tunnel for this client
|
||||
if (!m_tunnels.contains(proxyClient->token())) {
|
||||
// FIXME: kill all clients, something went wrong
|
||||
}
|
||||
|
||||
ProxyClient *remoteClient = getRemoteClient(proxyClient);
|
||||
if (!remoteClient) {
|
||||
// FIXME: kill all clients, something went wrong
|
||||
}
|
||||
|
||||
qCDebug(dcProxyServerTraffic()) << "Pipe data:";
|
||||
qCDebug(dcProxyServerTraffic()) << " --> from" << proxyClient;
|
||||
qCDebug(dcProxyServerTraffic()) << " --> to" << remoteClient;
|
||||
qCDebug(dcProxyServerTraffic()) << " --> data:" << qUtf8Printable(data);
|
||||
|
||||
remoteClient->interface()->sendData(remoteClient->clientId(), data);
|
||||
}
|
||||
}
|
||||
|
||||
void ProxyServer::onProxyClientAuthenticated()
|
||||
{
|
||||
ProxyClient *proxyClient = static_cast<ProxyClient *>(sender());
|
||||
|
||||
qCDebug(dcProxyServer()) << "Client authenticated" << proxyClient;
|
||||
m_authenticatedClients.insert(proxyClient->token(), proxyClient);
|
||||
qCDebug(dcProxyServer()) << " name:" << proxyClient->name();
|
||||
qCDebug(dcProxyServer()) << " uuid:" << proxyClient->uuid();
|
||||
|
||||
// Check if we have an other authenticated client with this token
|
||||
if (m_authenticatedClients.keys().contains(proxyClient->token())) {
|
||||
// Found a client with this token
|
||||
ProxyClient *tunnelEnd = m_authenticatedClients.take(proxyClient->token());
|
||||
establishTunnel(tunnelEnd, proxyClient);
|
||||
} else {
|
||||
// Append and wait for the other client
|
||||
m_authenticatedClients.insert(proxyClient->token(), proxyClient);
|
||||
}
|
||||
}
|
||||
|
||||
void ProxyServer::onProxyClientTunnelConnected()
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "proxyclient.h"
|
||||
#include "jsonrpcserver.h"
|
||||
#include "tunnelconnection.h"
|
||||
#include "transportinterface.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
@ -18,16 +19,33 @@ public:
|
||||
explicit ProxyServer(QObject *parent = nullptr);
|
||||
~ProxyServer();
|
||||
|
||||
bool running() const;
|
||||
void registerTransportInterface(TransportInterface *interface);
|
||||
|
||||
private:
|
||||
JsonRpcServer *m_jsonRpcServer = nullptr;
|
||||
QList<TransportInterface *> m_transportInterfaces;
|
||||
|
||||
bool m_running = false;
|
||||
|
||||
// Transport ClientId, ProxyClient
|
||||
QHash<QUuid, ProxyClient *> m_proxyClients;
|
||||
|
||||
// Token, ProxyClient
|
||||
QHash<QString, ProxyClient *> m_authenticatedClients;
|
||||
|
||||
// Token, Tunnel
|
||||
QHash<QString, TunnelConnection> m_tunnels;
|
||||
|
||||
void setRunning(bool running);
|
||||
|
||||
ProxyClient *getRemoteClient(ProxyClient *proxyClient);
|
||||
|
||||
void sendResponse(TransportInterface *interface, const QUuid &clientId, const QVariantMap &response = QVariantMap());
|
||||
void establishTunnel(ProxyClient *firstClient, ProxyClient *secondClient);
|
||||
|
||||
signals:
|
||||
void runningChanged();
|
||||
|
||||
private slots:
|
||||
void onClientConnected(const QUuid &clientId);
|
||||
|
||||
47
libnymea-remoteproxy/tunnelconnection.cpp
Normal file
47
libnymea-remoteproxy/tunnelconnection.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "tunnelconnection.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
|
||||
TunnelConnection::TunnelConnection(ProxyClient *clientOne, ProxyClient *clientTwo):
|
||||
m_clientOne(clientOne),
|
||||
m_clientTwo(clientTwo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString TunnelConnection::token() const
|
||||
{
|
||||
if (!isValid())
|
||||
return QString();
|
||||
|
||||
return m_clientOne->token();
|
||||
}
|
||||
|
||||
ProxyClient *TunnelConnection::clientOne() const
|
||||
{
|
||||
return m_clientOne;
|
||||
}
|
||||
|
||||
ProxyClient *TunnelConnection::clientTwo() const
|
||||
{
|
||||
return m_clientTwo;
|
||||
}
|
||||
|
||||
bool TunnelConnection::isValid() const
|
||||
{
|
||||
// Both clients have to be valid
|
||||
if (!m_clientOne || !m_clientTwo)
|
||||
return false;
|
||||
|
||||
// Both clients need the same token
|
||||
if (m_clientOne->token() != m_clientTwo->token())
|
||||
return false;
|
||||
|
||||
// The clients need to be different
|
||||
if (m_clientOne == m_clientTwo)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
28
libnymea-remoteproxy/tunnelconnection.h
Normal file
28
libnymea-remoteproxy/tunnelconnection.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef TUNNELCONNECTION_H
|
||||
#define TUNNELCONNECTION_H
|
||||
|
||||
#include "proxyclient.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
|
||||
class TunnelConnection
|
||||
{
|
||||
public:
|
||||
TunnelConnection(ProxyClient *clientOne = nullptr, ProxyClient *clientTwo = nullptr);
|
||||
|
||||
QString token() const;
|
||||
|
||||
ProxyClient *clientOne() const;
|
||||
ProxyClient *clientTwo() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
ProxyClient *m_clientOne = nullptr;
|
||||
ProxyClient *m_clientTwo = nullptr;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TUNNELCONNECTION_H
|
||||
@ -82,10 +82,17 @@ void JsonRpcClient::processData(const QByteArray &data)
|
||||
if (dataMap.contains("notification")) {
|
||||
QStringList notification = dataMap.value("notification").toString().split(".");
|
||||
QString nameSpace = notification.first();
|
||||
QString notificationName = notification.last();
|
||||
QVariantMap notificationParams = dataMap.value("params").toMap();
|
||||
|
||||
qCDebug(dcRemoteProxyClientJsonRpc()) << "Notification received" << nameSpace << notification;
|
||||
qCDebug(dcRemoteProxyClientJsonRpc()) << "Notification received" << nameSpace << notificationName;
|
||||
|
||||
if (nameSpace == "ProxyServer" && notificationName == "TunnelEstablished") {
|
||||
QString clientName = notificationParams.value("name").toString();
|
||||
QString clientUuid = notificationParams.value("uuid").toString();
|
||||
emit tunnelEstablished(clientName, clientUuid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ private:
|
||||
void sendRequest(const QVariantMap &request);
|
||||
|
||||
signals:
|
||||
void tunnelEstablished(const QString clientName, const QString &clientUuid);
|
||||
|
||||
public slots:
|
||||
void onConnectedChanged(bool connected);
|
||||
|
||||
@ -22,5 +22,4 @@ void ProxyConnection::setAllowSslErrors(bool allowSslErrors)
|
||||
m_allowSslErrors = allowSslErrors;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ RemoteProxyConnection::RemoteProxyConnection(const QUuid &clientUuid, const QStr
|
||||
|
||||
RemoteProxyConnection::~RemoteProxyConnection()
|
||||
{
|
||||
cleanUp();
|
||||
|
||||
}
|
||||
|
||||
RemoteProxyConnection::State RemoteProxyConnection::state() const
|
||||
@ -64,6 +64,12 @@ bool RemoteProxyConnection::isConnected() const
|
||||
|| m_state == StateRemoteConnected;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::isAuthenticated() const
|
||||
{
|
||||
return m_state == StateWaitTunnel
|
||||
|| m_state == StateRemoteConnected;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::isRemoteConnected() const
|
||||
{
|
||||
return m_state == StateRemoteConnected;
|
||||
@ -133,15 +139,21 @@ bool RemoteProxyConnection::sendData(const QByteArray &data)
|
||||
void RemoteProxyConnection::cleanUp()
|
||||
{
|
||||
if (m_jsonClient) {
|
||||
delete m_jsonClient;
|
||||
m_jsonClient->deleteLater();
|
||||
m_jsonClient = nullptr;
|
||||
}
|
||||
|
||||
if (m_connection) {
|
||||
delete m_connection;
|
||||
m_connection->deleteLater();
|
||||
m_connection = nullptr;
|
||||
}
|
||||
|
||||
m_error = ErrorNoError;
|
||||
m_serverName = QString();
|
||||
m_proxyServerName = QString();
|
||||
m_proxyServerVersion = QString();
|
||||
m_proxyServerApiVersion = QString();
|
||||
|
||||
setState(StateDisconnected);
|
||||
}
|
||||
|
||||
@ -167,16 +179,19 @@ void RemoteProxyConnection::setError(RemoteProxyConnection::Error error)
|
||||
|
||||
void RemoteProxyConnection::onConnectionChanged(bool isConnected)
|
||||
{
|
||||
if (!isConnected) {
|
||||
emit disconnected();
|
||||
cleanUp();
|
||||
} else {
|
||||
if (isConnected) {
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Connected from proxy server.";
|
||||
setState(StateConnected);
|
||||
emit connected();
|
||||
|
||||
setState(StateInitializing);
|
||||
JsonReply *reply = m_jsonClient->callHello();
|
||||
connect(reply, &JsonReply::finished, this, &RemoteProxyConnection::onHelloFinished);
|
||||
} else {
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Disconnected from proxy server.";
|
||||
emit disconnected();
|
||||
setState(StateDisconnected);
|
||||
cleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,6 +203,7 @@ void RemoteProxyConnection::onConnectionDataAvailable(const QByteArray &data)
|
||||
case StateInitializing:
|
||||
case StateReady:
|
||||
case StateAuthenticating:
|
||||
case StateWaitTunnel:
|
||||
m_jsonClient->processData(data);
|
||||
break;
|
||||
case StateRemoteConnected:
|
||||
@ -228,10 +244,10 @@ void RemoteProxyConnection::onHelloFinished()
|
||||
|
||||
// TODO: verify success
|
||||
|
||||
m_serverName = response.value("server").toString();
|
||||
m_proxyServerName = response.value("name").toString();
|
||||
m_proxyServerVersion = response.value("version").toString();
|
||||
m_proxyServerApiVersion = response.value("apiVersion").toString();
|
||||
m_serverName = responseParams.value("server").toString();
|
||||
m_proxyServerName = responseParams.value("name").toString();
|
||||
m_proxyServerVersion = responseParams.value("version").toString();
|
||||
m_proxyServerApiVersion = responseParams.value("apiVersion").toString();
|
||||
|
||||
setState(StateReady);
|
||||
emit ready();
|
||||
@ -242,6 +258,17 @@ void RemoteProxyConnection::onAuthenticateFinished()
|
||||
JsonReply *reply = static_cast<JsonReply *>(sender());
|
||||
QVariantMap response = reply->response();
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Authentication response ready" << response;
|
||||
|
||||
// TODO: verify success
|
||||
setState(StateWaitTunnel);
|
||||
emit authenticated();
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onTunnelEstablished(const QString &clientName, const QString &clientUuid)
|
||||
{
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "####### Remote connection established with" << clientName << clientUuid;
|
||||
setState(StateRemoteConnected);
|
||||
emit remoteConnectionEstablished();
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, quint16 port)
|
||||
@ -249,15 +276,7 @@ bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, qui
|
||||
m_serverAddress = serverAddress;
|
||||
m_serverPort = port;
|
||||
|
||||
if (m_connection) {
|
||||
delete m_connection;
|
||||
m_connection = nullptr;
|
||||
}
|
||||
|
||||
if (m_jsonClient) {
|
||||
delete m_jsonClient;
|
||||
m_jsonClient = nullptr;
|
||||
}
|
||||
cleanUp();
|
||||
|
||||
switch (m_connectionType) {
|
||||
case ConnectionTypeWebSocket:
|
||||
@ -272,6 +291,7 @@ bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, qui
|
||||
connect(m_connection, &ProxyConnection::sslErrorOccured, this, &RemoteProxyConnection::onConnectionSslError);
|
||||
|
||||
m_jsonClient = new JsonRpcClient(m_connection, this);
|
||||
connect(m_jsonClient, &JsonRpcClient::tunnelEstablished, this, &RemoteProxyConnection::onTunnelEstablished);
|
||||
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Connecting to" << m_connection->serverUrl().toString();
|
||||
m_connection->connectServer(serverAddress, port);
|
||||
@ -288,6 +308,8 @@ bool RemoteProxyConnection::authenticate(const QString &token)
|
||||
return false;
|
||||
}
|
||||
|
||||
setState(StateAuthenticating);
|
||||
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Start authentication using token" << token;
|
||||
JsonReply *reply = m_jsonClient->callAuthenticate(m_clientUuid, m_clientName, token);
|
||||
connect(reply, &JsonReply::finished, this, &RemoteProxyConnection::onAuthenticateFinished);
|
||||
@ -296,10 +318,10 @@ bool RemoteProxyConnection::authenticate(const QString &token)
|
||||
|
||||
void RemoteProxyConnection::disconnectServer()
|
||||
{
|
||||
if (m_connection)
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Disconnect from" << m_connection->serverUrl().toString();
|
||||
|
||||
cleanUp();
|
||||
if (m_connection) {
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Disconnecting from" << m_connection->serverUrl().toString();
|
||||
m_connection->disconnectServer();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ public:
|
||||
};
|
||||
Q_ENUM(Error)
|
||||
|
||||
explicit RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, ConnectionType connectionType = ConnectionTypeWebSocket, QObject *parent = nullptr);
|
||||
explicit RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, ConnectionType connectionType = RemoteProxyConnection::ConnectionTypeWebSocket, QObject *parent = nullptr);
|
||||
~RemoteProxyConnection();
|
||||
|
||||
RemoteProxyConnection::State state() const;
|
||||
@ -54,6 +54,7 @@ public:
|
||||
QString errorString() const;
|
||||
|
||||
bool isConnected() const;
|
||||
bool isAuthenticated() const;
|
||||
bool isRemoteConnected() const;
|
||||
|
||||
RemoteProxyConnection::ConnectionType connectionType() const;
|
||||
@ -100,9 +101,11 @@ private:
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void ready();
|
||||
void remoteConnectedChanged(bool remoteConnected);
|
||||
void authenticated();
|
||||
void remoteConnectionEstablished();
|
||||
void disconnected();
|
||||
|
||||
void stateChanged(RemoteProxyConnection::State state);
|
||||
void errorOccured(RemoteProxyConnection::Error error);
|
||||
|
||||
@ -116,6 +119,7 @@ private slots:
|
||||
|
||||
void onHelloFinished();
|
||||
void onAuthenticateFinished();
|
||||
void onTunnelEstablished(const QString &clientName, const QString &clientUuid);
|
||||
|
||||
public slots:
|
||||
bool connectServer(const QHostAddress &serverAddress, quint16 port);
|
||||
@ -126,8 +130,8 @@ public slots:
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::State);
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::Error);
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::State);
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::ConnectionType);
|
||||
|
||||
#endif // REMOTEPROXYCONNECTOR_H
|
||||
|
||||
@ -54,6 +54,7 @@ void WebSocketConnection::onDisconnected()
|
||||
void WebSocketConnection::onError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Socket error occured" << error << m_webSocket->errorString();
|
||||
emit errorOccured();
|
||||
}
|
||||
|
||||
void WebSocketConnection::onSslError(const QList<QSslError> &errors)
|
||||
@ -104,6 +105,9 @@ void WebSocketConnection::connectServer(const QHostAddress &address, quint16 por
|
||||
|
||||
void WebSocketConnection::disconnectServer()
|
||||
{
|
||||
if (!isConnected())
|
||||
return;
|
||||
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Disconnecting from" << serverUrl().toString();
|
||||
m_webSocket->close();
|
||||
}
|
||||
|
||||
@ -35,7 +35,6 @@ void MockAuthenticator::replyFinished()
|
||||
setReplyFinished(reply->authenticationReply());
|
||||
}
|
||||
|
||||
|
||||
AuthenticationReply *MockAuthenticator::authenticate(ProxyClient *proxyClient)
|
||||
{
|
||||
qCDebug(dcAuthenticator()) << name() << "Start authentication for" << proxyClient << "using token" << proxyClient->token();
|
||||
|
||||
@ -36,6 +36,20 @@ RemoteProxyTests::RemoteProxyTests(QObject *parent) :
|
||||
m_sslConfiguration.setLocalCertificate(QSslCertificate(certificateData, QSsl::Pem));
|
||||
m_sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
m_sslConfiguration.setProtocol(QSsl::TlsV1_2OrLater);
|
||||
|
||||
m_testToken = "eyJraWQiOiJXdnFFT3prVVh5VDlINzFyRUpoNWdxRnkxNFhnR2l3SFAzVEIzUFQ1V3ZrPSIsImFsZyI6IlJT"
|
||||
"MjU2In0.eyJzdWIiOiJmZTJmZDNlNC1hMGJhLTQ1OTUtOWRiZS00ZDkxYjRiMjFlMzUiLCJhdWQiOiI4cmpoZ"
|
||||
"mRsZjlqZjFzdW9rMmpjcmx0ZDZ2IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV2ZW50X2lkIjoiN2Y5NTRiNm"
|
||||
"ItOTYyZi0xMWU4LWI0ZjItMzU5NWRiZmRiODVmIiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE1MzM"
|
||||
"xOTkxMzgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5ldS13ZXN0LTEuYW1hem9uYXdzLmNvbVwvZXUt"
|
||||
"d2VzdC0xXzZlWDZZam1YciIsImNvZ25pdG86dXNlcm5hbWUiOiIyYzE3YzUwZC0xZDFlLTRhM2UtYmFjOS0zZ"
|
||||
"DI0YjQ1MTFiYWEiLCJleHAiOjE1MzMyMDI3MzgsImlhdCI6MTUzMzE5OTEzOCwiZW1haWwiOiJqZW5raW5zQG"
|
||||
"d1aC5pbyJ9.hMMSvZMx7pMvV70PaUmTZOZgdez5WGX5yagRFPZojBm8jNWZND1lUmi0RFkybeD4HonDiKHxTF"
|
||||
"_psyJoBVndgHbxYBBl3Np4gn0MxECWjvLxYzGxVBBkN24SqNUyAGkr0uFcZKkBecdtJlqNQnZN8Uk49twmODf"
|
||||
"raRaRmGmKmRBAK1qDITpUgP6AWqH9xoJWaoDzt0kwJ3EtPxS7vL1PHqOaN8ggXA8Eq4iTCSfXU1HAXhIWJH9Y"
|
||||
"pQbj58v1vktaAEATdmKmlzmcix-HJK9wWHRSuv3TsNa8DGxvcPOoeTu8Vql7krZ-y7Zu-s2WsgeP4VxyT80VE"
|
||||
"T_xh6pMkOhE6g";
|
||||
|
||||
}
|
||||
|
||||
void RemoteProxyTests::cleanUpEngine()
|
||||
@ -177,6 +191,8 @@ QVariant RemoteProxyTests::injectSocketData(const QByteArray &data)
|
||||
void RemoteProxyTests::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<RemoteProxyConnection::Error>();
|
||||
qRegisterMetaType<RemoteProxyConnection::State>();
|
||||
qRegisterMetaType<RemoteProxyConnection::ConnectionType>();
|
||||
|
||||
qCDebug(dcApplication()) << "Init test case.";
|
||||
restartEngine();
|
||||
@ -301,19 +317,19 @@ void RemoteProxyTests::authenticate_data()
|
||||
QTest::addColumn<int>("timeout");
|
||||
QTest::addColumn<Authenticator::AuthenticationError>("expectedError");
|
||||
|
||||
QTest::newRow("success") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << "Hh5JrkdFVstVVyCnfE3vVT3zG_JTacXEhPLZhCei"
|
||||
QTest::newRow("success") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 100 << Authenticator::AuthenticationErrorNoError;
|
||||
|
||||
QTest::newRow("failed") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << "invalid_token_42"
|
||||
QTest::newRow("failed") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 100 << Authenticator::AuthenticationErrorAuthenticationFailed;
|
||||
|
||||
QTest::newRow("not responding") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << "invalid_token_42"
|
||||
QTest::newRow("not responding") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 200 << Authenticator::AuthenticationErrorAuthenticationServerNotResponding;
|
||||
|
||||
QTest::newRow("aborted") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << "invalid_token_42"
|
||||
QTest::newRow("aborted") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 100 << Authenticator::AuthenticationErrorAborted;
|
||||
|
||||
QTest::newRow("unknown") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << "invalid_token_42"
|
||||
QTest::newRow("unknown") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 100 << Authenticator::AuthenticationErrorUnknown;
|
||||
|
||||
}
|
||||
@ -352,90 +368,189 @@ void RemoteProxyTests::clientConnection()
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
// Connect to the server (insecure disabled)
|
||||
RemoteProxyConnection *connectorOne = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||
connectorOne->setInsecureConnection(true);
|
||||
|
||||
// Connect to server (insecue enabled for testing)
|
||||
QSignalSpy readySpy(connectorOne, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectorOne->connectServer(QHostAddress::LocalHost, m_port));
|
||||
readySpy.wait();
|
||||
QVERIFY(readySpy.count() == 1);
|
||||
QVERIFY(connectorOne->isConnected());
|
||||
QVERIFY(connectorOne->state() == RemoteProxyConnection::StateReady);
|
||||
|
||||
// Authenticate
|
||||
// Configure moch authenticator
|
||||
m_authenticator->setTimeoutDuration(100);
|
||||
m_authenticator->setExpectedAuthenticationError();
|
||||
connectorOne->authenticate("foobar");
|
||||
|
||||
QTest::qWait(1000);
|
||||
// Connect to the server (insecure disabled)
|
||||
RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||
connection->setInsecureConnection(true);
|
||||
|
||||
// Connect to server (insecue enabled for testing)
|
||||
QSignalSpy readySpy(connection, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connection->connectServer(QHostAddress::LocalHost, m_port));
|
||||
readySpy.wait();
|
||||
QVERIFY(readySpy.count() == 1);
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(!connection->isRemoteConnected());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateReady);
|
||||
QVERIFY(connection->error() == RemoteProxyConnection::ErrorNoError);
|
||||
QVERIFY(connection->serverAddress() == QHostAddress::LocalHost);
|
||||
QVERIFY(connection->serverPort() == m_port);
|
||||
QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeWebSocket);
|
||||
QVERIFY(connection->insecureConnection() == true);
|
||||
QVERIFY(connection->serverName() == SERVER_NAME_STRING);
|
||||
QVERIFY(connection->proxyServerName() == Engine::instance()->serverName());
|
||||
QVERIFY(connection->proxyServerVersion() == SERVER_VERSION_STRING);
|
||||
QVERIFY(connection->proxyServerApiVersion() == API_VERSION_STRING);
|
||||
|
||||
QSignalSpy authenticatedSpy(connection, &RemoteProxyConnection::authenticated);
|
||||
QVERIFY(connection->authenticate("foobar"));
|
||||
authenticatedSpy.wait();
|
||||
QVERIFY(authenticatedSpy.count() == 1);
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(connection->isAuthenticated());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateWaitTunnel);
|
||||
|
||||
// Disconnect and clean up
|
||||
QSignalSpy spyDisconnected(connectorOne, &RemoteProxyConnection::disconnected);
|
||||
connectorOne->disconnectServer();
|
||||
spyDisconnected.wait();
|
||||
QVERIFY(!connectorOne->isConnected());
|
||||
QSignalSpy spyDisconnected(connection, &RemoteProxyConnection::disconnected);
|
||||
connection->disconnectServer();
|
||||
// FIXME: check why it waits the full time here
|
||||
spyDisconnected.wait(100);
|
||||
QVERIFY(spyDisconnected.count() == 1);
|
||||
QVERIFY(!connection->isConnected());
|
||||
|
||||
connectorOne->deleteLater();
|
||||
connection->deleteLater();
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyTests::remoteConnection()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
// Configure moch authenticator
|
||||
m_authenticator->setTimeoutDuration(100);
|
||||
m_authenticator->setExpectedAuthenticationError();
|
||||
|
||||
// Create two connection
|
||||
RemoteProxyConnection *connectionOne = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||
connectionOne->setInsecureConnection(true);
|
||||
|
||||
RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(QUuid::createUuid(), "Test client two", RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||
connectionTwo->setInsecureConnection(true);
|
||||
|
||||
// Connect one
|
||||
QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionOne->connectServer(QHostAddress::LocalHost, m_port));
|
||||
connectionOneReadySpy.wait();
|
||||
QVERIFY(connectionOneReadySpy.count() == 1);
|
||||
QVERIFY(connectionOne->isConnected());
|
||||
|
||||
// Connect two
|
||||
QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionTwo->connectServer(QHostAddress::LocalHost, m_port));
|
||||
connectionTwoReadySpy.wait();
|
||||
QVERIFY(connectionTwoReadySpy.count() == 1);
|
||||
QVERIFY(connectionTwo->isConnected());
|
||||
|
||||
// Authenticate one
|
||||
QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished);
|
||||
QSignalSpy connectionOneAuthenticatedSpy(connectionOne, &RemoteProxyConnection::authenticated);
|
||||
QVERIFY(connectionOne->authenticate(m_testToken));
|
||||
connectionOneAuthenticatedSpy.wait();
|
||||
QVERIFY(connectionOneAuthenticatedSpy.count() == 1);
|
||||
QVERIFY(connectionOne->isConnected());
|
||||
QVERIFY(connectionOne->isAuthenticated());
|
||||
QVERIFY(connectionOne->state() == RemoteProxyConnection::StateWaitTunnel);
|
||||
|
||||
// Authenticate two
|
||||
QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished);
|
||||
QSignalSpy connectionTwoAuthenticatedSpy(connectionTwo, &RemoteProxyConnection::authenticated);
|
||||
QVERIFY(connectionTwo->authenticate(m_testToken));
|
||||
connectionTwoAuthenticatedSpy.wait();
|
||||
QVERIFY(connectionTwoAuthenticatedSpy.count() == 1);
|
||||
QVERIFY(connectionTwo->isConnected());
|
||||
QVERIFY(connectionTwo->isAuthenticated());
|
||||
|
||||
// Wait for both to be connected
|
||||
remoteConnectionEstablishedOne.wait();
|
||||
remoteConnectionEstablishedTwo.wait();
|
||||
|
||||
QVERIFY(remoteConnectionEstablishedOne.count() == 1);
|
||||
QVERIFY(remoteConnectionEstablishedTwo.count() == 1);
|
||||
QVERIFY(connectionOne->state() == RemoteProxyConnection::StateRemoteConnected);
|
||||
QVERIFY(connectionTwo->state() == RemoteProxyConnection::StateRemoteConnected);
|
||||
|
||||
// Pipe data trought the tunnel
|
||||
QSignalSpy remoteConnectionDataOne(connectionOne, &RemoteProxyConnection::dataReady);
|
||||
QSignalSpy remoteConnectionDataTwo(connectionTwo, &RemoteProxyConnection::dataReady);
|
||||
|
||||
QByteArray dataOne = "Hello from client one :-)";
|
||||
QByteArray dataTwo = "Hello from client two :-)";
|
||||
|
||||
connectionOne->sendData(dataOne);
|
||||
remoteConnectionDataTwo.wait();
|
||||
QVERIFY(remoteConnectionDataTwo.count() == 1);
|
||||
|
||||
// verify if data is the same
|
||||
|
||||
connectionTwo->sendData(dataTwo);
|
||||
remoteConnectionDataOne.wait();
|
||||
QVERIFY(remoteConnectionDataOne.count() == 1);
|
||||
|
||||
// verify if data is the same
|
||||
|
||||
connectionOne->deleteLater();
|
||||
connectionTwo->deleteLater();
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyTests::sslConfigurations()
|
||||
{
|
||||
// // Start the server
|
||||
// startServer();
|
||||
// // Start the server
|
||||
// startServer();
|
||||
|
||||
// // Connect to the server (insecure disabled)
|
||||
// RemoteProxyConnection *connector = new RemoteProxyConnection(RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||
// connector->setInsecureConnection(false);
|
||||
// // Connect to the server (insecure disabled)
|
||||
// RemoteProxyConnection *connector = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeWebSocket, this);
|
||||
// QSignalSpy spyError(connector, &RemoteProxyConnection::errorOccured);
|
||||
// QVERIFY(connector->connectServer(QHostAddress::LocalHost, m_port));
|
||||
// spyError.wait();
|
||||
// QVERIFY(spyError.count() == 1);
|
||||
// QVERIFY(connector->error() == RemoteProxyConnection::ErrorSslError);
|
||||
// QVERIFY(connector->state() == RemoteProxyConnection::StateDisconnected);
|
||||
|
||||
// QSignalSpy spyError(connector, &RemoteProxyConnection::errorOccured);
|
||||
// connector->connectServer(QHostAddress::LocalHost, m_port);
|
||||
// spyError.wait();
|
||||
// // Connect to server (insecue enabled)
|
||||
// QSignalSpy spyConnected(connector, &RemoteProxyConnection::connected);
|
||||
// connector->setInsecureConnection(true);
|
||||
// connector->connectServer(QHostAddress::LocalHost, m_port);
|
||||
// spyConnected.wait();
|
||||
|
||||
// QCOMPARE(connector->error(), RemoteProxyConnection::ErrorSslError);
|
||||
// QCOMPARE(connector->state(), RemoteProxyConnection::StateDisconnected);
|
||||
// QVERIFY(connector->isConnected());
|
||||
|
||||
// // Connect to server (insecue enabled)
|
||||
// QSignalSpy spyConnected(connector, &RemoteProxyConnection::connected);
|
||||
// connector->setInsecureConnection(true);
|
||||
// connector->connectServer(QHostAddress::LocalHost, m_port);
|
||||
// spyConnected.wait();
|
||||
// // Disconnect and clean up
|
||||
// connector->disconnectServer();
|
||||
// QVERIFY(!connector->isConnected());
|
||||
|
||||
// QVERIFY(connector->isConnected());
|
||||
|
||||
// // Disconnect and clean up
|
||||
// connector->disconnectServer();
|
||||
// QVERIFY(!connector->isConnected());
|
||||
|
||||
// connector->deleteLater();
|
||||
// stopServer();
|
||||
// connector->deleteLater();
|
||||
// stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyTests::timeout()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
// // Start the server
|
||||
// startServer();
|
||||
|
||||
// Configure result
|
||||
// Start the server
|
||||
startServer();
|
||||
// // Configure result
|
||||
// // Start the server
|
||||
// startServer();
|
||||
|
||||
// Configure result
|
||||
m_authenticator->setExpectedAuthenticationError();
|
||||
m_authenticator->setTimeoutDuration(6000);
|
||||
// // Configure result
|
||||
// m_authenticator->setExpectedAuthenticationError();
|
||||
// m_authenticator->setTimeoutDuration(6000);
|
||||
|
||||
// Create request
|
||||
QVariantMap params;
|
||||
params.insert("uuid", "uuid");
|
||||
params.insert("name", "name");
|
||||
params.insert("token", "token");
|
||||
// // Create request
|
||||
// QVariantMap params;
|
||||
// params.insert("uuid", "uuid");
|
||||
// params.insert("name", "name");
|
||||
// params.insert("token", "token");
|
||||
|
||||
QVariant response = invokeApiCall("Authentication.Authenticate", params);
|
||||
qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
|
||||
// Clean up
|
||||
stopServer();
|
||||
// QVariant response = invokeApiCall("Authentication.Authenticate", params);
|
||||
// qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
|
||||
// // Clean up
|
||||
// stopServer();
|
||||
}
|
||||
|
||||
QTEST_MAIN(RemoteProxyTests)
|
||||
|
||||
@ -28,6 +28,7 @@ private:
|
||||
QHostAddress m_serverAddress = QHostAddress::LocalHost;
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
MockAuthenticator *m_authenticator = nullptr;
|
||||
QString m_testToken;
|
||||
|
||||
int m_commandCounter = 0;
|
||||
|
||||
@ -63,10 +64,11 @@ private slots:
|
||||
void authenticate();
|
||||
|
||||
// Client lib
|
||||
void clientConnection();
|
||||
void remoteConnection();
|
||||
void sslConfigurations();
|
||||
void timeout();
|
||||
|
||||
void clientConnection();
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
Reference in New Issue
Block a user