Improve debug output and add tests

This commit is contained in:
Simon Stürz 2018-08-28 09:58:57 +02:00
parent d356a39958
commit 3b97bc60bb
10 changed files with 93 additions and 23 deletions

View File

@ -40,7 +40,7 @@ QString DummyAuthenticator::name() const
AuthenticationReply *DummyAuthenticator::authenticate(ProxyClient *proxyClient) AuthenticationReply *DummyAuthenticator::authenticate(ProxyClient *proxyClient)
{ {
qCDebug(dcAuthentication()) << name() << "validate" << 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); AuthenticationReply *reply = createAuthenticationReply(proxyClient, this);
setReplyError(reply, AuthenticationErrorNoError); setReplyError(reply, AuthenticationErrorNoError);

View File

@ -141,9 +141,13 @@ void ProxyClient::killConnection(const QString &reason)
QDebug operator<<(QDebug debug, ProxyClient *proxyClient) 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->clientId().toString();
debug.nospace() << ", " << proxyClient->peerAddress().toString() << ") "; debug.nospace() << ", " << proxyClient->peerAddress().toString();
debug.nospace() << ", " << proxyClient->creationTimeString() << ") "; debug.nospace() << ", " << proxyClient->creationTimeString() << ") ";
return debug; return debug;
} }

View File

@ -128,9 +128,7 @@ void ProxyServer::sendResponse(TransportInterface *interface, const QUuid &clien
void ProxyServer::establishTunnel(ProxyClient *firstClient, ProxyClient *secondClient) void ProxyServer::establishTunnel(ProxyClient *firstClient, ProxyClient *secondClient)
{ {
qCDebug(dcProxyServer()) << "Create tunnel between authenticated clients:"; qCDebug(dcProxyServer()) << "Create tunnel between authenticated clients " << firstClient << secondClient;
qCDebug(dcProxyServer()) << " -->" << firstClient << firstClient->name();
qCDebug(dcProxyServer()) << " -->" << secondClient << secondClient->name();
TunnelConnection tunnel(firstClient, secondClient); TunnelConnection tunnel(firstClient, secondClient);
if (!tunnel.isValid()) { if (!tunnel.isValid()) {
@ -153,6 +151,8 @@ void ProxyServer::establishTunnel(ProxyClient *firstClient, ProxyClient *secondC
firstClient->setTunnelConnected(true); firstClient->setTunnelConnected(true);
secondClient->setTunnelConnected(true); secondClient->setTunnelConnected(true);
qCDebug(dcProxyServer()) << tunnel;
// Notify the clients in the next event loop // Notify the clients in the next event loop
QMetaObject::invokeMethod(m_jsonRpcServer, QString("sendNotification").toLatin1().data(), Qt::QueuedConnection, QMetaObject::invokeMethod(m_jsonRpcServer, QString("sendNotification").toLatin1().data(), Qt::QueuedConnection,
Q_ARG(QString, m_jsonRpcServer->name()), 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); ProxyClient *proxyClient = new ProxyClient(interface, clientId, address, this);
connect(proxyClient, &ProxyClient::authenticated, this, &ProxyServer::onProxyClientAuthenticated); connect(proxyClient, &ProxyClient::authenticated, this, &ProxyServer::onProxyClientAuthenticated);
connect(proxyClient, &ProxyClient::tunnelConnected, this, &ProxyServer::onProxyClientTunnelConnected);
connect(proxyClient, &ProxyClient::timeoutOccured, this, &ProxyServer::onProxyClientTimeoutOccured); connect(proxyClient, &ProxyClient::timeoutOccured, this, &ProxyServer::onProxyClientTimeoutOccured);
m_proxyClients.insert(clientId, proxyClient); 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(remoteClient, "ProxyServer", "Tunnel existing but not tunnel client available");
Q_ASSERT_X(m_tunnels.contains(proxyClient->token()), "ProxyServer", "Tunnel connect but not existing"); 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()) << " --> from" << proxyClient;
qCDebug(dcProxyServerTraffic()) << " --> to" << remoteClient; qCDebug(dcProxyServerTraffic()) << " --> to" << remoteClient;
qCDebug(dcProxyServerTraffic()) << " --> data:" << qUtf8Printable(data); qCDebug(dcProxyServerTraffic()) << " --> data:" << qUtf8Printable(data);
@ -259,8 +258,6 @@ void ProxyServer::onProxyClientAuthenticated()
ProxyClient *proxyClient = static_cast<ProxyClient *>(sender()); ProxyClient *proxyClient = static_cast<ProxyClient *>(sender());
qCDebug(dcProxyServer()) << "Client authenticated" << proxyClient; qCDebug(dcProxyServer()) << "Client authenticated" << proxyClient;
qCDebug(dcProxyServer()) << " name:" << proxyClient->name();
qCDebug(dcProxyServer()) << " uuid:" << proxyClient->uuid();
if (m_tunnels.contains(proxyClient->token())) { if (m_tunnels.contains(proxyClient->token())) {
qCWarning(dcProxyServer()) << "There is already a tunnel connection for this token. A third client is not allowed."; 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())) { if (m_authenticatedClients.keys().contains(proxyClient->token())) {
// Found a client with this token // Found a client with this token
ProxyClient *tunnelEnd = m_authenticatedClients.take(proxyClient->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); establishTunnel(tunnelEnd, proxyClient);
} else { } else {
// Append and wait for the other client // Append and wait for the other client
m_authenticatedClients.insert(proxyClient->token(), proxyClient); m_authenticatedClients.insert(proxyClient->token(), proxyClient);
} }
} }
void ProxyServer::onProxyClientTunnelConnected()
{
}
void ProxyServer::onProxyClientTimeoutOccured() void ProxyServer::onProxyClientTimeoutOccured()
{ {
ProxyClient *proxyClient = static_cast<ProxyClient *>(sender()); ProxyClient *proxyClient = static_cast<ProxyClient *>(sender());

View File

@ -76,7 +76,6 @@ private slots:
void onClientDataAvailable(const QUuid &clientId, const QByteArray &data); void onClientDataAvailable(const QUuid &clientId, const QByteArray &data);
void onProxyClientAuthenticated(); void onProxyClientAuthenticated();
void onProxyClientTunnelConnected();
void onProxyClientTimeoutOccured(); void onProxyClientTimeoutOccured();
public slots: public slots:

View File

@ -80,8 +80,8 @@ bool TunnelConnection::isValid() const
QDebug operator<<(QDebug debug, const TunnelConnection &tunnel) QDebug operator<<(QDebug debug, const TunnelConnection &tunnel)
{ {
debug.nospace() << "TunnelConnection(" << tunnel.creationTimeString() << ")" << endl; debug.nospace() << "TunnelConnection(" << tunnel.creationTimeString() << ")" << endl;
debug.nospace() << " client:" << tunnel.clientOne() << endl; debug.nospace() << " --> " << tunnel.clientOne() << endl;
debug.nospace() << " client:" << tunnel.clientTwo() << endl; debug.nospace() << " --> " << tunnel.clientTwo() << endl;
return debug; return debug;
} }

View File

@ -182,7 +182,7 @@ void TerminalWindow::paintContentClients()
QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 | %7") QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 | %7")
.arg(clientConnectionTime) .arg(clientConnectionTime)
.arg(clientMap.value("duration").toString()) .arg(clientMap.value("duration").toString())
.arg(clientMap.value("address").toString()) .arg(clientMap.value("address").toString(), - 16)
.arg(clientMap.value("uuid").toString()) .arg(clientMap.value("uuid").toString())
.arg((clientMap.value("authenticated").toBool() ? "A" : "-")) .arg((clientMap.value("authenticated").toBool() ? "A" : "-"))
.arg((clientMap.value("tunnelConnected").toBool() ? "T" : "-")) .arg((clientMap.value("tunnelConnected").toBool() ? "T" : "-"))
@ -211,10 +211,10 @@ void TerminalWindow::paintContentTunnels()
QString tunnelPrint = QString("%1 | %2 %3 %4 %5 %6") QString tunnelPrint = QString("%1 | %2 %3 %4 %5 %6")
.arg(tunnelConnectionTime) .arg(tunnelConnectionTime)
.arg(clientOne.value("address").toString()) .arg(clientOne.value("address").toString(), - 16)
.arg(clientOne.value("name").toString()) .arg(clientOne.value("name").toString())
.arg(" <---> ") .arg(" <---> ")
.arg(clientTwo.value("address").toString()) .arg(clientTwo.value("address").toString(), - 16)
.arg(clientTwo.value("name").toString()) .arg(clientTwo.value("name").toString())
; ;

View File

@ -5,7 +5,7 @@ QT -= gui
SERVER_NAME=nymea-remoteproxy SERVER_NAME=nymea-remoteproxy
API_VERSION_MAJOR=0 API_VERSION_MAJOR=0
API_VERSION_MINOR=2 API_VERSION_MINOR=2
SERVER_VERSION=0.1.3 SERVER_VERSION=0.1.4
DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \ DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \
SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \ SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \

View File

@ -49,6 +49,7 @@ void RemoteProxyOfflineTests::dummyAuthenticator()
// Start proxy webserver // Start proxy webserver
Engine::instance()->setAuthenticator(m_dummyAuthenticator); Engine::instance()->setAuthenticator(m_dummyAuthenticator);
Engine::instance()->setAuthenticator(m_dummyAuthenticator);
QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged); QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged);
Engine::instance()->start(m_configuration); Engine::instance()->start(m_configuration);
runningSpy.wait(); runningSpy.wait();
@ -397,7 +398,6 @@ void RemoteProxyOfflineTests::remoteConnection()
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, this); RemoteProxyConnection *connectionOne = new RemoteProxyConnection(uuidConnectionOne, nameConnectionOne, this);
connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError); connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
@ -553,6 +553,68 @@ void RemoteProxyOfflineTests::trippleConnection()
stopServer(); 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() void RemoteProxyOfflineTests::sslConfigurations()
{ {
// Start the server // Start the server

View File

@ -62,6 +62,7 @@ private slots:
void clientConnection(); void clientConnection();
void remoteConnection(); void remoteConnection();
void trippleConnection(); void trippleConnection();
void duplicateUuid();
void sslConfigurations(); void sslConfigurations();
void jsonRpcTimeout(); void jsonRpcTimeout();

View File

@ -81,6 +81,7 @@ void BaseTest::startServer()
} }
QVERIFY(Engine::instance()->running()); QVERIFY(Engine::instance()->running());
QVERIFY(Engine::instance()->developerMode());
QVERIFY(Engine::instance()->webSocketServer()->running()); QVERIFY(Engine::instance()->webSocketServer()->running());
QVERIFY(Engine::instance()->monitorServer()->running()); QVERIFY(Engine::instance()->monitorServer()->running());
} }