Add timing configurations and timeout tests
This commit is contained in:
parent
f28ac0f4e3
commit
13572ad219
1
.gitignore
vendored
1
.gitignore
vendored
@ -78,3 +78,4 @@ tests/test-offline/nymea-remoteproxy-tests-offline
|
||||
tests/test-online/nymea-remoteproxy-tests-online
|
||||
.crossbuilder/
|
||||
source_repository/
|
||||
*.gcno
|
||||
|
||||
@ -51,9 +51,9 @@ void ProxyClient::setPingpong(bool enable)
|
||||
m_pingpong = enable;
|
||||
}
|
||||
|
||||
void ProxyClient::onErrorOccured(RemoteProxyConnection::Error error)
|
||||
void ProxyClient::onErrorOccured(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qCWarning(dcProxyClient()) << "Error occured" << error << m_connection->errorString();
|
||||
qCWarning(dcProxyClient()) << "Error occured" << error;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ private:
|
||||
RemoteProxyConnection *m_connection = nullptr;
|
||||
|
||||
private slots:
|
||||
void onErrorOccured(RemoteProxyConnection::Error error);
|
||||
void onErrorOccured(QAbstractSocket::SocketError error);
|
||||
void onClientReady();
|
||||
void onAuthenticationFinished();
|
||||
void onRemoteConnectionEstablished();
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/libnymea-remoteproxy:$(pwd)/libnymea-remoteproxyclient
|
||||
|
||||
# Build
|
||||
qmake CONFIG+=coverage
|
||||
qmake CONFIG+=coverage CONFIG+=ccache
|
||||
make -j$(nproc)
|
||||
#make check
|
||||
make coverage-html
|
||||
|
||||
# Clean build
|
||||
@ -28,8 +29,8 @@ rm -v tests/Makefile
|
||||
rm -v tests/test-offline/nymea-remoteproxy-tests-offline
|
||||
rm -v tests/test-offline/Makefile
|
||||
|
||||
rm -v tests/test-online/nymea-remoteproxy-tests-online
|
||||
rm -v tests/test-online/Makefile
|
||||
#rm -v tests/test-online/nymea-remoteproxy-tests-online
|
||||
#rm -v tests/test-online/Makefile
|
||||
|
||||
rm -v client/nymea-remoteproxy-client
|
||||
rm -v client/Makefile
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "engine.h"
|
||||
#include "authenticationreply.h"
|
||||
#include "authentication/authenticator.h"
|
||||
|
||||
@ -28,11 +29,12 @@ AuthenticationReply::AuthenticationReply(ProxyClient *proxyClient, QObject *pare
|
||||
QObject(parent),
|
||||
m_proxyClient(proxyClient)
|
||||
{
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setInterval(10000);
|
||||
m_timer->setSingleShot(true);
|
||||
m_timer.setSingleShot(true);
|
||||
connect(&m_timer, &QTimer::timeout, this, &AuthenticationReply::onTimeout);
|
||||
|
||||
m_process = new QProcess(this);
|
||||
|
||||
m_timer.start(Engine::instance()->configuration()->authenticationTimeout());
|
||||
}
|
||||
|
||||
ProxyClient *AuthenticationReply::proxyClient() const
|
||||
@ -62,7 +64,7 @@ void AuthenticationReply::setError(Authenticator::AuthenticationError error)
|
||||
|
||||
void AuthenticationReply::setFinished()
|
||||
{
|
||||
m_timer->stop();
|
||||
m_timer.stop();
|
||||
// emit in next event loop
|
||||
QTimer::singleShot(0, this, &AuthenticationReply::finished);
|
||||
}
|
||||
@ -71,7 +73,7 @@ void AuthenticationReply::onTimeout()
|
||||
{
|
||||
m_timedOut = true;
|
||||
m_error = Authenticator::AuthenticationErrorTimeout;
|
||||
m_timer->stop();
|
||||
m_timer.stop();
|
||||
m_process->kill();
|
||||
QTimer::singleShot(0, this, &AuthenticationReply::finished);
|
||||
}
|
||||
@ -79,7 +81,7 @@ void AuthenticationReply::onTimeout()
|
||||
void AuthenticationReply::abort()
|
||||
{
|
||||
m_error = Authenticator::AuthenticationErrorAborted;
|
||||
m_timer->stop();
|
||||
m_timer.stop();
|
||||
m_process->kill();
|
||||
QTimer::singleShot(0, this, &AuthenticationReply::finished);
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public:
|
||||
private:
|
||||
explicit AuthenticationReply(ProxyClient *proxyClient, QObject *parent = nullptr);
|
||||
ProxyClient *m_proxyClient = nullptr;
|
||||
QTimer *m_timer = nullptr;
|
||||
QTimer m_timer;
|
||||
QProcess *m_process = nullptr;
|
||||
|
||||
bool m_timedOut = false;
|
||||
|
||||
@ -78,11 +78,9 @@ JsonReply *AuthenticationHandler::Authenticate(const QVariantMap ¶ms, ProxyC
|
||||
void AuthenticationHandler::onAuthenticationFinished()
|
||||
{
|
||||
AuthenticationReply *authenticationReply = static_cast<AuthenticationReply *>(sender());
|
||||
JsonReply *jsonReply = m_runningAuthentications.take(authenticationReply);
|
||||
|
||||
authenticationReply->deleteLater();
|
||||
|
||||
qCDebug(dcJsonRpc()) << "Authentication respons ready for" << authenticationReply->proxyClient() << authenticationReply->error();
|
||||
JsonReply *jsonReply = m_runningAuthentications.take(authenticationReply);
|
||||
|
||||
if (authenticationReply->error() != Authenticator::AuthenticationErrorNoError) {
|
||||
qCWarning(dcJsonRpc()) << "Authentication error occured" << authenticationReply->error();
|
||||
@ -91,12 +89,13 @@ void AuthenticationHandler::onAuthenticationFinished()
|
||||
// Successfully authenticated
|
||||
jsonReply->setSuccess(true);
|
||||
}
|
||||
|
||||
jsonReply->setData(errorToReply(authenticationReply->error()));
|
||||
jsonReply->finished();
|
||||
|
||||
// Set client authenticated
|
||||
authenticationReply->proxyClient()->setAuthenticated(authenticationReply->error() == Authenticator::AuthenticationErrorNoError);
|
||||
authenticationReply->deleteLater();
|
||||
|
||||
jsonReply->setData(errorToReply(authenticationReply->error()));
|
||||
jsonReply->finished();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "engine.h"
|
||||
#include "jsonreply.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
@ -95,7 +96,7 @@ bool JsonReply::timedOut() const
|
||||
|
||||
void JsonReply::startWait()
|
||||
{
|
||||
m_timeout.start(5000);
|
||||
m_timeout.start(Engine::instance()->configuration()->jsonRpcTimeout());
|
||||
}
|
||||
|
||||
void JsonReply::timeout()
|
||||
|
||||
@ -130,7 +130,7 @@ void JsonRpcServer::sendResponse(ProxyClient *client, int commandId, const QVari
|
||||
|
||||
QByteArray data = QJsonDocument::fromVariant(response).toJson(QJsonDocument::Compact);
|
||||
qCDebug(dcJsonRpcTraffic()) << "Sending data:" << data;
|
||||
client->interface()->sendData(client->clientId(), data);
|
||||
client->sendData(data);
|
||||
}
|
||||
|
||||
void JsonRpcServer::sendErrorResponse(ProxyClient *client, int commandId, const QString &error)
|
||||
@ -176,10 +176,11 @@ void JsonRpcServer::setup()
|
||||
void JsonRpcServer::asyncReplyFinished()
|
||||
{
|
||||
JsonReply *reply = static_cast<JsonReply *>(sender());
|
||||
ProxyClient *proxyClient = m_asyncReplies.take(reply);
|
||||
|
||||
reply->deleteLater();
|
||||
|
||||
ProxyClient *proxyClient = m_asyncReplies.take(reply);
|
||||
qCDebug(dcJsonRpc()) << "Async reply finished" << reply->handler()->name() << reply->method() << reply->clientId().toString();
|
||||
|
||||
if (!proxyClient) {
|
||||
qCWarning(dcJsonRpc()) << "Got an async reply but the client does not exist any more";
|
||||
return;
|
||||
@ -197,7 +198,7 @@ void JsonRpcServer::asyncReplyFinished()
|
||||
} else {
|
||||
sendErrorResponse(proxyClient, reply->commandId(), "Command timed out");
|
||||
// Disconnect this client since he requested something that created a timeout
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "API call timeouted.");
|
||||
proxyClient->killConnection("API call timeouted.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +236,7 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcJsonRpc) << "Failed to parse JSON data" << data << ":" << error.errorString();
|
||||
sendErrorResponse(proxyClient, -1, QString("Failed to parse JSON data: %1").arg(error.errorString()));
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Invalid JSON data received.");
|
||||
proxyClient->killConnection("Invalid JSON data received.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -246,7 +247,7 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
|
||||
if (!success) {
|
||||
qCWarning(dcJsonRpc()) << "Error parsing command. Missing \"id\":" << message;
|
||||
sendErrorResponse(proxyClient, -1, "Error parsing command. Missing 'id'");
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "The id property is missing in the request.");
|
||||
proxyClient->killConnection("The id property is missing in the request.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -254,7 +255,7 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
|
||||
if (commandList.count() != 2) {
|
||||
qCWarning(dcJsonRpc) << "Error parsing method.\nGot:" << message.value("method").toString() << "\nExpected: \"Namespace.method\"";
|
||||
sendErrorResponse(proxyClient, commandId, QString("Error parsing method. Got: '%1'', Expected: 'Namespace.method'").arg(message.value("method").toString()));
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Invalid method passed.");
|
||||
proxyClient->killConnection("Invalid method passed.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -264,22 +265,21 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
|
||||
JsonHandler *handler = m_handlers.value(targetNamespace);
|
||||
if (!handler) {
|
||||
sendErrorResponse(proxyClient, commandId, "No such namespace");
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "No such namespace.");
|
||||
proxyClient->killConnection("No such namespace.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!handler->hasMethod(method)) {
|
||||
sendErrorResponse(proxyClient, commandId, "No such method");
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "No such method.");
|
||||
proxyClient->killConnection("No such method.");
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap params = message.value("params").toMap();
|
||||
|
||||
QPair<bool, QString> validationResult = handler->validateParams(method, params);
|
||||
if (!validationResult.first) {
|
||||
sendErrorResponse(proxyClient, commandId, "Invalid params: " + validationResult.second);
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Invalid params passed.");
|
||||
proxyClient->killConnection("Invalid params passed.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -297,6 +297,7 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
|
||||
reply->setClientId(proxyClient->clientId());
|
||||
reply->setCommandId(commandId);
|
||||
sendResponse(proxyClient, commandId, reply->data());
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "monitorserver.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace remoteproxy {
|
||||
@ -87,6 +88,8 @@ void MonitorServer::onMonitorConnected()
|
||||
connect(clientConnection, &QLocalSocket::readyRead, this, &MonitorServer::onMonitorDisconnected);
|
||||
m_clients.append(clientConnection);
|
||||
|
||||
qCDebug(dcMonitorServer()) << "New monitor connected.";
|
||||
|
||||
if (!m_timer->isActive()) {
|
||||
// Send the data right the way
|
||||
onTimeout();
|
||||
@ -105,6 +108,13 @@ void MonitorServer::onMonitorDisconnected()
|
||||
void MonitorServer::startServer()
|
||||
{
|
||||
qCDebug(dcMonitorServer()) << "Starting server on" << m_serverName;
|
||||
|
||||
// Make sure the monitor can be created
|
||||
if (QFile::exists(m_serverName)) {
|
||||
qCDebug(dcMonitorServer()) << "Clean up old monitor socket";
|
||||
QFile::remove(m_serverName);
|
||||
}
|
||||
|
||||
m_server = new QLocalServer(this);
|
||||
if (!m_server->listen(m_serverName)) {
|
||||
qCWarning(dcMonitorServer()) << "Could not start local server for monitor on" << m_serverName << m_server->errorString();
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "engine.h"
|
||||
#include "proxyclient.h"
|
||||
|
||||
#include <QDateTime>
|
||||
@ -32,6 +33,10 @@ ProxyClient::ProxyClient(TransportInterface *interface, const QUuid &clientId, c
|
||||
m_peerAddress(address)
|
||||
{
|
||||
m_creationTimeStamp = QDateTime::currentDateTime().toTime_t();
|
||||
|
||||
connect(&m_timer, &QTimer::timeout, this, &ProxyClient::timeoutOccured);
|
||||
m_timer.setSingleShot(true);
|
||||
m_timer.start(Engine::instance()->configuration()->inactiveTimeout());
|
||||
}
|
||||
|
||||
QUuid ProxyClient::clientId() const
|
||||
@ -61,9 +66,10 @@ bool ProxyClient::isAuthenticated() const
|
||||
|
||||
void ProxyClient::setAuthenticated(bool isAuthenticated)
|
||||
{
|
||||
// TODO: start the timeout counter and disconnect if no tunnel established
|
||||
m_authenticated = isAuthenticated;
|
||||
if (m_authenticated){
|
||||
if (m_authenticated) {
|
||||
m_timer.stop();
|
||||
m_timer.start(Engine::instance()->configuration()->aloneTimeout());
|
||||
emit authenticated();
|
||||
}
|
||||
}
|
||||
@ -75,9 +81,9 @@ bool ProxyClient::isTunnelConnected() const
|
||||
|
||||
void ProxyClient::setTunnelConnected(bool isTunnelConnected)
|
||||
{
|
||||
// TODO: reset the timeout counter and disconnect if no tunnel established
|
||||
m_tunnelConnected = isTunnelConnected;
|
||||
if (m_tunnelConnected){
|
||||
if (m_tunnelConnected) {
|
||||
m_timer.stop();
|
||||
emit tunnelConnected();
|
||||
}
|
||||
}
|
||||
@ -117,6 +123,22 @@ void ProxyClient::setToken(const QString &token)
|
||||
m_token = token;
|
||||
}
|
||||
|
||||
void ProxyClient::sendData(const QByteArray &data)
|
||||
{
|
||||
if (!m_interface)
|
||||
return;
|
||||
|
||||
m_interface->sendData(m_clientId, data);
|
||||
}
|
||||
|
||||
void ProxyClient::killConnection(const QString &reason)
|
||||
{
|
||||
if (!m_interface)
|
||||
return;
|
||||
|
||||
m_interface->killClientConnection(m_clientId, reason);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, ProxyClient *proxyClient)
|
||||
{
|
||||
debug.nospace() << "ProxyClient(" << proxyClient->interface()->serverName();
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <QUuid>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "transportinterface.h"
|
||||
@ -62,11 +63,16 @@ public:
|
||||
QString token() const;
|
||||
void setToken(const QString &token);
|
||||
|
||||
// Actions for this client
|
||||
void sendData(const QByteArray &data);
|
||||
void killConnection(const QString &reason);
|
||||
|
||||
private:
|
||||
TransportInterface *m_interface = nullptr;
|
||||
QTimer m_timer;
|
||||
|
||||
QUuid m_clientId;
|
||||
QHostAddress m_peerAddress;
|
||||
|
||||
uint m_creationTimeStamp = 0;
|
||||
|
||||
bool m_authenticated = false;
|
||||
@ -79,6 +85,7 @@ private:
|
||||
signals:
|
||||
void authenticated();
|
||||
void tunnelConnected();
|
||||
void timeoutOccured();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -44,11 +44,6 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileInfo.isReadable()) {
|
||||
qCWarning(dcApplication()) << "Configuration: Cannot read configuration file" << m_fileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
QSettings settings(m_fileName, QSettings::IniFormat);
|
||||
|
||||
settings.beginGroup("ProxyServer");
|
||||
@ -56,6 +51,12 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
|
||||
setWriteLogFile(settings.value("writeLogs", false).toBool());
|
||||
setLogFileName(settings.value("logFile", "/var/log/nymea-remoteproxy.log").toString());
|
||||
setMonitorSocketFileName(settings.value("monitorSocket", "/tmp/nymea-remoteproxy.monitor").toString());
|
||||
|
||||
setJsonRpcTimeout(settings.value("jsonRpcTimeout", 10000).toInt());
|
||||
setAuthenticationTimeout(settings.value("authenticationTimeout", 5000).toInt());
|
||||
setInactiveTimeout(settings.value("inactiveTimeout", 5000).toInt());
|
||||
setAloneTimeout(settings.value("aloneTimeout", 5000).toInt());
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("SSL");
|
||||
@ -164,6 +165,46 @@ void ProxyConfiguration::setMonitorSocketFileName(const QString &fileName)
|
||||
m_monitorSocketFileName = fileName;
|
||||
}
|
||||
|
||||
int ProxyConfiguration::jsonRpcTimeout() const
|
||||
{
|
||||
return m_jsonRpcTimeout;
|
||||
}
|
||||
|
||||
void ProxyConfiguration::setJsonRpcTimeout(int timeout)
|
||||
{
|
||||
m_jsonRpcTimeout = timeout;
|
||||
}
|
||||
|
||||
int ProxyConfiguration::authenticationTimeout() const
|
||||
{
|
||||
return m_authenticationTimeout;
|
||||
}
|
||||
|
||||
void ProxyConfiguration::setAuthenticationTimeout(int timeout)
|
||||
{
|
||||
m_authenticationTimeout = timeout;
|
||||
}
|
||||
|
||||
int ProxyConfiguration::inactiveTimeout() const
|
||||
{
|
||||
return m_inactiveTimeout;
|
||||
}
|
||||
|
||||
void ProxyConfiguration::setInactiveTimeout(int timeout)
|
||||
{
|
||||
m_inactiveTimeout = timeout;
|
||||
}
|
||||
|
||||
int ProxyConfiguration::aloneTimeout() const
|
||||
{
|
||||
return m_aloneTimeout;
|
||||
}
|
||||
|
||||
void ProxyConfiguration::setAloneTimeout(int timeout)
|
||||
{
|
||||
m_aloneTimeout = timeout;
|
||||
}
|
||||
|
||||
QString ProxyConfiguration::sslCertificateFileName() const
|
||||
{
|
||||
return m_sslCertificateFileName;
|
||||
@ -247,6 +288,10 @@ QDebug operator<<(QDebug debug, ProxyConfiguration *configuration)
|
||||
debug.nospace() << " - Server name:" << configuration->serverName() << endl;
|
||||
debug.nospace() << " - Write logfile:" << configuration->writeLogFile() << endl;
|
||||
debug.nospace() << " - Logfile:" << configuration->logFileName() << endl;
|
||||
debug.nospace() << " - JSON RPC timeout:" << configuration->jsonRpcTimeout() << " [ms]" << endl;
|
||||
debug.nospace() << " - Authentication timeout:" << configuration->authenticationTimeout() << " [ms]" << endl;
|
||||
debug.nospace() << " - Inactive timeout:" << configuration->inactiveTimeout() << " [ms]" << endl;
|
||||
debug.nospace() << " - Alone timeout:" << configuration->aloneTimeout() << " [ms]" << endl;
|
||||
debug.nospace() << "SSL configuration" << endl;
|
||||
debug.nospace() << " - Certificate:" << configuration->sslCertificateFileName() << endl;
|
||||
debug.nospace() << " - Certificate key:" << configuration->sslCertificateKeyFileName() << endl;
|
||||
|
||||
@ -52,6 +52,18 @@ public:
|
||||
QString monitorSocketFileName() const;
|
||||
void setMonitorSocketFileName(const QString &fileName);
|
||||
|
||||
int jsonRpcTimeout() const;
|
||||
void setJsonRpcTimeout(int timeout);
|
||||
|
||||
int authenticationTimeout() const;
|
||||
void setAuthenticationTimeout(int timeout);
|
||||
|
||||
int inactiveTimeout() const;
|
||||
void setInactiveTimeout(int timeout);
|
||||
|
||||
int aloneTimeout() const;
|
||||
void setAloneTimeout(int timeout);
|
||||
|
||||
// Ssl
|
||||
QString sslCertificateFileName() const;
|
||||
void setSslCertificateFileName(const QString &fileName);
|
||||
@ -86,6 +98,11 @@ private:
|
||||
QString m_logFileName = "/var/log/nymea-remoteproxy.log";
|
||||
QString m_monitorSocketFileName;
|
||||
|
||||
int m_jsonRpcTimeout = 10000;
|
||||
int m_authenticationTimeout = 5000;
|
||||
int m_inactiveTimeout = 5000;
|
||||
int m_aloneTimeout = 5000;
|
||||
|
||||
// Ssl
|
||||
QString m_sslCertificateFileName = "/etc/ssl/certs/ssl-cert-snakeoil.pem";
|
||||
QString m_sslCertificateKeyFileName = "/etc/ssl/private/ssl-cert-snakeoil.key";
|
||||
|
||||
@ -149,6 +149,7 @@ 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);
|
||||
m_jsonRpcServer->registerClient(proxyClient);
|
||||
@ -176,7 +177,7 @@ void ProxyServer::onClientDisconnected(const QUuid &clientId)
|
||||
ProxyClient *remoteClient = getRemoteClient(proxyClient);
|
||||
m_tunnels.remove(proxyClient->token());
|
||||
if (remoteClient) {
|
||||
remoteClient->interface()->killClientConnection(remoteClient->clientId(), "Tunnel client disconnected");
|
||||
remoteClient->killConnection("Tunnel client disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,27 +208,21 @@ void ProxyServer::onClientDataAvailable(const QUuid &clientId, const QByteArray
|
||||
qCWarning(dcProxyServer()) << "An authenticated client sent data without tunnel connection. This is not allowed.";
|
||||
m_jsonRpcServer->unregisterClient(proxyClient);
|
||||
// The client is authenticated and tries to send data, this is not allowed.
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Data received while authenticated but not remote connected.");
|
||||
proxyClient->killConnection("Data received while authenticated but not remote connected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (proxyClient->isAuthenticated() && proxyClient->isTunnelConnected()) {
|
||||
// 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
|
||||
}
|
||||
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()) << " --> from" << proxyClient;
|
||||
qCDebug(dcProxyServerTraffic()) << " --> to" << remoteClient;
|
||||
qCDebug(dcProxyServerTraffic()) << " --> data:" << qUtf8Printable(data);
|
||||
|
||||
remoteClient->interface()->sendData(remoteClient->clientId(), data);
|
||||
remoteClient->sendData(data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,7 +239,7 @@ void ProxyServer::onProxyClientAuthenticated()
|
||||
// Note: remove the authenticated token, so the current tunnel will not interrupted.
|
||||
proxyClient->setToken(QString());
|
||||
proxyClient->setAuthenticated(false);
|
||||
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "There is already an established tunnel with this token.");
|
||||
proxyClient->killConnection("There is already an established tunnel with this token.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -264,6 +259,13 @@ void ProxyServer::onProxyClientTunnelConnected()
|
||||
|
||||
}
|
||||
|
||||
void ProxyServer::onProxyClientTimeoutOccured()
|
||||
{
|
||||
ProxyClient *proxyClient = static_cast<ProxyClient *>(sender());
|
||||
qCDebug(dcProxyServer()) << "Timeout occured for" << proxyClient;
|
||||
proxyClient->killConnection("Proxy timeout occuret");
|
||||
}
|
||||
|
||||
void ProxyServer::startServer()
|
||||
{
|
||||
qCDebug(dcProxyServer()) << "Start proxy server.";
|
||||
|
||||
@ -77,6 +77,7 @@ private slots:
|
||||
|
||||
void onProxyClientAuthenticated();
|
||||
void onProxyClientTunnelConnected();
|
||||
void onProxyClientTimeoutOccured();
|
||||
|
||||
public slots:
|
||||
void startServer();
|
||||
|
||||
@ -37,8 +37,6 @@ public:
|
||||
QString serverName() const;
|
||||
|
||||
virtual void sendData(const QUuid &clientId, const QByteArray &data) = 0;
|
||||
virtual void sendData(const QList<QUuid> &clients, const QByteArray &data) = 0;
|
||||
|
||||
virtual void killClientConnection(const QUuid &clientId, const QString &killReason) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
@ -73,20 +73,13 @@ void WebSocketServer::sendData(const QUuid &clientId, const QByteArray &data)
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketServer::sendData(const QList<QUuid> &clients, const QByteArray &data)
|
||||
{
|
||||
foreach (const QUuid &client, clients) {
|
||||
sendData(client, data);
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketServer::killClientConnection(const QUuid &clientId, const QString &killReason)
|
||||
{
|
||||
QWebSocket *client = m_clientList.value(clientId);
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
qCWarning(dcWebSocketServer()) << "Kill client connection" << clientId.toString() << "Reason:" << killReason;
|
||||
qCWarning(dcWebSocketServer()) << "Killing client connection" << clientId.toString() << "Reason:" << killReason;
|
||||
client->close(QWebSocketProtocol::CloseCodeBadOperation, killReason);
|
||||
}
|
||||
|
||||
@ -110,7 +103,6 @@ void WebSocketServer::onClientConnected()
|
||||
// Append the new client to the client list
|
||||
m_clientList.insert(clientId, client);
|
||||
|
||||
connect(client, SIGNAL(pong(quint64,QByteArray)), this, SLOT(onPing(quint64,QByteArray)));
|
||||
connect(client, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(onBinaryMessageReceived(QByteArray)));
|
||||
connect(client, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
|
||||
connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onClientError(QAbstractSocket::SocketError)));
|
||||
@ -130,12 +122,6 @@ void WebSocketServer::onClientDisconnected()
|
||||
emit clientDisconnected(clientId);
|
||||
}
|
||||
|
||||
void WebSocketServer::onBinaryMessageReceived(const QByteArray &data)
|
||||
{
|
||||
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||
qCDebug(dcWebSocketServerTraffic()) << "<-- Binary message from" << client->peerAddress().toString() << ":" << data;
|
||||
}
|
||||
|
||||
void WebSocketServer::onTextMessageReceived(const QString &message)
|
||||
{
|
||||
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||
@ -143,6 +129,14 @@ void WebSocketServer::onTextMessageReceived(const QString &message)
|
||||
emit dataAvailable(m_clientList.key(client), message.toUtf8());
|
||||
}
|
||||
|
||||
void WebSocketServer::onBinaryMessageReceived(const QByteArray &data)
|
||||
{
|
||||
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||
qCWarning(dcWebSocketServerTraffic()) << "<-- Binary message from" << client->peerAddress().toString() << ":" << data;
|
||||
// Note: this is not expected, so close this client connection.
|
||||
client->close(QWebSocketProtocol::CloseCodeBadOperation, "Binary message not expected.");
|
||||
}
|
||||
|
||||
void WebSocketServer::onClientError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||
@ -154,12 +148,6 @@ void WebSocketServer::onServerError(QAbstractSocket::SocketError error)
|
||||
qCWarning(dcWebSocketServer()) << "Server error occured:" << error << m_server->errorString();
|
||||
}
|
||||
|
||||
void WebSocketServer::onPing(quint64 elapsedTime, const QByteArray &payload)
|
||||
{
|
||||
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||
qCDebug(dcWebSocketServer) << "ping response" << client->peerAddress() << elapsedTime << payload;
|
||||
}
|
||||
|
||||
bool WebSocketServer::startServer()
|
||||
{
|
||||
m_server = new QWebSocketServer(QCoreApplication::applicationName(), QWebSocketServer::SecureMode, this);
|
||||
|
||||
@ -48,8 +48,6 @@ public:
|
||||
QSslConfiguration sslConfiguration() const;
|
||||
|
||||
void sendData(const QUuid &clientId, const QByteArray &data) override;
|
||||
void sendData(const QList<QUuid> &clients, const QByteArray &data) override;
|
||||
|
||||
void killClientConnection(const QUuid &clientId, const QString &killReason) override;
|
||||
|
||||
private:
|
||||
@ -63,11 +61,10 @@ private:
|
||||
private slots:
|
||||
void onClientConnected();
|
||||
void onClientDisconnected();
|
||||
void onBinaryMessageReceived(const QByteArray &data);
|
||||
void onTextMessageReceived(const QString &message);
|
||||
void onBinaryMessageReceived(const QByteArray &data);
|
||||
void onClientError(QAbstractSocket::SocketError error);
|
||||
void onServerError(QAbstractSocket::SocketError error);
|
||||
void onPing(quint64 elapsedTime, const QByteArray & payload);
|
||||
|
||||
public slots:
|
||||
bool startServer() override;
|
||||
|
||||
@ -53,7 +53,10 @@ protected:
|
||||
signals:
|
||||
void connectedChanged(bool connected);
|
||||
void dataReceived(const QByteArray &data);
|
||||
|
||||
void stateChanged(QAbstractSocket::SocketState state);
|
||||
void errorOccured(QAbstractSocket::SocketError error);
|
||||
|
||||
void sslErrors(const QList<QSslError> &errors);
|
||||
|
||||
public slots:
|
||||
|
||||
@ -47,38 +47,11 @@ RemoteProxyConnection::State RemoteProxyConnection::state() const
|
||||
return m_state;
|
||||
}
|
||||
|
||||
RemoteProxyConnection::Error RemoteProxyConnection::error() const
|
||||
QAbstractSocket::SocketError RemoteProxyConnection::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
QString RemoteProxyConnection::errorString() const
|
||||
{
|
||||
QString errorString;
|
||||
switch (m_error) {
|
||||
case ErrorNoError:
|
||||
errorString = "";
|
||||
break;
|
||||
case ErrorHostNotFound:
|
||||
errorString = "The proxy host url could not be resolved.";
|
||||
break;
|
||||
case ErrorSocketError:
|
||||
errorString = "Socket connection error occured.";
|
||||
break;
|
||||
case ErrorSslError:
|
||||
errorString = "SSL error occured.";
|
||||
break;
|
||||
case ErrorProxyNotResponding:
|
||||
errorString = "The proxy server does not respond.";
|
||||
break;
|
||||
case ErrorProxyAuthenticationFailed:
|
||||
errorString = "The authentication on the proxy server failed.";
|
||||
break;
|
||||
}
|
||||
|
||||
return errorString;
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::ignoreSslErrors()
|
||||
{
|
||||
m_connection->ignoreSslErrors();
|
||||
@ -95,13 +68,13 @@ bool RemoteProxyConnection::isConnected() const
|
||||
|| m_state == StateInitializing
|
||||
|| m_state == StateReady
|
||||
|| m_state == StateAuthenticating
|
||||
|| m_state == StateWaitTunnel
|
||||
|| m_state == StateAuthenticated
|
||||
|| m_state == StateRemoteConnected;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::isAuthenticated() const
|
||||
{
|
||||
return m_state == StateWaitTunnel || m_state == StateRemoteConnected;
|
||||
return m_state == StateAuthenticated || m_state == StateRemoteConnected;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::isRemoteConnected() const
|
||||
@ -197,13 +170,13 @@ void RemoteProxyConnection::setState(RemoteProxyConnection::State state)
|
||||
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::setError(RemoteProxyConnection::Error error)
|
||||
void RemoteProxyConnection::setError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
if (m_error == error)
|
||||
return;
|
||||
|
||||
m_error = error;
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Error occured" << m_error << errorString();
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Error occured" << m_error;
|
||||
emit errorOccured(m_error);
|
||||
}
|
||||
|
||||
@ -226,12 +199,13 @@ void RemoteProxyConnection::onConnectionChanged(bool isConnected)
|
||||
void RemoteProxyConnection::onConnectionDataAvailable(const QByteArray &data)
|
||||
{
|
||||
switch (m_state) {
|
||||
case StateHostLookup:
|
||||
case StateConnecting:
|
||||
case StateConnected:
|
||||
case StateInitializing:
|
||||
case StateReady:
|
||||
case StateAuthenticating:
|
||||
case StateWaitTunnel:
|
||||
case StateAuthenticated:
|
||||
m_jsonClient->processData(data);
|
||||
break;
|
||||
case StateRemoteConnected:
|
||||
@ -239,15 +213,38 @@ void RemoteProxyConnection::onConnectionDataAvailable(const QByteArray &data)
|
||||
emit dataReady(data);
|
||||
break;
|
||||
default:
|
||||
qCWarning(dcRemoteProxyClientConnection()) << "Unhandled: Data reviced" << data;
|
||||
qCWarning(dcRemoteProxyClientConnection()) << "Unhandled: Data received" << data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onConnectionSocketError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
emit socketErrorOccured(error);
|
||||
setError(ErrorSocketError);
|
||||
setError(error);
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onConnectionStateChanged(QAbstractSocket::SocketState state)
|
||||
{
|
||||
switch (state) {
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
setState(StateDisconnected);
|
||||
break;
|
||||
case QAbstractSocket::HostLookupState:
|
||||
setState(StateHostLookup);
|
||||
break;
|
||||
case QAbstractSocket::ConnectingState:
|
||||
setState(StateConnecting);
|
||||
break;
|
||||
case QAbstractSocket::ConnectedState:
|
||||
setState(StateConnected);
|
||||
break;
|
||||
case QAbstractSocket::ClosingState:
|
||||
setState(StateDiconnecting);
|
||||
break;
|
||||
case QAbstractSocket::BoundState:
|
||||
case QAbstractSocket::ListeningState:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onHelloFinished()
|
||||
@ -287,11 +284,11 @@ void RemoteProxyConnection::onAuthenticateFinished()
|
||||
QVariantMap responseParams = response.value("params").toMap();
|
||||
if (responseParams.value("authenticationError").toString() != "AuthenticationErrorNoError") {
|
||||
qCWarning(dcRemoteProxyClientConnection()) << "Authentication request finished with error" << responseParams.value("authenticationError").toString();
|
||||
setError(RemoteProxyConnection::ErrorProxyAuthenticationFailed);
|
||||
setError(QAbstractSocket::ProxyConnectionRefusedError);
|
||||
m_connection->disconnectServer();
|
||||
} else {
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Successfully authenticated.";
|
||||
setState(StateWaitTunnel);
|
||||
setState(StateAuthenticated);
|
||||
emit authenticated();
|
||||
}
|
||||
}
|
||||
@ -314,7 +311,7 @@ bool RemoteProxyConnection::connectServer(const QUrl &url)
|
||||
|
||||
m_serverUrl = url;
|
||||
m_connectionType = ConnectionTypeWebSocket;
|
||||
m_error = ErrorNoError;
|
||||
m_error = QAbstractSocket::UnknownSocketError;
|
||||
|
||||
cleanUp();
|
||||
|
||||
@ -324,13 +321,14 @@ bool RemoteProxyConnection::connectServer(const QUrl &url)
|
||||
break;
|
||||
case ConnectionTypeTcpSocket:
|
||||
// FIXME:
|
||||
m_connection = qobject_cast<ProxyConnection *>(new WebSocketConnection(this));
|
||||
//m_connection = qobject_cast<ProxyConnection *>(new WebSocketConnection(this));
|
||||
break;
|
||||
}
|
||||
|
||||
connect(m_connection, &ProxyConnection::connectedChanged, this, &RemoteProxyConnection::onConnectionChanged);
|
||||
connect(m_connection, &ProxyConnection::dataReceived, this, &RemoteProxyConnection::onConnectionDataAvailable);
|
||||
connect(m_connection, &ProxyConnection::errorOccured, this, &RemoteProxyConnection::onConnectionSocketError);
|
||||
connect(m_connection, &ProxyConnection::stateChanged, this, &RemoteProxyConnection::onConnectionStateChanged);
|
||||
connect(m_connection, &ProxyConnection::sslErrors, this, &RemoteProxyConnection::sslErrors);
|
||||
|
||||
m_jsonClient = new JsonRpcClient(m_connection, this);
|
||||
|
||||
@ -49,33 +49,24 @@ public:
|
||||
Q_ENUM(ConnectionType)
|
||||
|
||||
enum State {
|
||||
StateHostLookup,
|
||||
StateConnecting,
|
||||
StateConnected,
|
||||
StateInitializing,
|
||||
StateReady,
|
||||
StateAuthenticating,
|
||||
StateWaitTunnel,
|
||||
StateAuthenticated,
|
||||
StateRemoteConnected,
|
||||
StateDisconnected
|
||||
StateDiconnecting,
|
||||
StateDisconnected,
|
||||
};
|
||||
Q_ENUM(State)
|
||||
|
||||
enum Error {
|
||||
ErrorNoError,
|
||||
ErrorHostNotFound,
|
||||
ErrorSocketError,
|
||||
ErrorSslError,
|
||||
ErrorProxyNotResponding,
|
||||
ErrorProxyAuthenticationFailed
|
||||
};
|
||||
Q_ENUM(Error)
|
||||
|
||||
explicit RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, QObject *parent = nullptr);
|
||||
~RemoteProxyConnection();
|
||||
|
||||
RemoteProxyConnection::State state() const;
|
||||
RemoteProxyConnection::Error error() const;
|
||||
QString errorString() const;
|
||||
QAbstractSocket::SocketError error() const;
|
||||
|
||||
void ignoreSslErrors();
|
||||
void ignoreSslErrors(const QList<QSslError> &errors);
|
||||
@ -104,7 +95,7 @@ private:
|
||||
QUrl m_serverUrl;
|
||||
|
||||
State m_state = StateDisconnected;
|
||||
Error m_error = ErrorNoError;
|
||||
QAbstractSocket::SocketError m_error = QAbstractSocket::UnknownSocketError;
|
||||
|
||||
bool m_insecureConnection = false;
|
||||
bool m_remoteConnected = false;
|
||||
@ -125,7 +116,7 @@ private:
|
||||
void cleanUp();
|
||||
|
||||
void setState(State state);
|
||||
void setError(Error error);
|
||||
void setError(QAbstractSocket::SocketError error);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
@ -135,8 +126,7 @@ signals:
|
||||
void disconnected();
|
||||
|
||||
void stateChanged(RemoteProxyConnection::State state);
|
||||
void errorOccured(RemoteProxyConnection::Error error);
|
||||
void socketErrorOccured(QAbstractSocket::SocketError error);
|
||||
void errorOccured(QAbstractSocket::SocketError error);
|
||||
void sslErrors(const QList<QSslError> &errors);
|
||||
|
||||
void dataReady(const QByteArray &data);
|
||||
@ -145,6 +135,7 @@ private slots:
|
||||
void onConnectionChanged(bool isConnected);
|
||||
void onConnectionDataAvailable(const QByteArray &data);
|
||||
void onConnectionSocketError(QAbstractSocket::SocketError error);
|
||||
void onConnectionStateChanged(QAbstractSocket::SocketState state);
|
||||
|
||||
void onHelloFinished();
|
||||
void onAuthenticateFinished();
|
||||
@ -155,12 +146,10 @@ public slots:
|
||||
bool authenticate(const QString &token);
|
||||
void disconnectServer();
|
||||
bool sendData(const QByteArray &data);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::Error);
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::State);
|
||||
Q_DECLARE_METATYPE(remoteproxyclient::RemoteProxyConnection::ConnectionType);
|
||||
|
||||
|
||||
@ -32,7 +32,6 @@ WebSocketConnection::WebSocketConnection(QObject *parent) :
|
||||
|
||||
connect(m_webSocket, &QWebSocket::disconnected, this, &WebSocketConnection::onDisconnected);
|
||||
connect(m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketConnection::onTextMessageReceived);
|
||||
connect(m_webSocket, &QWebSocket::binaryMessageReceived, this, &WebSocketConnection::onBinaryMessageReceived);
|
||||
|
||||
connect(m_webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||
connect(m_webSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onStateChanged(QAbstractSocket::SocketState)));
|
||||
@ -41,7 +40,7 @@ WebSocketConnection::WebSocketConnection(QObject *parent) :
|
||||
|
||||
WebSocketConnection::~WebSocketConnection()
|
||||
{
|
||||
|
||||
m_webSocket->close();
|
||||
}
|
||||
|
||||
QUrl WebSocketConnection::serverUrl() const
|
||||
@ -67,7 +66,7 @@ void WebSocketConnection::ignoreSslErrors(const QList<QSslError> &errors)
|
||||
void WebSocketConnection::onDisconnected()
|
||||
{
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Disconnected from" << m_webSocket->requestUrl().toString() << m_webSocket->closeReason();
|
||||
emit connectedChanged(false);
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
void WebSocketConnection::onError(QAbstractSocket::SocketError error)
|
||||
@ -89,6 +88,8 @@ void WebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
|
||||
setConnected(false);
|
||||
break;
|
||||
}
|
||||
|
||||
emit stateChanged(state);
|
||||
}
|
||||
|
||||
void WebSocketConnection::onTextMessageReceived(const QString &message)
|
||||
@ -96,11 +97,6 @@ void WebSocketConnection::onTextMessageReceived(const QString &message)
|
||||
emit dataReceived(message.toUtf8());
|
||||
}
|
||||
|
||||
void WebSocketConnection::onBinaryMessageReceived(const QByteArray &message)
|
||||
{
|
||||
Q_UNUSED(message)
|
||||
}
|
||||
|
||||
void WebSocketConnection::connectServer(const QUrl &serverUrl)
|
||||
{
|
||||
if (connected()) {
|
||||
|
||||
@ -56,7 +56,6 @@ private slots:
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
void onStateChanged(QAbstractSocket::SocketState state);
|
||||
void onTextMessageReceived(const QString &message);
|
||||
void onBinaryMessageReceived(const QByteArray &message);
|
||||
|
||||
public slots:
|
||||
void connectServer(const QUrl &serverUrl) override;
|
||||
|
||||
@ -5,7 +5,7 @@ QT -= gui
|
||||
SERVER_NAME=nymea-remoteproxy
|
||||
API_VERSION_MAJOR=0
|
||||
API_VERSION_MINOR=1
|
||||
SERVER_VERSION=0.1.0
|
||||
SERVER_VERSION=0.1.1
|
||||
|
||||
DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \
|
||||
SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \
|
||||
@ -19,6 +19,10 @@ QMAKE_LFLAGS *= -std=c++11
|
||||
top_srcdir=$$PWD
|
||||
top_builddir=$$shadowed($$PWD)
|
||||
|
||||
ccache {
|
||||
QMAKE_CXX = ccache g++
|
||||
}
|
||||
|
||||
coverage {
|
||||
# Note: this works only if you build in the source dir
|
||||
OBJECTS_DIR =
|
||||
@ -44,7 +48,7 @@ coverage {
|
||||
coverage-html.depends = clean-gcda check generate-coverage-html
|
||||
|
||||
generate-coverage-html.commands = \
|
||||
"@echo Collecting coverage data"; \
|
||||
"echo 'Collecting coverage data'"; \
|
||||
"lcov --directory $${top_srcdir} --capture --output-file coverage.info --no-checksum --compat-libtool"; \
|
||||
"lcov --extract coverage.info \"*/server/*.cpp\" --extract coverage.info \"*/libnymea-remoteproxy/*.cpp\" --extract coverage.info \"*/libnymea-remoteproxyclient/*.cpp\" -o coverage.info"; \
|
||||
"lcov --remove coverage.info \"moc_*.cpp\" --remove coverage.info \"*/test/*\" -o coverage.info"; \
|
||||
@ -52,17 +56,19 @@ coverage {
|
||||
|
||||
clean-coverage-html.depends = clean-gcda
|
||||
clean-coverage-html.commands = \
|
||||
"echo 'Clean html coverage report'"; \
|
||||
"lcov --directory $${top_srcdir} -z"; \
|
||||
"rm -rf coverage.info coverage-html"
|
||||
|
||||
coverage-gcovr.depends = clean-gcda check generate-coverage-gcovr
|
||||
|
||||
generate-coverage-gcovr.commands = \
|
||||
"@echo Generating coverage GCOVR report"; \
|
||||
"echo 'Generating coverage GCOVR report'"; \
|
||||
"gcovr -x -r $${top_srcdir} -o $${top_srcdir}/coverage.xml -e \".*/moc_.*\" -e \"tests/.*\" -e \".*\\.h\""
|
||||
|
||||
clean-coverage-gcovr.depends = clean-gcda
|
||||
clean-coverage-gcovr.commands = \
|
||||
"echo 'Clean coverage report'"; \
|
||||
"rm -rf $${top_srcdir}/coverage.xml"
|
||||
|
||||
QMAKE_CLEAN += *.gcda *.gcno coverage.info coverage.xml
|
||||
|
||||
@ -13,3 +13,4 @@ message("----------------------------------------------------------")
|
||||
message("JSON-RPC API version $${API_VERSION_MAJOR}.$${API_VERSION_MINOR}")
|
||||
message("Qt version:" $$[QT_VERSION])
|
||||
coverage { message("Building with coverage report") }
|
||||
ccache { message("Building with ccache support") }
|
||||
|
||||
@ -3,5 +3,9 @@
|
||||
<file>test-certificate.crt</file>
|
||||
<file>test-certificate.key</file>
|
||||
<file>test-configuration.conf</file>
|
||||
<file>test-configuration-chain.conf</file>
|
||||
<file>test-configuration-faulty-certificate.conf</file>
|
||||
<file>test-configuration-faulty-key.conf</file>
|
||||
<file>test-configuration-faulty-chain.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
18
tests/resources/test-configuration-chain.conf
Normal file
18
tests/resources/test-configuration-chain.conf
Normal file
@ -0,0 +1,18 @@
|
||||
[ProxyServer]
|
||||
name=test-nymea-remoteproxy
|
||||
writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy-faulty.log
|
||||
monitorSocket=/tmp/nymea-remoteproxy-test.sock
|
||||
|
||||
[SSL]
|
||||
certificate=:/test-certificate.crt
|
||||
certificateKey=:/test-certificate.key
|
||||
certificateChain=:/test-certificate.crt
|
||||
|
||||
[WebSocketServer]
|
||||
host=127.0.0.1
|
||||
port=1212
|
||||
|
||||
[TcpServer]
|
||||
host=127.0.0.1
|
||||
port=1213
|
||||
18
tests/resources/test-configuration-faulty-certificate.conf
Normal file
18
tests/resources/test-configuration-faulty-certificate.conf
Normal file
@ -0,0 +1,18 @@
|
||||
[ProxyServer]
|
||||
name=test-nymea-remoteproxy-faulty-certificate
|
||||
writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy-faulty.log
|
||||
monitorSocket=/tmp/nymea-remoteproxy-test.sock
|
||||
|
||||
[SSL]
|
||||
certificate=:/not-existing-test-certificate.crt
|
||||
certificateKey=:/test-certificate.key
|
||||
certificateChain=
|
||||
|
||||
[WebSocketServer]
|
||||
host=127.0.0.1
|
||||
port=1212
|
||||
|
||||
[TcpServer]
|
||||
host=127.0.0.1
|
||||
port=1213
|
||||
18
tests/resources/test-configuration-faulty-chain.conf
Normal file
18
tests/resources/test-configuration-faulty-chain.conf
Normal file
@ -0,0 +1,18 @@
|
||||
[ProxyServer]
|
||||
name=test-nymea-remoteproxy
|
||||
writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy.log
|
||||
monitorSocket=/tmp/nymea-remoteproxy-test.sock
|
||||
|
||||
[SSL]
|
||||
certificate=:/test-certificate.crt
|
||||
certificateKey=:/test-certificate.key
|
||||
certificateChain=:/not-existing-test-certificate.crt
|
||||
|
||||
[WebSocketServer]
|
||||
host=127.0.0.1
|
||||
port=1212
|
||||
|
||||
[TcpServer]
|
||||
host=127.0.0.1
|
||||
port=1213
|
||||
18
tests/resources/test-configuration-faulty-key.conf
Normal file
18
tests/resources/test-configuration-faulty-key.conf
Normal file
@ -0,0 +1,18 @@
|
||||
[ProxyServer]
|
||||
name=test-nymea-remoteproxy-faulty-certificate
|
||||
writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy-faulty.log
|
||||
monitorSocket=/tmp/nymea-remoteproxy-test.sock
|
||||
|
||||
[SSL]
|
||||
certificate=:/test-certificate.crt
|
||||
certificateKey=:/not-existing-test-certificate.key
|
||||
certificateChain=
|
||||
|
||||
[WebSocketServer]
|
||||
host=127.0.0.1
|
||||
port=1212
|
||||
|
||||
[TcpServer]
|
||||
host=127.0.0.1
|
||||
port=1213
|
||||
@ -3,6 +3,10 @@ name=test-nymea-remoteproxy
|
||||
writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy.log
|
||||
monitorSocket=/tmp/nymea-remoteproxy-test.sock
|
||||
jsonRpcTimeout=1000
|
||||
authenticationTimeout=1500
|
||||
inactiveTimeout=1500
|
||||
aloneTimeout=1000
|
||||
|
||||
[SSL]
|
||||
certificate=:/test-certificate.crt
|
||||
|
||||
@ -73,16 +73,61 @@ void RemoteProxyOfflineTests::dummyAuthenticator()
|
||||
cleanUpEngine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RemoteProxyOfflineTests::monitorServer()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
QVERIFY(Engine::instance()->monitorServer()->running());
|
||||
QLocalSocket *monitor = new QLocalSocket(this);
|
||||
|
||||
QSignalSpy connectedSpy(monitor, &QLocalSocket::connected);
|
||||
monitor->connectToServer(m_configuration->monitorSocketFileName());
|
||||
connectedSpy.wait(200);
|
||||
QVERIFY(connectedSpy.count() == 1);
|
||||
|
||||
QSignalSpy dataSpy(monitor, &QLocalSocket::readyRead);
|
||||
dataSpy.wait();
|
||||
QVERIFY(dataSpy.count() == 1);
|
||||
QByteArray data = monitor->readAll();
|
||||
qDebug() << data;
|
||||
|
||||
// TODO: verify monitor data
|
||||
|
||||
QSignalSpy disconnectedSpy(monitor, &QLocalSocket::connected);
|
||||
monitor->disconnectFromServer();
|
||||
disconnectedSpy.wait(200);
|
||||
|
||||
// Clean up
|
||||
monitor->deleteLater();
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::webserverConnectionBlocked()
|
||||
void RemoteProxyOfflineTests::configuration_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<bool>("success");
|
||||
|
||||
QTest::newRow("valid configuration") << ":/test-configuration.conf" << true;
|
||||
QTest::newRow("valid configuration chain") << ":/test-configuration-chain.conf" << true;
|
||||
QTest::newRow("faulty filename") << ":/not-exisitng-test-configuration.conf" << false;
|
||||
QTest::newRow("faulty certificate") << ":/test-configuration-faulty-certificate.conf" << false;
|
||||
QTest::newRow("faulty key") << ":/test-configuration-faulty-key.conf" << false;
|
||||
QTest::newRow("faulty chain") << ":/test-configuration-faulty-chain.conf" << false;
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::configuration()
|
||||
{
|
||||
QFETCH(QString, fileName);
|
||||
QFETCH(bool, success);
|
||||
|
||||
ProxyConfiguration configuration;
|
||||
QCOMPARE(configuration.loadConfiguration(fileName), success);
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::serverPortBlocked()
|
||||
{
|
||||
cleanUpEngine();
|
||||
|
||||
@ -117,6 +162,52 @@ void RemoteProxyOfflineTests::webserverConnectionBlocked()
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::websocketBinaryData()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
QWebSocket *client = new QWebSocket("bad-client", QWebSocketProtocol::Version13);
|
||||
connect(client, &QWebSocket::sslErrors, this, &BaseTest::sslErrors);
|
||||
QSignalSpy spyConnection(client, SIGNAL(connected()));
|
||||
client->open(Engine::instance()->webSocketServer()->serverUrl());
|
||||
spyConnection.wait();
|
||||
|
||||
// Send binary data and make sure the server disconnects this socket
|
||||
QSignalSpy spyDisconnected(client, SIGNAL(disconnected()));
|
||||
client->sendBinaryMessage("trying to upload stuff...stuff...more stuff... other stuff");
|
||||
spyConnection.wait(200);
|
||||
QVERIFY(spyConnection.count() == 1);
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::websocketPing()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
QWebSocket *client = new QWebSocket("bad-client", QWebSocketProtocol::Version13);
|
||||
connect(client, &QWebSocket::sslErrors, this, &BaseTest::sslErrors);
|
||||
QSignalSpy spyConnection(client, SIGNAL(connected()));
|
||||
client->open(Engine::instance()->webSocketServer()->serverUrl());
|
||||
spyConnection.wait();
|
||||
QVERIFY(spyConnection.count() == 1);
|
||||
|
||||
QByteArray pingMessage = QByteArray("ping!");
|
||||
QSignalSpy pongSpy(client, &QWebSocket::pong);
|
||||
client->ping(pingMessage);
|
||||
pongSpy.wait();
|
||||
QVERIFY(pongSpy.count() == 1);
|
||||
qDebug() << pongSpy.at(0).at(0) << pongSpy.at(0).at(1);
|
||||
|
||||
QVERIFY(pongSpy.at(0).at(1).toByteArray() == pingMessage);
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::getIntrospect()
|
||||
{
|
||||
// Start the server
|
||||
@ -134,9 +225,15 @@ void RemoteProxyOfflineTests::getHello()
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
QVariant response = invokeApiCall("RemoteProxy.Hello");
|
||||
QVariantMap response = invokeApiCall("RemoteProxy.Hello").toMap();
|
||||
qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
|
||||
|
||||
// Verify data
|
||||
QCOMPARE(response.value("params").toMap().value("name").toString(), Engine::instance()->configuration()->serverName());
|
||||
QCOMPARE(response.value("params").toMap().value("server").toString(), QString(SERVER_NAME_STRING));
|
||||
QCOMPARE(response.value("params").toMap().value("version").toString(), QString(SERVER_VERSION_STRING));
|
||||
QCOMPARE(response.value("params").toMap().value("apiVersion").toString(), QString(API_VERSION_STRING));
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
@ -144,30 +241,34 @@ void RemoteProxyOfflineTests::getHello()
|
||||
void RemoteProxyOfflineTests::apiBasicCalls_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("data");
|
||||
QTest::addColumn<bool>("valid");
|
||||
QTest::addColumn<int>("responseId");
|
||||
QTest::addColumn<QString>("responseStatus");
|
||||
|
||||
QTest::newRow("valid call") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\"}") << true;
|
||||
QTest::newRow("missing id") << QByteArray("{\"method\":\"RemoteProxy.Hello\"}")<< false;
|
||||
QTest::newRow("missing method") << QByteArray("{\"id\":42}") << false;
|
||||
QTest::newRow("borked") << QByteArray("{\"id\":42, \"method\":\"RemoteProx")<< false;
|
||||
QTest::newRow("invalid function") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Explode\"}") << false;
|
||||
QTest::newRow("invalid namespace") << QByteArray("{\"id\":42, \"method\":\"ProxyRemote.Hello\"}") << false;
|
||||
QTest::newRow("missing dot") << QByteArray("{\"id\":42, \"method\":\"RemoteProxyHello\"}") << false;
|
||||
QTest::newRow("invalid params") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\", \"params\":{\"törööö\":\"chooo-chooo\"}}") << false;
|
||||
QTest::newRow("valid call") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\"}") << 42 << "success";
|
||||
QTest::newRow("missing id") << QByteArray("{\"method\":\"RemoteProxy.Hello\"}") << -1 << "error";
|
||||
QTest::newRow("missing method") << QByteArray("{\"id\":42}") << 42 << "error";
|
||||
QTest::newRow("invalid json") << QByteArray("{\"id\":42, \"method\":\"RemoteProx") << -1 << "error";
|
||||
QTest::newRow("invalid function") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Explode\"}") << 42 << "error";
|
||||
QTest::newRow("invalid namespace") << QByteArray("{\"id\":42, \"method\":\"ProxyRemote.Hello\"}") << 42 << "error";
|
||||
QTest::newRow("missing dot") << QByteArray("{\"id\":42, \"method\":\"RemoteProxyHello\"}") << 42 << "error";
|
||||
QTest::newRow("invalid params") << QByteArray("{\"id\":42, \"method\":\"RemoteProxy.Hello\", \"params\":{\"törööö\":\"chooo-chooo\"}}") << 42 << "error";
|
||||
QTest::newRow("invalid authentication params") << QByteArray("{\"id\":42, \"method\":\"Authentication.Authenticate\", \"params\":{\"your\":\"mamma\"}}") << 42 << "error";
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::apiBasicCalls()
|
||||
{
|
||||
QFETCH(QByteArray, data);
|
||||
QFETCH(bool, valid);
|
||||
QFETCH(int, responseId);
|
||||
QFETCH(QString, responseStatus);
|
||||
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
QVariant response = injectSocketData(data);
|
||||
if (valid) {
|
||||
QVERIFY2(response.toMap().value("status").toString() == "success", "Call wasn't parsed correctly by nymea.");
|
||||
}
|
||||
qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
|
||||
|
||||
QCOMPARE(response.toMap().value("id").toInt(), responseId);
|
||||
QCOMPARE(response.toMap().value("status").toString(), responseStatus);
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
@ -249,7 +350,7 @@ void RemoteProxyOfflineTests::clientConnection()
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(!connection->isRemoteConnected());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateReady);
|
||||
QVERIFY(connection->error() == RemoteProxyConnection::ErrorNoError);
|
||||
QVERIFY(connection->error() == QAbstractSocket::UnknownSocketError);
|
||||
QVERIFY(connection->serverUrl() == m_serverUrl);
|
||||
QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeWebSocket);
|
||||
QVERIFY(connection->serverName() == SERVER_NAME_STRING);
|
||||
@ -263,15 +364,15 @@ void RemoteProxyOfflineTests::clientConnection()
|
||||
QVERIFY(authenticatedSpy.count() == 1);
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(connection->isAuthenticated());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateWaitTunnel);
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateAuthenticated);
|
||||
|
||||
// Disconnect and clean up
|
||||
QSignalSpy spyDisconnected(connection, &RemoteProxyConnection::disconnected);
|
||||
connection->disconnectServer();
|
||||
// FIXME: check why it waits the full time here
|
||||
spyDisconnected.wait(100);
|
||||
spyDisconnected.wait(500);
|
||||
|
||||
QVERIFY(spyDisconnected.count() == 1);
|
||||
QVERIFY(spyDisconnected.count() >= 1);
|
||||
QVERIFY(!connection->isConnected());
|
||||
|
||||
connection->deleteLater();
|
||||
@ -326,7 +427,7 @@ void RemoteProxyOfflineTests::remoteConnection()
|
||||
QVERIFY(connectionOneAuthenticatedSpy.count() == 1);
|
||||
QVERIFY(connectionOne->isConnected());
|
||||
QVERIFY(connectionOne->isAuthenticated());
|
||||
QVERIFY(connectionOne->state() == RemoteProxyConnection::StateWaitTunnel);
|
||||
QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated);
|
||||
|
||||
// Authenticate two
|
||||
QSignalSpy remoteConnectionEstablishedTwo(connectionTwo, &RemoteProxyConnection::remoteConnectionEstablished);
|
||||
@ -420,7 +521,7 @@ void RemoteProxyOfflineTests::trippleConnection()
|
||||
QVERIFY(connectionOneAuthenticatedSpy.count() == 1);
|
||||
QVERIFY(connectionOne->isConnected());
|
||||
QVERIFY(connectionOne->isAuthenticated());
|
||||
QVERIFY(connectionOne->state() == RemoteProxyConnection::StateWaitTunnel);
|
||||
QVERIFY(connectionOne->state() == RemoteProxyConnection::StateAuthenticated);
|
||||
|
||||
QSignalSpy remoteConnectionEstablishedOne(connectionOne, &RemoteProxyConnection::remoteConnectionEstablished);
|
||||
|
||||
@ -463,7 +564,8 @@ void RemoteProxyOfflineTests::sslConfigurations()
|
||||
QVERIFY(connector->connectServer(m_serverUrl));
|
||||
spyError.wait();
|
||||
QVERIFY(spyError.count() == 1);
|
||||
QVERIFY(connector->error() == RemoteProxyConnection::ErrorSocketError);
|
||||
qDebug() << connector->error();
|
||||
QCOMPARE(connector->error(), QAbstractSocket::SslHandshakeFailedError);
|
||||
QVERIFY(connector->state() == RemoteProxyConnection::StateDisconnected);
|
||||
|
||||
// Connect to server (insecue enabled)
|
||||
@ -482,14 +584,14 @@ void RemoteProxyOfflineTests::sslConfigurations()
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::timeout()
|
||||
void RemoteProxyOfflineTests::jsonRpcTimeout()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
// Configure result
|
||||
// Configure result (authentication takes longer than json rpc timeout
|
||||
m_mockAuthenticator->setExpectedAuthenticationError();
|
||||
m_mockAuthenticator->setTimeoutDuration(6000);
|
||||
m_mockAuthenticator->setTimeoutDuration(4000);
|
||||
|
||||
// Create request
|
||||
QVariantMap params;
|
||||
@ -500,6 +602,91 @@ void RemoteProxyOfflineTests::timeout()
|
||||
QVariant response = invokeApiCall("Authentication.Authenticate", params);
|
||||
qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
|
||||
|
||||
QVERIFY(response.toMap().value("status").toString() == "error");
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::inactiveTimeout()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Sleepy test client", this);
|
||||
connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
// Connect one
|
||||
QSignalSpy connectionReadySpy(connection, &RemoteProxyConnection::ready);
|
||||
QSignalSpy connectionDisconnectedSpy(connection, &RemoteProxyConnection::disconnected);
|
||||
QVERIFY(connection->connectServer(m_serverUrl));
|
||||
connectionReadySpy.wait();
|
||||
QVERIFY(connectionReadySpy.count() == 1);
|
||||
|
||||
// Now wait for disconnected
|
||||
connectionDisconnectedSpy.wait();
|
||||
QVERIFY(connectionDisconnectedSpy.count() >= 1);
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::authenticationReplyTimeout()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
// Configure result (authentication takes longer than json rpc timeout
|
||||
m_mockAuthenticator->setExpectedAuthenticationError();
|
||||
m_mockAuthenticator->setTimeoutDuration(1000);
|
||||
|
||||
m_configuration->setAuthenticationTimeout(500);
|
||||
m_configuration->setJsonRpcTimeout(1000);
|
||||
m_configuration->setInactiveTimeout(1000);
|
||||
|
||||
// Create request
|
||||
QVariantMap params;
|
||||
params.insert("uuid", QUuid::createUuid().toString());
|
||||
params.insert("name", "Sleepy test client");
|
||||
params.insert("token", "sleepy token zzzZZZ");
|
||||
|
||||
QVariant response = invokeApiCall("Authentication.Authenticate", params);
|
||||
qDebug() << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
|
||||
verifyAuthenticationError(response, Authenticator::AuthenticationErrorTimeout);
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void RemoteProxyOfflineTests::authenticationReplyConnection()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Sleepy test client", this);
|
||||
connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
// Connect one
|
||||
QSignalSpy connectionReadySpy(connection, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connection->connectServer(m_serverUrl));
|
||||
connectionReadySpy.wait();
|
||||
QVERIFY(connectionReadySpy.count() == 1);
|
||||
|
||||
// Configure result (authentication takes longer than json rpc timeout
|
||||
m_mockAuthenticator->setExpectedAuthenticationError();
|
||||
m_mockAuthenticator->setTimeoutDuration(1000);
|
||||
|
||||
m_configuration->setAuthenticationTimeout(500);
|
||||
m_configuration->setJsonRpcTimeout(1000);
|
||||
m_configuration->setInactiveTimeout(1000);
|
||||
|
||||
QSignalSpy connectionErrorSpy(connection, &RemoteProxyConnection::errorOccured);
|
||||
connection->authenticate("blub");
|
||||
connectionErrorSpy.wait();
|
||||
QVERIFY(connectionErrorSpy.count() == 1);
|
||||
QVERIFY(connectionErrorSpy.at(0).at(0).toInt() == static_cast<int>(QAbstractSocket::ProxyConnectionRefusedError));
|
||||
QVERIFY(connection->error() == QAbstractSocket::ProxyConnectionRefusedError);
|
||||
|
||||
// Clean up
|
||||
stopServer();
|
||||
}
|
||||
|
||||
@ -40,8 +40,13 @@ private slots:
|
||||
void dummyAuthenticator();
|
||||
void monitorServer();
|
||||
|
||||
void configuration_data();
|
||||
void configuration();
|
||||
|
||||
// WebSocket connection
|
||||
void webserverConnectionBlocked();
|
||||
void serverPortBlocked();
|
||||
void websocketBinaryData();
|
||||
void websocketPing();
|
||||
|
||||
// Api
|
||||
void getIntrospect();
|
||||
@ -58,7 +63,11 @@ private slots:
|
||||
void remoteConnection();
|
||||
void trippleConnection();
|
||||
void sslConfigurations();
|
||||
void timeout();
|
||||
|
||||
void jsonRpcTimeout();
|
||||
void inactiveTimeout();
|
||||
void authenticationReplyTimeout();
|
||||
void authenticationReplyConnection();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -34,7 +34,6 @@ RemoteProxyOnlineTests::RemoteProxyOnlineTests(QObject *parent) :
|
||||
BaseTest(parent)
|
||||
{
|
||||
m_authenticator = qobject_cast<Authenticator *>(m_awsAuthenticator);
|
||||
|
||||
}
|
||||
|
||||
void RemoteProxyOnlineTests::awsStaticCredentials()
|
||||
@ -53,7 +52,6 @@ void RemoteProxyOnlineTests::awsStaticCredentials()
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(!connection->isRemoteConnected());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateReady);
|
||||
QVERIFY(connection->error() == RemoteProxyConnection::ErrorNoError);
|
||||
QVERIFY(connection->serverUrl() == m_serverUrl);
|
||||
QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeWebSocket);
|
||||
QVERIFY(connection->serverName() == SERVER_NAME_STRING);
|
||||
@ -67,7 +65,7 @@ void RemoteProxyOnlineTests::awsStaticCredentials()
|
||||
QVERIFY(connection->authenticate("foobar"));
|
||||
errorSpy.wait();
|
||||
QVERIFY(errorSpy.count() == 1);
|
||||
QVERIFY(connection->error() == RemoteProxyConnection::ErrorProxyAuthenticationFailed);
|
||||
QVERIFY(connection->error() == QAbstractSocket::ProxyAuthenticationRequiredError);
|
||||
|
||||
// Disconnect and clean up
|
||||
connection->disconnectServer();
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
include(../../nymea-remoteproxy.pri)
|
||||
include(../testbase/testbase.pri)
|
||||
|
||||
|
||||
|
||||
TARGET = nymea-remoteproxy-tests-online
|
||||
|
||||
HEADERS += nymea-remoteproxy-tests-online.h
|
||||
|
||||
@ -97,12 +97,13 @@ void BaseTest::startServer()
|
||||
QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged);
|
||||
Engine::instance()->setDeveloperModeEnabled(true);
|
||||
Engine::instance()->start(m_configuration);
|
||||
runningSpy.wait();
|
||||
runningSpy.wait(100);
|
||||
QVERIFY(runningSpy.count() == 1);
|
||||
}
|
||||
|
||||
QVERIFY(Engine::instance()->running());
|
||||
QVERIFY(Engine::instance()->webSocketServer()->running());
|
||||
QVERIFY(Engine::instance()->monitorServer()->running());
|
||||
}
|
||||
|
||||
void BaseTest::stopServer()
|
||||
@ -198,7 +199,6 @@ QVariant BaseTest::injectSocketData(const QByteArray &data)
|
||||
|
||||
void BaseTest::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<RemoteProxyConnection::Error>();
|
||||
qRegisterMetaType<RemoteProxyConnection::State>();
|
||||
qRegisterMetaType<RemoteProxyConnection::ConnectionType>();
|
||||
|
||||
|
||||
@ -80,13 +80,14 @@ protected slots:
|
||||
void cleanupTestCase();
|
||||
|
||||
public slots:
|
||||
void sslErrors(const QList<QSslError> &) {
|
||||
inline void sslErrors(const QList<QSslError> &) {
|
||||
QWebSocket *socket = static_cast<QWebSocket*>(sender());
|
||||
socket->ignoreSslErrors();
|
||||
}
|
||||
|
||||
void ignoreConnectionSslError(const QList<QSslError> &) {
|
||||
inline void ignoreConnectionSslError(const QList<QSslError> &errors) {
|
||||
RemoteProxyConnection *connection = static_cast<RemoteProxyConnection *>(sender());
|
||||
connection->ignoreSslErrors(errors);
|
||||
connection->ignoreSslErrors();
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
include(../nymea-remoteproxy.pri)
|
||||
|
||||
TEMPLATE=subdirs
|
||||
SUBDIRS += test-offline test-online
|
||||
SUBDIRS += test-offline
|
||||
|
||||
online {
|
||||
message("Online tests enabled")
|
||||
SUBDIRS += test-online
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user