First working client authentication

more-debug
Simon Stürz 2018-08-10 11:53:00 +02:00
parent 06c27fb5aa
commit ca54d5b44d
18 changed files with 266 additions and 84 deletions

View File

@ -156,6 +156,74 @@ Once the other client is here and ready, the server will send a notification to
}
## The complete API
s"methods": {
"Authentication.Authenticate": {
"description": "Authenticate this connection. The returned AuthenticationError informs about the result. If the authentication was not successfull, the server will close the connection immediatly after sending the error response. The given id should be a unique id the other tunnel client can understand. Once the authentication was successfull, you can wait for the RemoteProxy.TunnelEstablished notification. If you send any data before getting this notification, the server will close the connection. If the tunnel client does not show up within 10 seconds, the server will close the connection.",
"params": {
"name": "String",
"token": "String",
"uuid": "String"
},
"returns": {
"authenticationError": "$ref:AuthenticationError"
}
},
"RemoteProxy.Hello": {
"description": "Once connected to this server, a client can get information about the server by saying Hello. The response informs the client about this proxy server.",
"params": {
},
"returns": {
"apiVersion": "String",
"name": "String",
"server": "String",
"version": "String"
}
},
"RemoteProxy.Introspect": {
"description": "Introspect this API.",
"params": {
},
"returns": {
"methods": "Object",
"notifications": "Object",
"types": "Object"
}
}
},
"notifications": {
"RemoteProxy.TunnelEstablished": {
"description": "Emitted whenever the tunnel has been established successfully. This is the last message from the remote proxy server! Any following data will be from the other tunnel client until the connection will be closed. The parameter contain some information about the other tunnel client.",
"params": {
"name": "String",
"uuid": "String"
}
}
},
"types": {
"AuthenticationError": [
"AuthenticationErrorNoError",
"AuthenticationErrorUnknown",
"AuthenticationErrorTimeout",
"AuthenticationErrorAborted",
"AuthenticationErrorAuthenticationFailed",
"AuthenticationErrorAuthenticationServerNotResponding"
],
"BasicType": [
"Uuid",
"String",
"Int",
"UInt",
"Double",
"Bool",
"Variant",
"Object"
]
}
# License
This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.

View File

@ -65,11 +65,12 @@ void AuthenticationHandler::onAuthenticationFinished()
if (authenticationReply->error() != Authenticator::AuthenticationErrorNoError) {
qCWarning(dcJsonRpc()) << "Authentication error occured" << authenticationReply->error();
jsonReply->setSuccess(true);
authenticationReply->proxyClient()->setAuthenticated(true);
} else {
authenticationReply->proxyClient()->setAuthenticated(false);
jsonReply->setSuccess(false);
authenticationReply->proxyClient()->setAuthenticated(false);
} else {
// Successfully authenticated
authenticationReply->proxyClient()->setAuthenticated(true);
jsonReply->setSuccess(true);
}
jsonReply->setData(errorToReply(authenticationReply->error()));

View File

@ -65,9 +65,9 @@ JsonReply *JsonRpcServer::Hello(const QVariantMap &params, ProxyClient *proxyCli
Q_UNUSED(proxyClient)
QVariantMap data;
data.insert("server", QCoreApplication::applicationName());
data.insert("server", SERVER_NAME_STRING);
data.insert("name", Engine::instance()->serverName());
data.insert("version", QCoreApplication::applicationVersion());
data.insert("version", SERVER_VERSION_STRING);
data.insert("apiVersion", API_VERSION_STRING);
return createReply(data);
@ -182,12 +182,12 @@ void JsonRpcServer::asyncReplyFinished()
sendResponse(proxyClient, reply->commandId(), reply->data());
if (!reply->success()) {
// Disconnect this client since the request was not successfully
proxyClient->interface()->killClientConnection(proxyClient->clientId());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "API call was not successfully.");
}
} else {
sendErrorResponse(proxyClient, reply->commandId(), "Command timed out");
// Disconnect this client since he requested something that created a timeout
proxyClient->interface()->killClientConnection(proxyClient->clientId());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "API call timeouted.");
}
}
@ -225,7 +225,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());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Invalid JSON data received.");
return;
}
@ -236,7 +236,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());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "The id property is missing in the request.");
return;
}
@ -244,7 +244,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());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Invalid method passed.");
return;
}
@ -254,13 +254,13 @@ 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());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "No such namespace.");
return;
}
if (!handler->hasMethod(method)) {
sendErrorResponse(proxyClient, commandId, "No such namespace");
proxyClient->interface()->killClientConnection(proxyClient->clientId());
sendErrorResponse(proxyClient, commandId, "No such method");
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "No such method.");
return;
}
@ -269,7 +269,7 @@ void JsonRpcServer::processData(ProxyClient *proxyClient, const QByteArray &data
QPair<bool, QString> validationResult = handler->validateParams(method, params);
if (!validationResult.first) {
sendErrorResponse(proxyClient, commandId, "Invalid params: " + validationResult.second);
proxyClient->interface()->killClientConnection(proxyClient->clientId());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Invalid params passed.");
return;
}

View File

@ -100,7 +100,7 @@ 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());
proxyClient->interface()->killClientConnection(proxyClient->clientId(), "Data received while authenticated but not remote connected.");
return;
}

View File

@ -17,7 +17,7 @@ public:
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) = 0;
virtual void killClientConnection(const QUuid &clientId, const QString &killReason) = 0;
signals:
void clientConnected(const QUuid &clientId);

View File

@ -59,14 +59,14 @@ void WebSocketServer::sendData(const QList<QUuid> &clients, const QByteArray &da
}
}
void WebSocketServer::killClientConnection(const QUuid &clientId)
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();
client->close(QWebSocketProtocol::CloseCodeBadOperation);
qCWarning(dcWebSocketServer()) << "Kill client connection" << clientId.toString() << "Reason:" << killReason;
client->close(QWebSocketProtocol::CloseCodeBadOperation, killReason);
}
void WebSocketServer::onClientConnected()

View File

@ -29,7 +29,7 @@ public:
void sendData(const QUuid &clientId, const QByteArray &data) override;
void sendData(const QList<QUuid> &clients, const QByteArray &data) override;
void killClientConnection(const QUuid &clientId) override;
void killClientConnection(const QUuid &clientId, const QString &killReason) override;
private:
QUrl m_serverUrl;

View File

@ -40,6 +40,7 @@ QVariantMap JsonReply::requestMap()
if (!m_params.isEmpty())
request.insert("params", m_params);
m_commandId++;
return request;
}

View File

@ -8,37 +8,52 @@ Q_LOGGING_CATEGORY(dcRemoteProxyClientJsonRpcTraffic, "RemoteProxyClientJsonRpcT
namespace remoteproxyclient {
JsonRpcClient::JsonRpcClient(QObject *parent) :
QObject(parent)
JsonRpcClient::JsonRpcClient(ProxyConnection *connection, QObject *parent) :
QObject(parent),
m_connection(connection)
{
}
JsonReply *JsonRpcClient::callHello()
{
JsonReply *reply = new JsonReply(m_commandId, "RemoteProxy", "Hello", QVariantMap(), this);
qCDebug(dcRemoteProxyClientJsonRpc()) << "Calling" << QString("%1.%2").arg(reply->nameSpace()).arg(reply->method());
sendRequest(reply->requestMap());
m_replies.insert(m_commandId, reply);
return reply;
}
JsonReply *JsonRpcClient::callAuthenticate(const QUuid &clientUuid, const QString &clientName, const QString &token)
{
QVariantMap params;
params.insert("name", clientName);
params.insert("uuid", clientUuid.toString());
params.insert("token", token);
JsonReply *reply = new JsonReply(m_commandId, "Authentication", "Authenticate", params, this);
qCDebug(dcRemoteProxyClientJsonRpc()) << "Calling" << QString("%1.%2").arg(reply->nameSpace()).arg(reply->method()) << params;
sendRequest(reply->requestMap());
m_replies.insert(m_commandId, reply);
return reply;
}
void JsonRpcClient::sendRequest(const QVariantMap &request)
{
m_connection->sendData(QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + '\n');
QByteArray data = QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + '\n';
qCDebug(dcRemoteProxyClientJsonRpcTraffic()) << "Sending" << qUtf8Printable(data);
m_connection->sendData(data);
}
void JsonRpcClient::onConnectedChanged(bool connected)
{
if (!connected) {
m_serverName = QString();
m_proxyServerName = QString();
m_proxyServerVersion = QString();
m_proxyApiVersion = QString();
}
Q_UNUSED(connected)
}
void JsonRpcClient::processData(const QByteArray &data)
{
qCDebug(dcRemoteProxyClientJsonRpcTraffic()) << "Received data:" << qUtf8Printable(data);
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
@ -52,15 +67,10 @@ void JsonRpcClient::processData(const QByteArray &data)
int commandId = dataMap.value("id").toInt();
JsonReply *reply = m_replies.take(commandId);
if (reply) {
reply->deleteLater();
qCDebug(dcRemoteProxyClientJsonRpcTraffic()) << QString("Got response for %1.%2: %3").arg(reply->nameSpace(),
reply->method(),
QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Indented)));
qCDebug(dcRemoteProxyClientJsonRpcTraffic()) << QString("Got response for %1.%2: %3").arg(reply->nameSpace(), reply->method(), QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Indented)));
if (dataMap.value("status").toString() == "error") {
qCWarning(dcRemoteProxyClientJsonRpc()) << "Api error happend" << dataMap.value("error").toString();
return;
}
reply->setResponse(dataMap);

View File

@ -1,6 +1,7 @@
#ifndef JSONRPCCLIENT_H
#define JSONRPCCLIENT_H
#include <QUuid>
#include <QObject>
#include <QVariantMap>
#include <QLoggingCategory>
@ -17,9 +18,10 @@ class JsonRpcClient : public QObject
{
Q_OBJECT
public:
explicit JsonRpcClient(QObject *parent = nullptr);
explicit JsonRpcClient(ProxyConnection *connection, QObject *parent = nullptr);
JsonReply *callHello();
JsonReply *callAuthenticate(const QUuid &clientUuid, const QString &clientName, const QString &token);
private:
ProxyConnection *m_connection = nullptr;
@ -28,11 +30,6 @@ private:
QHash<int, JsonReply *> m_replies;
QString m_serverName;
QString m_proxyServerName;
QString m_proxyServerVersion;
QString m_proxyApiVersion;
void sendRequest(const QVariantMap &request);
signals:

View File

@ -6,9 +6,11 @@ Q_LOGGING_CATEGORY(dcRemoteProxyClientConnectionTraffic, "RemoteProxyClientConne
namespace remoteproxyclient {
RemoteProxyConnection::RemoteProxyConnection(ConnectionType connectionType, QObject *parent) :
RemoteProxyConnection::RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, ConnectionType connectionType, QObject *parent) :
QObject(parent),
m_connectionType(connectionType)
m_connectionType(connectionType),
m_clientUuid(clientUuid),
m_clientName(clientName)
{
}
@ -54,7 +56,12 @@ QString RemoteProxyConnection::errorString() const
bool RemoteProxyConnection::isConnected() const
{
return m_state == StateConnected || m_state == StateAuthenticating || m_state == StateWaitTunnel || m_state == StateRemoteConnected;
return m_state == StateConnected
|| m_state == StateInitializing
|| m_state == StateReady
|| m_state == StateAuthenticating
|| m_state == StateWaitTunnel
|| m_state == StateRemoteConnected;
}
bool RemoteProxyConnection::isRemoteConnected() const
@ -77,6 +84,26 @@ quint16 RemoteProxyConnection::serverPort() const
return m_serverPort;
}
QString RemoteProxyConnection::serverName() const
{
return m_serverName;
}
QString RemoteProxyConnection::proxyServerName() const
{
return m_proxyServerName;
}
QString RemoteProxyConnection::proxyServerVersion() const
{
return m_proxyServerVersion;
}
QString RemoteProxyConnection::proxyServerApiVersion() const
{
return m_proxyServerApiVersion;
}
bool RemoteProxyConnection::insecureConnection() const
{
return m_insecureConnection;
@ -147,6 +174,7 @@ void RemoteProxyConnection::onConnectionChanged(bool isConnected)
setState(StateConnected);
emit connected();
setState(StateInitializing);
JsonReply *reply = m_jsonClient->callHello();
connect(reply, &JsonReply::finished, this, &RemoteProxyConnection::onHelloFinished);
}
@ -155,13 +183,20 @@ void RemoteProxyConnection::onConnectionChanged(bool isConnected)
void RemoteProxyConnection::onConnectionDataAvailable(const QByteArray &data)
{
switch (m_state) {
case StateConnecting:
case StateConnected:
case StateInitializing:
case StateReady:
case StateAuthenticating:
m_jsonClient->processData(data);
break;
case StateRemoteConnected:
// Remote data arrived
emit dataReady(data);
break;
default:
qCDebug(dcRemoteProxyClientConnection()) << "Unhandled: Data reviced" << data;
qCWarning(dcRemoteProxyClientConnection()) << "Unhandled: Data reviced" << data;
break;
}
}
@ -178,15 +213,35 @@ void RemoteProxyConnection::onConnectionSslError()
void RemoteProxyConnection::onHelloFinished()
{
JsonReply *reply = static_cast<JsonReply *>(sender());
reply->deleteLater();
QVariantMap response = reply->response();
qCDebug(dcRemoteProxyClientConnection()) << "Hello response ready" << response;
if (response.value("status").toString() != "success") {
qCWarning(dcRemoteProxyClientConnection()) << "Could not get initial information from proxy server.";
m_connection->disconnectServer();
return;
}
QVariantMap responseParams = response.value("params").toMap();
// TODO: verify success
m_serverName = response.value("server").toString();
m_proxyServerName = response.value("name").toString();
m_proxyServerVersion = response.value("version").toString();
m_proxyServerApiVersion = response.value("apiVersion").toString();
setState(StateReady);
emit ready();
}
void RemoteProxyConnection::onAuthenticateFinished()
{
JsonReply *reply = static_cast<JsonReply *>(sender());
QVariantMap response = reply->response();
qCDebug(dcRemoteProxyClientConnection()) << "Hello response ready" << response;
qCDebug(dcRemoteProxyClientConnection()) << "Authentication response ready" << response;
}
bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, quint16 port)
@ -216,9 +271,9 @@ bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, qui
connect(m_connection, &ProxyConnection::errorOccured, this, &RemoteProxyConnection::onConnectionSocketError);
connect(m_connection, &ProxyConnection::sslErrorOccured, this, &RemoteProxyConnection::onConnectionSslError);
m_jsonClient = new JsonRpcClient(this);
m_jsonClient = new JsonRpcClient(m_connection, this);
qCDebug(dcRemoteProxyClientConnection()) << "Connecting to" << QString("%1:%2").arg(serverAddress.toString()).arg(port);
qCDebug(dcRemoteProxyClientConnection()) << "Connecting to" << m_connection->serverUrl().toString();
m_connection->connectServer(serverAddress, port);
setState(StateConnecting);
@ -226,6 +281,19 @@ bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, qui
return true;
}
bool RemoteProxyConnection::authenticate(const QString &token)
{
if (m_state != StateReady) {
qCWarning(dcRemoteProxyClientConnection()) << "Could not authenticate. The connection is not ready";
return false;
}
qCDebug(dcRemoteProxyClientConnection()) << "Start authentication using token" << token;
JsonReply *reply = m_jsonClient->callAuthenticate(m_clientUuid, m_clientName, token);
connect(reply, &JsonReply::finished, this, &RemoteProxyConnection::onAuthenticateFinished);
return true;
}
void RemoteProxyConnection::disconnectServer()
{
if (m_connection)

View File

@ -1,6 +1,7 @@
#ifndef REMOTEPROXYCONNECTOR_H
#define REMOTEPROXYCONNECTOR_H
#include <QUuid>
#include <QDebug>
#include <QObject>
#include <QWebSocket>
@ -27,6 +28,8 @@ public:
enum State {
StateConnecting,
StateConnected,
StateInitializing,
StateReady,
StateAuthenticating,
StateWaitTunnel,
StateRemoteConnected,
@ -43,11 +46,10 @@ public:
};
Q_ENUM(Error)
explicit RemoteProxyConnection(ConnectionType connectionType = ConnectionTypeWebSocket, QObject *parent = nullptr);
explicit RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, ConnectionType connectionType = ConnectionTypeWebSocket, QObject *parent = nullptr);
~RemoteProxyConnection();
RemoteProxyConnection::State state() const;
RemoteProxyConnection::Error error() const;
QString errorString() const;
@ -58,6 +60,11 @@ public:
QHostAddress serverAddress() const;
quint16 serverPort() const;
QString serverName() const;
QString proxyServerName() const;
QString proxyServerVersion() const;
QString proxyServerApiVersion() const;
bool insecureConnection() const;
void setInsecureConnection(bool insecureConnection);
@ -65,16 +72,27 @@ public:
private:
ConnectionType m_connectionType = ConnectionTypeWebSocket;
QUuid m_clientUuid;
QString m_clientName;
QHostAddress m_serverAddress;
quint16 m_serverPort = 443;
State m_state = StateDisconnected;
Error m_error = ErrorNoError;
bool m_insecureConnection = false;
bool m_remoteConnected = false;
JsonRpcClient *m_jsonClient = nullptr;
ProxyConnection *m_connection = nullptr;
// Server information
QString m_serverName;
QString m_proxyServerName;
QString m_proxyServerVersion;
QString m_proxyServerApiVersion;
void cleanUp();
void setState(State state);
@ -83,6 +101,7 @@ private:
signals:
void connected();
void disconnected();
void ready();
void remoteConnectedChanged(bool remoteConnected);
void stateChanged(RemoteProxyConnection::State state);
void errorOccured(RemoteProxyConnection::Error error);
@ -100,6 +119,7 @@ private slots:
public slots:
bool connectServer(const QHostAddress &serverAddress, quint16 port);
bool authenticate(const QString &token);
void disconnectServer();
};

View File

@ -7,10 +7,7 @@ namespace remoteproxyclient {
WebSocketConnection::WebSocketConnection(QObject *parent) :
ProxyConnection(parent)
{
m_webSocket = new QWebSocket("libnymea-remoteproxyclient", QWebSocketProtocol::VersionLatest, this);
if (allowSslErrors())
m_webSocket->ignoreSslErrors();
m_webSocket = new QWebSocket("libnymea-remoteproxyclient", QWebSocketProtocol::Version13, this);
connect(m_webSocket, &QWebSocket::connected, this, &WebSocketConnection::onConnected);
connect(m_webSocket, &QWebSocket::disconnected, this, &WebSocketConnection::onDisconnected);
@ -24,7 +21,7 @@ WebSocketConnection::WebSocketConnection(QObject *parent) :
WebSocketConnection::~WebSocketConnection()
{
disconnectServer();
}
QUrl WebSocketConnection::serverUrl() const
@ -69,6 +66,7 @@ void WebSocketConnection::onSslError(const QList<QSslError> &errors)
foreach (const QSslError sslError, errors) {
qCWarning(dcRemoteProxyClientWebSocket()) << " -->" << static_cast<int>(sslError.error()) << sslError.errorString();
}
emit sslErrorOccured();
}
}
@ -89,10 +87,14 @@ void WebSocketConnection::onBinaryMessageReceived(const QByteArray &message)
void WebSocketConnection::connectServer(const QHostAddress &address, quint16 port)
{
if (isConnected()) {
m_webSocket->close();
}
QUrl url;
url.setScheme("wss");
url.setHost(address.toString());
url.port(port);
url.setPort(port);
m_serverUrl = url;

View File

@ -1,10 +1,15 @@
QT *= network websockets
QT -= gui
# define protocol versions
# Define versions
SERVER_NAME=nymea-remoteproxy
API_VERSION_MAJOR=0
API_VERSION_MINOR=1
DEFINES += API_VERSION_STRING=\\\"$${API_VERSION_MAJOR}.$${API_VERSION_MINOR}\\\"
SERVER_VERSION=0.0.1
DEFINES += SERVER_NAME_STRING=\\\"$${SERVER_NAME}\\\" \
SERVER_VERSION_STRING=\\\"$${SERVER_VERSION}\\\" \
API_VERSION_STRING=\\\"$${API_VERSION_MAJOR}.$${API_VERSION_MINOR}\\\"
CONFIG += c++11 console
@ -15,8 +20,6 @@ top_srcdir=$$PWD
top_builddir=$$shadowed($$PWD)
coverage {
message("Building with coverage report")
# Note: this works only if you build in the source dir
OBJECTS_DIR =
MOC_DIR =

View File

@ -5,3 +5,11 @@ SUBDIRS += server libnymea-remoteproxy libnymea-remoteproxyclient tests
server.depends = libnymea-remoteproxy
tests.depends = libnymea-remoteproxy libnymea-remoteproxyclient
message("----------------------------------------------------------")
message("Building nymea-remoteproxy $${SERVER_VERSION}")
message("----------------------------------------------------------")
message("JSON-RPC API version $${API_VERSION_MAJOR}.$${API_VERSION_MINOR}")
message("Qt version:" $$[QT_VERSION])
coverage { message("Building with coverage report") }

View File

@ -85,9 +85,9 @@ int main(int argc, char *argv[])
qInstallMessageHandler(consoleLogHandler);
QCoreApplication application(argc, argv);
application.setApplicationName("nymea-remoteproxy");
application.setApplicationName(SERVER_NAME_STRING);
application.setOrganizationName("guh");
application.setApplicationVersion("0.0.1");
application.setApplicationVersion(SERVER_VERSION_STRING);
s_loggingFilters.insert("Engine", true);
s_loggingFilters.insert("Application", true);
@ -101,9 +101,15 @@ int main(int argc, char *argv[])
// command line parser
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
parser.setApplicationDescription(QString("\nThe nymea remote proxy server. This server allowes nymea-cloud users and "
"registered nymea deamons to establish a tunnel connection.\n\n"
"Copyright %1 2018 Simon Stürz <simon.stuerz@guh.io>").arg(QChar(0xA9)));
"Server version: %1\n"
"API version: %2\n\n"
"Copyright %3 2018 Simon Stürz <simon.stuerz@guh.io>\n")
.arg(SERVER_VERSION_STRING)
.arg(API_VERSION_STRING)
.arg(QChar(0xA9)));
QCommandLineOption logfileOption(QStringList() << "l" << "logging", "Write log file to the given logfile.",
"logfile", "/var/log/nymea-remoteproxy.log");

View File

@ -112,21 +112,9 @@ QVariant RemoteProxyTests::invokeApiCall(const QString &method, const QVariantMa
return QVariant();
}
// QSignalSpy disconnectedSpy(socket, SIGNAL(disconnected()));
QSignalSpy dataSpy(socket, SIGNAL(textMessageReceived(QString)));
socket->sendTextMessage(QString(jsonDoc.toJson(QJsonDocument::Compact)));
dataSpy.wait();
// if (remainsConnected) {
// disconnectedSpy.wait(1000);
// if (socket->state() != QAbstractSocket::UnconnectedState) {
// qWarning() << "!!!!!!!!!!!!! socket still connected but should be disconnected!";
// }
// } else {
// disconnectedSpy.wait();
// if (socket->state() != QAbstractSocket::ConnectedState) {
// qWarning() << "!!!!!!!!!!!!! socket not connected but should be!";
// }
// }
socket->close();
socket->deleteLater();
@ -365,14 +353,23 @@ void RemoteProxyTests::clientConnection()
startServer();
// Connect to the server (insecure disabled)
RemoteProxyConnection *connectorOne = new RemoteProxyConnection(RemoteProxyConnection::ConnectionTypeWebSocket, this);
RemoteProxyConnection *connectorOne = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", RemoteProxyConnection::ConnectionTypeWebSocket, this);
connectorOne->setInsecureConnection(true);
// Connect to server (insecue enabled for testing)
QSignalSpy spyConnected(connectorOne, &RemoteProxyConnection::connected);
connectorOne->connectServer(QHostAddress::LocalHost, m_port);
spyConnected.wait();
//QVERIFY(connectorOne->isConnected());
QSignalSpy readySpy(connectorOne, &RemoteProxyConnection::ready);
QVERIFY(connectorOne->connectServer(QHostAddress::LocalHost, m_port));
readySpy.wait();
QVERIFY(readySpy.count() == 1);
QVERIFY(connectorOne->isConnected());
QVERIFY(connectorOne->state() == RemoteProxyConnection::StateReady);
// Authenticate
m_authenticator->setTimeoutDuration(100);
m_authenticator->setExpectedAuthenticationError();
connectorOne->authenticate("foobar");
QTest::qWait(1000);
// Disconnect and clean up
QSignalSpy spyDisconnected(connectorOne, &RemoteProxyConnection::disconnected);

View File

@ -63,11 +63,12 @@ private slots:
void authenticate();
// Client lib
void clientConnection();
void sslConfigurations();
void timeout();
void clientConnection();
public slots:
void sslErrors(const QList<QSslError> &) {
QWebSocket *socket = static_cast<QWebSocket*>(sender());