From 3b97bc60bbaf1ae5d4ced7eb1586d2d20fe5b0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 28 Aug 2018 09:58:57 +0200 Subject: [PATCH] Improve debug output and add tests --- .../dummy/dummyauthenticator.cpp | 2 +- libnymea-remoteproxy/proxyclient.cpp | 8 ++- libnymea-remoteproxy/proxyserver.cpp | 27 ++++---- libnymea-remoteproxy/proxyserver.h | 1 - libnymea-remoteproxy/tunnelconnection.cpp | 4 +- monitor/terminalwindow.cpp | 6 +- nymea-remoteproxy.pri | 2 +- .../nymea-remoteproxy-tests-offline.cpp | 64 ++++++++++++++++++- .../nymea-remoteproxy-tests-offline.h | 1 + tests/testbase/basetest.cpp | 1 + 10 files changed, 93 insertions(+), 23 deletions(-) diff --git a/libnymea-remoteproxy/authentication/dummy/dummyauthenticator.cpp b/libnymea-remoteproxy/authentication/dummy/dummyauthenticator.cpp index 7a397d7..4d08ccb 100644 --- a/libnymea-remoteproxy/authentication/dummy/dummyauthenticator.cpp +++ b/libnymea-remoteproxy/authentication/dummy/dummyauthenticator.cpp @@ -40,7 +40,7 @@ QString DummyAuthenticator::name() const AuthenticationReply *DummyAuthenticator::authenticate(ProxyClient *proxyClient) { qCDebug(dcAuthentication()) << name() << "validate" << proxyClient; - qCWarning(dcAuthentication()) << "Attention: This authenticator will always succeed! This is a security risk and was enabled explitly!"; + qCWarning(dcAuthentication()) << "Attention: This authenticator will always succeed! This is a security risk and was explicitly enabled!"; AuthenticationReply *reply = createAuthenticationReply(proxyClient, this); setReplyError(reply, AuthenticationErrorNoError); diff --git a/libnymea-remoteproxy/proxyclient.cpp b/libnymea-remoteproxy/proxyclient.cpp index 33673c0..404b1f6 100644 --- a/libnymea-remoteproxy/proxyclient.cpp +++ b/libnymea-remoteproxy/proxyclient.cpp @@ -141,9 +141,13 @@ void ProxyClient::killConnection(const QString &reason) QDebug operator<<(QDebug debug, ProxyClient *proxyClient) { - debug.nospace() << "ProxyClient(" << proxyClient->interface()->serverName(); + debug.nospace() << "ProxyClient("; + if (!proxyClient->name().isEmpty()) { + debug.nospace() << proxyClient->name() << ", "; + } + debug.nospace() << proxyClient->interface()->serverName(); debug.nospace() << ", " << proxyClient->clientId().toString(); - debug.nospace() << ", " << proxyClient->peerAddress().toString() << ") "; + debug.nospace() << ", " << proxyClient->peerAddress().toString(); debug.nospace() << ", " << proxyClient->creationTimeString() << ") "; return debug; } diff --git a/libnymea-remoteproxy/proxyserver.cpp b/libnymea-remoteproxy/proxyserver.cpp index 7c2f375..5cea8cf 100644 --- a/libnymea-remoteproxy/proxyserver.cpp +++ b/libnymea-remoteproxy/proxyserver.cpp @@ -128,9 +128,7 @@ void ProxyServer::sendResponse(TransportInterface *interface, const QUuid &clien void ProxyServer::establishTunnel(ProxyClient *firstClient, ProxyClient *secondClient) { - qCDebug(dcProxyServer()) << "Create tunnel between authenticated clients:"; - qCDebug(dcProxyServer()) << " -->" << firstClient << firstClient->name(); - qCDebug(dcProxyServer()) << " -->" << secondClient << secondClient->name(); + qCDebug(dcProxyServer()) << "Create tunnel between authenticated clients " << firstClient << secondClient; TunnelConnection tunnel(firstClient, secondClient); if (!tunnel.isValid()) { @@ -153,6 +151,8 @@ void ProxyServer::establishTunnel(ProxyClient *firstClient, ProxyClient *secondC firstClient->setTunnelConnected(true); secondClient->setTunnelConnected(true); + qCDebug(dcProxyServer()) << tunnel; + // Notify the clients in the next event loop QMetaObject::invokeMethod(m_jsonRpcServer, QString("sendNotification").toLatin1().data(), Qt::QueuedConnection, Q_ARG(QString, m_jsonRpcServer->name()), @@ -176,7 +176,6 @@ void ProxyServer::onClientConnected(const QUuid &clientId, const QHostAddress &a ProxyClient *proxyClient = new ProxyClient(interface, clientId, address, this); connect(proxyClient, &ProxyClient::authenticated, this, &ProxyServer::onProxyClientAuthenticated); - connect(proxyClient, &ProxyClient::tunnelConnected, this, &ProxyServer::onProxyClientTunnelConnected); connect(proxyClient, &ProxyClient::timeoutOccured, this, &ProxyServer::onProxyClientTimeoutOccured); m_proxyClients.insert(clientId, proxyClient); @@ -245,7 +244,7 @@ void ProxyServer::onClientDataAvailable(const QUuid &clientId, const QByteArray Q_ASSERT_X(remoteClient, "ProxyServer", "Tunnel existing but not tunnel client available"); Q_ASSERT_X(m_tunnels.contains(proxyClient->token()), "ProxyServer", "Tunnel connect but not existing"); - qCDebug(dcProxyServerTraffic()) << "Pipe data:"; + qCDebug(dcProxyServerTraffic()) << "Pipe tunnel data:"; qCDebug(dcProxyServerTraffic()) << " --> from" << proxyClient; qCDebug(dcProxyServerTraffic()) << " --> to" << remoteClient; qCDebug(dcProxyServerTraffic()) << " --> data:" << qUtf8Printable(data); @@ -259,8 +258,6 @@ void ProxyServer::onProxyClientAuthenticated() ProxyClient *proxyClient = static_cast(sender()); qCDebug(dcProxyServer()) << "Client authenticated" << proxyClient; - qCDebug(dcProxyServer()) << " name:" << proxyClient->name(); - qCDebug(dcProxyServer()) << " uuid:" << proxyClient->uuid(); if (m_tunnels.contains(proxyClient->token())) { qCWarning(dcProxyServer()) << "There is already a tunnel connection for this token. A third client is not allowed."; @@ -275,18 +272,24 @@ void ProxyServer::onProxyClientAuthenticated() if (m_authenticatedClients.keys().contains(proxyClient->token())) { // Found a client with this token ProxyClient *tunnelEnd = m_authenticatedClients.take(proxyClient->token()); + + // Check if the two clients show up with the same uuid + if (tunnelEnd->uuid() == proxyClient->uuid()) { + qCWarning(dcProxyServer()) << "The clients have the same uuid. This is not allowed."; + proxyClient->killConnection("Duplicated client UUID."); + tunnelEnd->killConnection("Duplicated client UUID."); + return; + } + + // All ok so far. Create the tunnel establishTunnel(tunnelEnd, proxyClient); + } else { // Append and wait for the other client m_authenticatedClients.insert(proxyClient->token(), proxyClient); } } -void ProxyServer::onProxyClientTunnelConnected() -{ - -} - void ProxyServer::onProxyClientTimeoutOccured() { ProxyClient *proxyClient = static_cast(sender()); diff --git a/libnymea-remoteproxy/proxyserver.h b/libnymea-remoteproxy/proxyserver.h index d90674c..d99408c 100644 --- a/libnymea-remoteproxy/proxyserver.h +++ b/libnymea-remoteproxy/proxyserver.h @@ -76,7 +76,6 @@ private slots: void onClientDataAvailable(const QUuid &clientId, const QByteArray &data); void onProxyClientAuthenticated(); - void onProxyClientTunnelConnected(); void onProxyClientTimeoutOccured(); public slots: diff --git a/libnymea-remoteproxy/tunnelconnection.cpp b/libnymea-remoteproxy/tunnelconnection.cpp index 1ea6340..8a76986 100644 --- a/libnymea-remoteproxy/tunnelconnection.cpp +++ b/libnymea-remoteproxy/tunnelconnection.cpp @@ -80,8 +80,8 @@ bool TunnelConnection::isValid() const QDebug operator<<(QDebug debug, const TunnelConnection &tunnel) { debug.nospace() << "TunnelConnection(" << tunnel.creationTimeString() << ")" << endl; - debug.nospace() << " client:" << tunnel.clientOne() << endl; - debug.nospace() << " client:" << tunnel.clientTwo() << endl; + debug.nospace() << " --> " << tunnel.clientOne() << endl; + debug.nospace() << " --> " << tunnel.clientTwo() << endl; return debug; } diff --git a/monitor/terminalwindow.cpp b/monitor/terminalwindow.cpp index 1ffa011..6787a4a 100644 --- a/monitor/terminalwindow.cpp +++ b/monitor/terminalwindow.cpp @@ -182,7 +182,7 @@ void TerminalWindow::paintContentClients() QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 | %7") .arg(clientConnectionTime) .arg(clientMap.value("duration").toString()) - .arg(clientMap.value("address").toString()) + .arg(clientMap.value("address").toString(), - 16) .arg(clientMap.value("uuid").toString()) .arg((clientMap.value("authenticated").toBool() ? "A" : "-")) .arg((clientMap.value("tunnelConnected").toBool() ? "T" : "-")) @@ -211,10 +211,10 @@ void TerminalWindow::paintContentTunnels() QString tunnelPrint = QString("%1 | %2 %3 %4 %5 %6") .arg(tunnelConnectionTime) - .arg(clientOne.value("address").toString()) + .arg(clientOne.value("address").toString(), - 16) .arg(clientOne.value("name").toString()) .arg(" <---> ") - .arg(clientTwo.value("address").toString()) + .arg(clientTwo.value("address").toString(), - 16) .arg(clientTwo.value("name").toString()) ; diff --git a/nymea-remoteproxy.pri b/nymea-remoteproxy.pri index 92f544e..255f287 100644 --- a/nymea-remoteproxy.pri +++ b/nymea-remoteproxy.pri @@ -5,7 +5,7 @@ QT -= gui SERVER_NAME=nymea-remoteproxy API_VERSION_MAJOR=0 API_VERSION_MINOR=2 -SERVER_VERSION=0.1.3 +SERVER_VERSION=0.1.4 DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \ SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \ diff --git a/tests/test-offline/nymea-remoteproxy-tests-offline.cpp b/tests/test-offline/nymea-remoteproxy-tests-offline.cpp index 725fc93..f463f43 100644 --- a/tests/test-offline/nymea-remoteproxy-tests-offline.cpp +++ b/tests/test-offline/nymea-remoteproxy-tests-offline.cpp @@ -49,6 +49,7 @@ void RemoteProxyOfflineTests::dummyAuthenticator() // Start proxy webserver Engine::instance()->setAuthenticator(m_dummyAuthenticator); + Engine::instance()->setAuthenticator(m_dummyAuthenticator); QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged); Engine::instance()->start(m_configuration); runningSpy.wait(); @@ -397,7 +398,6 @@ void RemoteProxyOfflineTests::remoteConnection() QByteArray dataOne = "Hello from client one :-)"; QByteArray dataTwo = "Hello from client two :-)"; - // Create two connection RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, this); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); @@ -553,6 +553,68 @@ void RemoteProxyOfflineTests::trippleConnection() stopServer(); } +void RemoteProxyOfflineTests::duplicateUuid() +{ + // Start the server + startServer(); + + // Configure moch authenticator + m_mockAuthenticator->setTimeoutDuration(100); + m_mockAuthenticator->setExpectedAuthenticationError(); + + QUuid connectionUuid = QUuid::createUuid(); + + QString nameConnectionOne = "Test client one"; + QString nameConnectionTwo = "Test client two"; + + // Create two connection + RemoteProxyConnection *connectionOne = new RemoteProxyConnection(connectionUuid, nameConnectionOne, this); + connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); + + RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(connectionUuid, nameConnectionTwo, this); + connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); + + // Connect one + QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready); + QVERIFY(connectionOne->connectServer(m_serverUrl)); + connectionOneReadySpy.wait(); + QVERIFY(connectionOneReadySpy.count() == 1); + QVERIFY(connectionOne->isConnected()); + + // Connect two + QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready); + QVERIFY(connectionTwo->connectServer(m_serverUrl)); + connectionTwoReadySpy.wait(); + QVERIFY(connectionTwoReadySpy.count() == 1); + QVERIFY(connectionTwo->isConnected()); + + // Authenticate one + 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::StateAuthenticated); + + // Authenticate two + QSignalSpy disconnectSpyOne(connectionOne, &RemoteProxyConnection::disconnected); + QSignalSpy disconnectSpyTwo(connectionTwo, &RemoteProxyConnection::disconnected); + + QVERIFY(connectionTwo->authenticate(m_testToken)); + disconnectSpyOne.wait(); + QVERIFY(disconnectSpyOne.count() >= 1); + + disconnectSpyTwo.wait(); + QVERIFY(disconnectSpyTwo.count() >= 1); + + connectionOne->deleteLater(); + connectionTwo->deleteLater(); + + // Clean up + stopServer(); +} + void RemoteProxyOfflineTests::sslConfigurations() { // Start the server diff --git a/tests/test-offline/nymea-remoteproxy-tests-offline.h b/tests/test-offline/nymea-remoteproxy-tests-offline.h index f996e70..bbf5384 100644 --- a/tests/test-offline/nymea-remoteproxy-tests-offline.h +++ b/tests/test-offline/nymea-remoteproxy-tests-offline.h @@ -62,6 +62,7 @@ private slots: void clientConnection(); void remoteConnection(); void trippleConnection(); + void duplicateUuid(); void sslConfigurations(); void jsonRpcTimeout(); diff --git a/tests/testbase/basetest.cpp b/tests/testbase/basetest.cpp index e73bb15..e018785 100644 --- a/tests/testbase/basetest.cpp +++ b/tests/testbase/basetest.cpp @@ -81,6 +81,7 @@ void BaseTest::startServer() } QVERIFY(Engine::instance()->running()); + QVERIFY(Engine::instance()->developerMode()); QVERIFY(Engine::instance()->webSocketServer()->running()); QVERIFY(Engine::instance()->monitorServer()->running()); }