Add first version of remote client connector in tests
parent
8b14e3bc06
commit
43ebf38f30
|
|
@ -1,5 +1,4 @@
|
|||
#include "engine.h"
|
||||
#include "websocketserver.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
Engine *Engine::s_instance = nullptr;
|
||||
|
|
@ -34,22 +33,20 @@ void Engine::start()
|
|||
if (!m_running)
|
||||
qCDebug(dcEngine()) << "Start server engine";
|
||||
|
||||
QUrl proxyUrl;
|
||||
proxyUrl.setScheme("wss");
|
||||
proxyUrl.setHost(m_webSocketServerHostAddress.toString());
|
||||
proxyUrl.setPort(m_webSocketServerPort);
|
||||
|
||||
qCDebug(dcApplication()) << "Authentication server" << m_authenticationServerUrl.toString();
|
||||
qCDebug(dcApplication()) << "Start server" << proxyUrl.toString();
|
||||
|
||||
qCDebug(dcEngine()) << "Starting websocket server";
|
||||
// Init WebSocketServer
|
||||
if (m_webSocketServer) {
|
||||
delete m_webSocketServer;
|
||||
m_webSocketServer = nullptr;
|
||||
}
|
||||
|
||||
QUrl websocketServerUrl;
|
||||
websocketServerUrl.setScheme("wss");
|
||||
websocketServerUrl.setHost(m_webSocketServerHostAddress.toString());
|
||||
websocketServerUrl.setPort(m_webSocketServerPort);
|
||||
|
||||
m_webSocketServer = new WebSocketServer(m_sslConfiguration, this);
|
||||
m_webSocketServer->setServerUrl(proxyUrl);
|
||||
m_webSocketServer->setServerUrl(websocketServerUrl);
|
||||
m_webSocketServer->startServer();
|
||||
|
||||
setRunning(true);
|
||||
|
|
@ -106,6 +103,11 @@ void Engine::setAuthenticationServerUrl(const QUrl &url)
|
|||
m_authenticationServerUrl = url;
|
||||
}
|
||||
|
||||
WebSocketServer *Engine::webSocketServer() const
|
||||
{
|
||||
return m_webSocketServer;
|
||||
}
|
||||
|
||||
Engine::Engine(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <QHostAddress>
|
||||
#include <QSslConfiguration>
|
||||
|
||||
class WebSocketServer;
|
||||
#include "websocketserver.h"
|
||||
|
||||
class Engine : public QObject
|
||||
{
|
||||
|
|
@ -27,6 +27,8 @@ public:
|
|||
void setSslConfiguration(const QSslConfiguration &configuration);
|
||||
void setAuthenticationServerUrl(const QUrl &url);
|
||||
|
||||
WebSocketServer *webSocketServer() const;
|
||||
|
||||
private:
|
||||
explicit Engine(QObject *parent = nullptr);
|
||||
~Engine();
|
||||
|
|
|
|||
|
|
@ -4,3 +4,254 @@ RemoteProxyConnector::RemoteProxyConnector(QObject *parent) : QObject(parent)
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
RemoteProxyConnector::~RemoteProxyConnector()
|
||||
{
|
||||
disconnectServer();
|
||||
}
|
||||
|
||||
RemoteProxyConnector::Error RemoteProxyConnector::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
QString RemoteProxyConnector::errorString() const
|
||||
{
|
||||
QString errorString;
|
||||
switch (m_error) {
|
||||
case ErrorNoError:
|
||||
errorString = "";
|
||||
break;
|
||||
case ErrorSocketError:
|
||||
errorString = "Socket connection error occured: " + socketErrorString();
|
||||
break;
|
||||
case ErrorSslError:
|
||||
errorString = "Socket 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;
|
||||
}
|
||||
|
||||
QAbstractSocket::SocketError RemoteProxyConnector::socketError() const
|
||||
{
|
||||
if (!m_webSocket)
|
||||
return QAbstractSocket::UnknownSocketError;
|
||||
|
||||
return m_webSocket->error();
|
||||
}
|
||||
|
||||
QString RemoteProxyConnector::socketErrorString() const
|
||||
{
|
||||
if (!m_webSocket)
|
||||
return QString();
|
||||
|
||||
return m_webSocket->errorString();
|
||||
}
|
||||
|
||||
QUrl RemoteProxyConnector::serverUrl() const
|
||||
{
|
||||
QUrl serverUrl;
|
||||
serverUrl.setScheme("wss");
|
||||
serverUrl.setHost(m_serverAddress.toString());
|
||||
serverUrl.setPort(m_serverPort);
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnector::isConnected() const
|
||||
{
|
||||
return m_state == StateConnected;
|
||||
}
|
||||
|
||||
RemoteProxyConnector::ConnectionType RemoteProxyConnector::connectionType() const
|
||||
{
|
||||
return m_connectionType;
|
||||
}
|
||||
|
||||
QHostAddress RemoteProxyConnector::serverAddress() const
|
||||
{
|
||||
return m_serverAddress;
|
||||
}
|
||||
|
||||
quint16 RemoteProxyConnector::serverPort() const
|
||||
{
|
||||
return m_serverPort;
|
||||
}
|
||||
|
||||
QList<QSslError> RemoteProxyConnector::ignoreSslErrors() const
|
||||
{
|
||||
return m_ignoreSslErrors;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::setIgnoreSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
m_ignoreSslErrors = errors;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnector::sendData(const QByteArray &data)
|
||||
{
|
||||
if (m_state != StateTunnelEstablished) {
|
||||
qWarning() << "RemoteProxyClient: There is no established tunnel for" << serverUrl().toString() << "yet.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_webSocket) {
|
||||
qWarning() << "RemoteProxyClient: There is no websocket";
|
||||
return false;
|
||||
}
|
||||
|
||||
qint64 dataSendCount = m_webSocket->sendTextMessage(QString::fromUtf8(data));
|
||||
if (dataSendCount != data.count()) {
|
||||
qWarning() << "RemoteProxyClient: Could not send all data to" << serverUrl().toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::setState(RemoteProxyConnector::State state)
|
||||
{
|
||||
if (m_state == state)
|
||||
return;
|
||||
|
||||
qDebug() << "RemoteProxyClient: State changed" << state;
|
||||
m_state = state;
|
||||
emit stateChanged(m_state);
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::setError(RemoteProxyConnector::Error error)
|
||||
{
|
||||
if (m_error == error)
|
||||
return;
|
||||
|
||||
qDebug() << "RemoteProxyClient: Error occured" << error;
|
||||
m_error = error;
|
||||
emit errorOccured(m_error);
|
||||
}
|
||||
|
||||
|
||||
void RemoteProxyConnector::setConnectionType(RemoteProxyConnector::ConnectionType type)
|
||||
{
|
||||
m_connectionType = type;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::setServerAddress(const QHostAddress serverAddress)
|
||||
{
|
||||
m_serverAddress = serverAddress;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::setServerPort(quint16 serverPort)
|
||||
{
|
||||
m_serverPort = serverPort;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onSocketConnected()
|
||||
{
|
||||
setState(StateConnected);
|
||||
qDebug() << "RemoteProxyClient: Connected to" << serverUrl().toString();
|
||||
|
||||
// TODO: start authentication process
|
||||
|
||||
setState(StateAuthenticating);
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onSocketDisconnected()
|
||||
{
|
||||
qDebug() << "RemoteProxyClient: Disconnected from" << serverUrl().toString();
|
||||
setState(StateDisconnected);
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onSocketError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qWarning() << "RemoteProxyClient: Socket error occured" << error;
|
||||
setError(ErrorSocketError);
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onSocketSslError(const QList<QSslError> &errors)
|
||||
{
|
||||
qWarning() << "RemoteProxyClient: Socket ssl errors occured" << errors;
|
||||
foreach (const QSslError sslError, errors) {
|
||||
qWarning() << "RemoteProxyClient: " << static_cast<int>(sslError.error()) << sslError.errorString();
|
||||
}
|
||||
|
||||
qDebug() << m_ignoreSslErrors;
|
||||
|
||||
m_webSocket->ignoreSslErrors();
|
||||
setError(ErrorSslError);
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onSocketStateChanged(QAbstractSocket::SocketState state)
|
||||
{
|
||||
qDebug() << "RemoteProxyClient: Socket state changed" << state;
|
||||
switch (state) {
|
||||
case QAbstractSocket::ConnectingState:
|
||||
case QAbstractSocket::HostLookupState:
|
||||
setState(StateConnecting);
|
||||
break;
|
||||
case QAbstractSocket::ConnectedState:
|
||||
setState(StateConnected);
|
||||
break;
|
||||
default:
|
||||
setState(StateDisconnected);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onTextMessageReceived(const QString &message)
|
||||
{
|
||||
// TODO: check if tunnel is established, if so, emit data received
|
||||
qDebug() << "RemoteProxyClient: Data recived" << message;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::onBinaryMessageReceived(const QByteArray &message)
|
||||
{
|
||||
Q_UNUSED(message);
|
||||
}
|
||||
|
||||
bool RemoteProxyConnector::connectServer(RemoteProxyConnector::ConnectionType type, const QHostAddress &serverAddress, quint16 port)
|
||||
{
|
||||
setConnectionType(type);
|
||||
setServerAddress(serverAddress);
|
||||
setServerPort(port);
|
||||
|
||||
switch (m_connectionType) {
|
||||
// TODO: currently only websocket support
|
||||
case ConnectionTypeWebSocket:
|
||||
if (m_webSocket) {
|
||||
delete m_webSocket;
|
||||
m_webSocket = nullptr;
|
||||
}
|
||||
|
||||
setState(StateDisconnected);
|
||||
|
||||
m_webSocket = new QWebSocket("libnymea-remoteproxyclient", QWebSocketProtocol::VersionLatest, this);
|
||||
m_webSocket->ignoreSslErrors(m_ignoreSslErrors);
|
||||
|
||||
connect(m_webSocket, &QWebSocket::connected, this, &RemoteProxyConnector::onSocketConnected);
|
||||
connect(m_webSocket, &QWebSocket::disconnected, this, &RemoteProxyConnector::onSocketDisconnected);
|
||||
connect(m_webSocket, &QWebSocket::textMessageReceived, this, &RemoteProxyConnector::onTextMessageReceived);
|
||||
connect(m_webSocket, &QWebSocket::binaryMessageReceived, this, &RemoteProxyConnector::onBinaryMessageReceived);
|
||||
|
||||
connect(m_webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
|
||||
connect(m_webSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(onSocketSslError(QList<QSslError>)));
|
||||
connect(m_webSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
|
||||
|
||||
setState(StateConnecting);
|
||||
m_webSocket->open(serverUrl());
|
||||
qDebug() << "RemoteProxyClient: Start connecting to" << serverUrl().toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RemoteProxyConnector::disconnectServer()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,101 @@
|
|||
#define REMOTEPROXYCONNECTOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QWebSocket>
|
||||
#include <QHostAddress>
|
||||
|
||||
class RemoteProxyConnector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ConnectionType {
|
||||
ConnectionTypeWebSocket
|
||||
};
|
||||
Q_ENUM(ConnectionType)
|
||||
|
||||
enum State {
|
||||
StateConnecting,
|
||||
StateConnected,
|
||||
StateAuthenticating,
|
||||
StateWaitTunnel,
|
||||
StateTunnelEstablished,
|
||||
StateDisconnected
|
||||
};
|
||||
Q_ENUM(State)
|
||||
|
||||
enum Error {
|
||||
ErrorNoError,
|
||||
ErrorSocketError,
|
||||
ErrorSslError,
|
||||
ErrorProxyNotResponding,
|
||||
ErrorProxyAuthenticationFailed
|
||||
};
|
||||
Q_ENUM(Error)
|
||||
|
||||
explicit RemoteProxyConnector(QObject *parent = nullptr);
|
||||
~RemoteProxyConnector();
|
||||
|
||||
State state() const;
|
||||
|
||||
Error error() const;
|
||||
QString errorString() const;
|
||||
|
||||
QAbstractSocket::SocketError socketError() const;
|
||||
QString socketErrorString() const;
|
||||
|
||||
QUrl serverUrl() const;
|
||||
|
||||
bool isConnected() const;
|
||||
bool tunnelEstablished() const;
|
||||
|
||||
ConnectionType connectionType() const;
|
||||
QHostAddress serverAddress() const;
|
||||
quint16 serverPort() const;
|
||||
|
||||
QList<QSslError> ignoreSslErrors() const;
|
||||
void setIgnoreSslErrors(const QList<QSslError> &errors);
|
||||
|
||||
bool sendData(const QByteArray &data);
|
||||
|
||||
private:
|
||||
ConnectionType m_connectionType = ConnectionTypeWebSocket;
|
||||
QHostAddress m_serverAddress;
|
||||
quint16 m_serverPort = 443;
|
||||
State m_state = StateDisconnected;
|
||||
Error m_error = ErrorNoError;
|
||||
QList<QSslError> m_ignoreSslErrors;
|
||||
bool m_tunnelEstablished = false;
|
||||
QWebSocket *m_webSocket = nullptr;
|
||||
|
||||
void setState(State state);
|
||||
void setError(Error error);
|
||||
|
||||
void setConnectionType(ConnectionType type);
|
||||
void setServerAddress(const QHostAddress serverAddress);
|
||||
void setServerPort(quint16 serverPort);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void tunnelEstablished();
|
||||
void stateChanged(State state);
|
||||
void errorOccured(Error error);
|
||||
|
||||
void dataReady(const QByteArray &data);
|
||||
|
||||
private slots:
|
||||
void onSocketConnected();
|
||||
void onSocketDisconnected();
|
||||
void onSocketError(QAbstractSocket::SocketError error);
|
||||
void onSocketSslError(const QList<QSslError> &errors);
|
||||
void onSocketStateChanged(QAbstractSocket::SocketState state);
|
||||
void onTextMessageReceived(const QString &message);
|
||||
void onBinaryMessageReceived(const QByteArray &message);
|
||||
|
||||
|
||||
public slots:
|
||||
bool connectServer(ConnectionType type, const QHostAddress &serverAddress, quint16 port);
|
||||
void disconnectServer();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ int main(int argc, char *argv[])
|
|||
s_loggingFilters.insert("Engine", true);
|
||||
s_loggingFilters.insert("JsonRpc", true);
|
||||
s_loggingFilters.insert("WebSocketServer", true);
|
||||
s_loggingFilters.insert("WebSocketServerTraffic", false);
|
||||
s_loggingFilters.insert("Authenticator", true);
|
||||
s_loggingFilters.insert("ConnectionManager", true);
|
||||
s_loggingFilters.insert("Debug", false);
|
||||
|
|
@ -97,25 +98,31 @@ int main(int argc, char *argv[])
|
|||
// command line parser
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
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"
|
||||
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)));
|
||||
|
||||
QCommandLineOption logfileOption(QStringList() << "l" << "logging", "Write log file to the given logfile.", "logfile", "/var/log/nymea-remoteproxy.log");
|
||||
QCommandLineOption logfileOption(QStringList() << "l" << "logging", "Write log file to the given logfile.",
|
||||
"logfile", "/var/log/nymea-remoteproxy.log");
|
||||
parser.addOption(logfileOption);
|
||||
|
||||
QCommandLineOption serverOption(QStringList() << "s" << "server", "The server address this proxy will listen on. Default is 127.0.0.1", "hostaddress", "127.0.0.1");
|
||||
QCommandLineOption serverOption(QStringList() << "s" << "server", "The server address this proxy will listen on. "
|
||||
"Default is 127.0.0.1", "hostaddress", "127.0.0.1");
|
||||
parser.addOption(serverOption);
|
||||
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", "The proxy server port. Default is 1212", "port", "1212");
|
||||
parser.addOption(portOption);
|
||||
|
||||
QCommandLineOption certOption(QStringList() << "c" <<"certificate", "The path to the SSL certificate used for this proxy server.", "certificate");
|
||||
QCommandLineOption certOption(QStringList() << "c" <<"certificate", "The path to the SSL certificate used for "
|
||||
"this proxy server.", "certificate");
|
||||
parser.addOption(certOption);
|
||||
|
||||
QCommandLineOption certKeyOption(QStringList() << "k" << "certificate-key", "The path to the SSL certificate key used for this proxy server.", "certificate-key");
|
||||
QCommandLineOption certKeyOption(QStringList() << "k" << "certificate-key", "The path to the SSL certificate key "
|
||||
"used for this proxy server.", "certificate-key");
|
||||
parser.addOption(certKeyOption);
|
||||
|
||||
QCommandLineOption authenticationUrlOption(QStringList() << "a" << "authentication-server", "The server url of the AWS authentication server.", "url", "https://127.0.0.1");
|
||||
QCommandLineOption authenticationUrlOption(QStringList() << "a" << "authentication-server",
|
||||
"The server url of the AWS authentication server.", "url", "https://127.0.0.1");
|
||||
parser.addOption(authenticationUrlOption);
|
||||
|
||||
QCommandLineOption verboseOption(QStringList() << "v" << "verbose", "Print more verbose.");
|
||||
|
|
@ -123,8 +130,10 @@ int main(int argc, char *argv[])
|
|||
|
||||
parser.process(application);
|
||||
|
||||
if (parser.isSet(verboseOption))
|
||||
if (parser.isSet(verboseOption)) {
|
||||
s_loggingFilters["Debug"] = true;
|
||||
s_loggingFilters["WebSocketServerTraffic"] = true;
|
||||
}
|
||||
|
||||
QLoggingCategory::installFilter(loggingCategoryFilter);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include "engine.h"
|
||||
#include "loggingcategories.h"
|
||||
#include "remoteproxyconnector.h"
|
||||
|
||||
#include <QSignalSpy>
|
||||
|
||||
RemoteProxyTests::RemoteProxyTests(QObject *parent) :
|
||||
QObject(parent)
|
||||
|
|
@ -54,7 +57,6 @@ void RemoteProxyTests::startServer()
|
|||
Engine::instance()->setWebSocketServerHostAddress(QHostAddress::LocalHost);
|
||||
Engine::instance()->setSslConfiguration(m_sslConfiguration);
|
||||
Engine::instance()->start();
|
||||
|
||||
}
|
||||
|
||||
void RemoteProxyTests::initTestCase()
|
||||
|
|
@ -71,9 +73,19 @@ void RemoteProxyTests::cleanupTestCase()
|
|||
|
||||
void RemoteProxyTests::authenticate()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
// Connect to the server
|
||||
RemoteProxyConnector *connector = new RemoteProxyConnector(this);
|
||||
connector->setIgnoreSslErrors(QList<QSslError>() << QSslError::HostNameMismatch << QSslError::SelfSignedCertificate);
|
||||
|
||||
QSignalSpy spy(connector, &RemoteProxyConnector::error);
|
||||
connector->connectServer(RemoteProxyConnector::ConnectionTypeWebSocket, QHostAddress::LocalHost, m_port);
|
||||
//spy.wait();
|
||||
|
||||
connector->disconnectServer();
|
||||
connector->deleteLater();
|
||||
Engine::instance()->stop();
|
||||
}
|
||||
|
||||
|
|
@ -94,4 +106,22 @@ void RemoteProxyTests::startStopServer()
|
|||
QVERIFY(!Engine::exists());
|
||||
}
|
||||
|
||||
void RemoteProxyTests::sslConfigurations()
|
||||
{
|
||||
// Start the server
|
||||
startServer();
|
||||
|
||||
// Connect to the server
|
||||
RemoteProxyConnector *connector = new RemoteProxyConnector(this);
|
||||
connector->setIgnoreSslErrors(QList<QSslError>() << QSslError::HostNameMismatch << QSslError::SelfSignedCertificate);
|
||||
|
||||
QSignalSpy spy(connector, &RemoteProxyConnector::connected);
|
||||
connector->connectServer(RemoteProxyConnector::ConnectionTypeWebSocket, QHostAddress::LocalHost, m_port);
|
||||
spy.wait();
|
||||
|
||||
connector->disconnectServer();
|
||||
connector->deleteLater();
|
||||
Engine::instance()->stop();
|
||||
}
|
||||
|
||||
QTEST_MAIN(RemoteProxyTests)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef NYMEA_REMOTEPROXY_TESTS_H
|
||||
#define NYMEA_REMOTEPROXY_TESTS_H
|
||||
|
||||
#include <QUrl>
|
||||
#include <QtTest>
|
||||
#include <QSslKey>
|
||||
#include <QObject>
|
||||
|
|
@ -31,6 +32,7 @@ protected slots:
|
|||
private slots:
|
||||
void startStopServer();
|
||||
void authenticate();
|
||||
void sslConfigurations();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ QT += testlib
|
|||
|
||||
TARGET = nymea-remoteproxy-tests
|
||||
|
||||
INCLUDEPATH += ../libnymea-remoteproxy
|
||||
LIBS += -L$$top_builddir/libnymea-remoteproxy/ -lnymea-remoteproxy
|
||||
INCLUDEPATH += ../libnymea-remoteproxy ../libnymea-remoteproxyclient
|
||||
LIBS += -L$$top_builddir/libnymea-remoteproxy/ -lnymea-remoteproxy \
|
||||
-L$$top_builddir/libnymea-remoteproxyclient/ -lnymea-remoteproxyclient \
|
||||
|
||||
RESOURCES += certificate.qrc
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue