Add basic websocket server.
This commit is contained in:
parent
e892fe2b46
commit
8b14e3bc06
28
README.md
28
README.md
@ -22,8 +22,8 @@ In the build directory you can find the resulting library and binary files.
|
|||||||
If you want to start the proxy server from the build directory, you need to export the library path before starting the application:
|
If you want to start the proxy server from the build directory, you need to export the library path before starting the application:
|
||||||
|
|
||||||
|
|
||||||
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/libnymea-remoteproxy
|
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/libnymea-remoteproxy:$(pwd)/libnymea-remoteproxyclient
|
||||||
$ ./server/nymea-remoteproxy
|
$ ./server/nymea-remoteproxy -c ../nymea-remoteproxy/tests/test-certificate.crt -k ../nymea-remoteproxy/tests/test-certificate.key
|
||||||
|
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
@ -46,24 +46,28 @@ In order to get information about the server you can start the command with the
|
|||||||
|
|
||||||
$ nymea-remoteproxy --help
|
$ nymea-remoteproxy --help
|
||||||
|
|
||||||
usage: nymea-remoteproxy [options]
|
Usage: nymea-remoteproxy [options]
|
||||||
|
|
||||||
The nymea remote proxy server.
|
The nymea remote proxy server. This server allowes nymea-cloud users and registered nymea deamons to establish a tunnel connection.
|
||||||
|
|
||||||
Copyright © 2018 Simon Stürz <simon.stuerz@guh.io>
|
Copyright © 2018 Simon Stürz <simon.stuerz@guh.io>
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h, --help Displays this help.
|
-h, --help Displays this help.
|
||||||
-l, --logging <logfile> Write log file to the given logfile.
|
-l, --logging <logfile> Write log file to the given logfile.
|
||||||
-s, --server <url> The authentication server url.
|
-s, --server <hostaddress> The server address this proxy will
|
||||||
-p, --port <port> The proxy server port.
|
listen on. Default is 127.0.0.1
|
||||||
-c, --certificate <certificate> The path to the SSL certificate.
|
-p, --port <port> The proxy server port. Default is
|
||||||
|
1212
|
||||||
|
-c, --certificate <certificate> The path to the SSL certificate used
|
||||||
|
for this proxy server.
|
||||||
-k, --certificate-key <certificate-key> The path to the SSL certificate key
|
-k, --certificate-key <certificate-key> The path to the SSL certificate key
|
||||||
(KEY).
|
used for this proxy server.
|
||||||
-v, --verbose Print the whole traffic.
|
-a, --authentication-server <url> The server url of the AWS
|
||||||
|
authentication server.
|
||||||
|
-v, --verbose Print more verbose.
|
||||||
|
|
||||||
|
|
||||||
# Server API
|
# Server API
|
||||||
|
|
||||||
Once a client connects to the proxy server, he must authenticate him self by passing the token received from the nymea-cloud mqtt connection request.
|
Once a client connects to the proxy server, he must authenticate him self by passing the token received from the nymea-cloud mqtt connection request.
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "websocketserver.h"
|
||||||
#include "loggingcategories.h"
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
Engine *Engine::s_instance = nullptr;
|
Engine *Engine::s_instance = nullptr;
|
||||||
@ -30,24 +31,40 @@ void Engine::destroy()
|
|||||||
|
|
||||||
void Engine::start()
|
void Engine::start()
|
||||||
{
|
{
|
||||||
qCDebug(dcEngine()) << "Start server engine";
|
if (!m_running)
|
||||||
|
qCDebug(dcEngine()) << "Start server engine";
|
||||||
|
|
||||||
QUrl proxyUrl;
|
QUrl proxyUrl;
|
||||||
proxyUrl.setScheme("wss");
|
proxyUrl.setScheme("wss");
|
||||||
proxyUrl.setHost("0.0.0.0");
|
proxyUrl.setHost(m_webSocketServerHostAddress.toString());
|
||||||
proxyUrl.setPort(static_cast<int>(m_port));
|
proxyUrl.setPort(m_webSocketServerPort);
|
||||||
|
|
||||||
qCDebug(dcApplication()) << "Authentication server" << m_authenticationServerUrl.toString();
|
qCDebug(dcApplication()) << "Authentication server" << m_authenticationServerUrl.toString();
|
||||||
qCDebug(dcApplication()) << "Start server" << proxyUrl.toString();
|
qCDebug(dcApplication()) << "Start server" << proxyUrl.toString();
|
||||||
|
|
||||||
// TODO: init stuff
|
// Init WebSocketServer
|
||||||
|
if (m_webSocketServer) {
|
||||||
|
delete m_webSocketServer;
|
||||||
|
m_webSocketServer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_webSocketServer = new WebSocketServer(m_sslConfiguration, this);
|
||||||
|
m_webSocketServer->setServerUrl(proxyUrl);
|
||||||
|
m_webSocketServer->startServer();
|
||||||
|
|
||||||
setRunning(true);
|
setRunning(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::stop()
|
void Engine::stop()
|
||||||
{
|
{
|
||||||
qCDebug(dcEngine()) << "Stop server engine";
|
if (m_running)
|
||||||
|
qCDebug(dcEngine()) << "Stop server engine";
|
||||||
|
|
||||||
// TODO: deinit stuff
|
if (m_webSocketServer) {
|
||||||
|
m_webSocketServer->stopServer();
|
||||||
|
m_webSocketServer->deleteLater();
|
||||||
|
m_webSocketServer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
setRunning(false);
|
setRunning(false);
|
||||||
}
|
}
|
||||||
@ -57,32 +74,49 @@ bool Engine::running() const
|
|||||||
return m_running;
|
return m_running;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::setHost(const QHostAddress &hostAddress)
|
void Engine::setWebSocketServerHostAddress(const QHostAddress &hostAddress)
|
||||||
{
|
{
|
||||||
m_hostAddress = hostAddress;
|
qCDebug(dcEngine()) << "Websocket server host address:" << hostAddress;
|
||||||
|
m_webSocketServerHostAddress = hostAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::setAuthenticationServerUrl(const QUrl &url)
|
void Engine::setWebSocketServerPort(const quint16 &port)
|
||||||
{
|
{
|
||||||
m_authenticationServerUrl = url;
|
qCDebug(dcEngine()) << "Websocket server port:" << port;
|
||||||
}
|
m_webSocketServerPort = port;
|
||||||
|
|
||||||
void Engine::setPort(const quint16 &port)
|
|
||||||
{
|
|
||||||
m_port = port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::setSslConfiguration(const QSslConfiguration &configuration)
|
void Engine::setSslConfiguration(const QSslConfiguration &configuration)
|
||||||
{
|
{
|
||||||
|
qCDebug(dcEngine()) << "SSL Configuration:";
|
||||||
|
qCDebug(dcEngine()) << " Common name:" << configuration.localCertificate().issuerInfo(QSslCertificate::CommonName);
|
||||||
|
qCDebug(dcEngine()) << " Organisation:" << configuration.localCertificate().issuerInfo(QSslCertificate::Organization);
|
||||||
|
qCDebug(dcEngine()) << " Organisation unit name:" << configuration.localCertificate().issuerInfo(QSslCertificate::OrganizationalUnitName);
|
||||||
|
qCDebug(dcEngine()) << " Country name:" << configuration.localCertificate().issuerInfo(QSslCertificate::CountryName);
|
||||||
|
qCDebug(dcEngine()) << " Locality name:" << configuration.localCertificate().issuerInfo(QSslCertificate::LocalityName);
|
||||||
|
qCDebug(dcEngine()) << " State/Province:" << configuration.localCertificate().issuerInfo(QSslCertificate::StateOrProvinceName);
|
||||||
|
qCDebug(dcEngine()) << " Email address:" << configuration.localCertificate().issuerInfo(QSslCertificate::EmailAddress);
|
||||||
|
|
||||||
m_sslConfiguration = configuration;
|
m_sslConfiguration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::setAuthenticationServerUrl(const QUrl &url)
|
||||||
|
{
|
||||||
|
qCDebug(dcEngine()) << "Authentication server URL" << url.toString();
|
||||||
|
m_authenticationServerUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
Engine::Engine(QObject *parent) :
|
Engine::Engine(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Engine::~Engine()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::setRunning(bool running)
|
void Engine::setRunning(bool running)
|
||||||
{
|
{
|
||||||
if (m_running == running)
|
if (m_running == running)
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QSslConfiguration>
|
#include <QSslConfiguration>
|
||||||
|
|
||||||
|
class WebSocketServer;
|
||||||
|
|
||||||
class Engine : public QObject
|
class Engine : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -19,23 +21,27 @@ public:
|
|||||||
|
|
||||||
bool running() const;
|
bool running() const;
|
||||||
|
|
||||||
void setHost(const QHostAddress &hostAddress);
|
void setWebSocketServerHostAddress(const QHostAddress &hostAddress);
|
||||||
void setAuthenticationServerUrl(const QUrl &url);
|
void setWebSocketServerPort(const quint16 &port);
|
||||||
void setPort(const quint16 &port);
|
|
||||||
void setSslConfiguration(const QSslConfiguration &configuration);
|
void setSslConfiguration(const QSslConfiguration &configuration);
|
||||||
|
void setAuthenticationServerUrl(const QUrl &url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Engine(QObject *parent = nullptr);
|
explicit Engine(QObject *parent = nullptr);
|
||||||
|
~Engine();
|
||||||
static Engine *s_instance;
|
static Engine *s_instance;
|
||||||
|
|
||||||
bool m_running = false;
|
bool m_running = false;
|
||||||
|
|
||||||
quint16 m_port = 0;
|
quint16 m_webSocketServerPort = 1212;
|
||||||
QHostAddress m_hostAddress;
|
QHostAddress m_webSocketServerHostAddress = QHostAddress::LocalHost;
|
||||||
QSslConfiguration m_sslConfiguration;
|
|
||||||
|
|
||||||
|
QSslConfiguration m_sslConfiguration;
|
||||||
QUrl m_authenticationServerUrl;
|
QUrl m_authenticationServerUrl;
|
||||||
|
|
||||||
|
WebSocketServer *m_webSocketServer = nullptr;
|
||||||
|
|
||||||
void setRunning(bool running);
|
void setRunning(bool running);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|||||||
@ -5,8 +5,21 @@ TARGET = nymea-remoteproxy
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
engine.h \
|
engine.h \
|
||||||
loggingcategories.h
|
loggingcategories.h \
|
||||||
|
transportinterface.h \
|
||||||
|
websocketserver.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
engine.cpp \
|
engine.cpp \
|
||||||
loggingcategories.cpp
|
loggingcategories.cpp \
|
||||||
|
transportinterface.cpp \
|
||||||
|
websocketserver.cpp
|
||||||
|
|
||||||
|
|
||||||
|
# install header file with relative subdirectory
|
||||||
|
for(header, HEADERS) {
|
||||||
|
path = /usr/include/nymea-remoteproxy/$${dirname(header)}
|
||||||
|
eval(headers_$${path}.files += $${header})
|
||||||
|
eval(headers_$${path}.path = $${path})
|
||||||
|
eval(INSTALLS *= headers_$${path})
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ Q_LOGGING_CATEGORY(dcApplication, "Application")
|
|||||||
Q_LOGGING_CATEGORY(dcEngine, "Engine")
|
Q_LOGGING_CATEGORY(dcEngine, "Engine")
|
||||||
Q_LOGGING_CATEGORY(dcJsonRpc, "JsonRpc")
|
Q_LOGGING_CATEGORY(dcJsonRpc, "JsonRpc")
|
||||||
Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
||||||
|
Q_LOGGING_CATEGORY(dcWebSocketServerTraffic, "WebSocketServerTraffic")
|
||||||
Q_LOGGING_CATEGORY(dcAuthenticator, "Authenticator")
|
Q_LOGGING_CATEGORY(dcAuthenticator, "Authenticator")
|
||||||
Q_LOGGING_CATEGORY(dcDebug, "Debug")
|
Q_LOGGING_CATEGORY(dcDebug, "Debug")
|
||||||
Q_LOGGING_CATEGORY(dcConnectionManager, "ConnectionManager")
|
Q_LOGGING_CATEGORY(dcConnectionManager, "ConnectionManager")
|
||||||
|
|||||||
@ -8,6 +8,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcApplication)
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(dcEngine)
|
Q_DECLARE_LOGGING_CATEGORY(dcEngine)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
|
Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServerTraffic)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcAuthenticator)
|
Q_DECLARE_LOGGING_CATEGORY(dcAuthenticator)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcConnectionManager)
|
Q_DECLARE_LOGGING_CATEGORY(dcConnectionManager)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcDebug)
|
Q_DECLARE_LOGGING_CATEGORY(dcDebug)
|
||||||
|
|||||||
12
libnymea-remoteproxy/transportinterface.cpp
Normal file
12
libnymea-remoteproxy/transportinterface.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "transportinterface.h"
|
||||||
|
|
||||||
|
TransportInterface::TransportInterface(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportInterface::~TransportInterface()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
27
libnymea-remoteproxy/transportinterface.h
Normal file
27
libnymea-remoteproxy/transportinterface.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef TRANSPORTINTERFACE_H
|
||||||
|
#define TRANSPORTINTERFACE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class TransportInterface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TransportInterface(QObject *parent = nullptr);
|
||||||
|
virtual ~TransportInterface() = 0;
|
||||||
|
|
||||||
|
virtual void sendData(const QUuid &clientId, const QByteArray &data) = 0;
|
||||||
|
virtual void sendData(const QList<QUuid> &clients, const QByteArray &data) = 0;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void clientConnected(const QUuid &clientId);
|
||||||
|
void clientDisconnected(const QUuid &clientId);
|
||||||
|
void dataAvailable(const QUuid &clientId, const QByteArray &data);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
virtual bool startServer() = 0;
|
||||||
|
virtual bool stopServer() = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSPORTINTERFACE_H
|
||||||
162
libnymea-remoteproxy/websocketserver.cpp
Normal file
162
libnymea-remoteproxy/websocketserver.cpp
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#include "websocketserver.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
WebSocketServer::WebSocketServer(const QSslConfiguration &sslConfiguration, QObject *parent) :
|
||||||
|
TransportInterface(parent),
|
||||||
|
m_sslConfiguration(sslConfiguration)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WebSocketServer::~WebSocketServer()
|
||||||
|
{
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl WebSocketServer::serverUrl() const
|
||||||
|
{
|
||||||
|
return m_serverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::setServerUrl(const QUrl &serverUrl)
|
||||||
|
{
|
||||||
|
m_serverUrl = serverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketServer::running() const
|
||||||
|
{
|
||||||
|
return m_server->isListening();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSslConfiguration WebSocketServer::sslConfiguration() const
|
||||||
|
{
|
||||||
|
return m_sslConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::sendData(const QUuid &clientId, const QByteArray &data)
|
||||||
|
{
|
||||||
|
QWebSocket *client = nullptr;
|
||||||
|
client = m_clientList.value(clientId);
|
||||||
|
if (client) {
|
||||||
|
qCDebug(dcWebSocketServerTraffic()) << "--> Sending data to client:" << data;
|
||||||
|
client->sendTextMessage(data + '\n');
|
||||||
|
} else {
|
||||||
|
qCWarning(dcWebSocketServer()) << "Client" << clientId << "unknown to this transport";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::sendData(const QList<QUuid> &clients, const QByteArray &data)
|
||||||
|
{
|
||||||
|
foreach (const QUuid &client, clients) {
|
||||||
|
sendData(client, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::onClientConnected()
|
||||||
|
{
|
||||||
|
// Got a new client connected
|
||||||
|
QWebSocket *client = m_server->nextPendingConnection();
|
||||||
|
|
||||||
|
// Check websocket version
|
||||||
|
if (client->version() != QWebSocketProtocol::Version13) {
|
||||||
|
qCWarning(dcWebSocketServer()) << "Client with invalid protocol version" << client->version() << ". Rejecting.";
|
||||||
|
client->close(QWebSocketProtocol::CloseCodeProtocolError, QString("invalid protocol version: %1 != Supported Version 13").arg(client->version()));
|
||||||
|
delete client;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new uuid for this connection
|
||||||
|
QUuid clientId = QUuid::createUuid();
|
||||||
|
qCDebug(dcWebSocketServer()) << "New client connected:" << client->peerAddress().toString() << clientId;
|
||||||
|
|
||||||
|
// 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)));
|
||||||
|
connect(client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
|
||||||
|
|
||||||
|
emit clientConnected(clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::onClientDisconnected()
|
||||||
|
{
|
||||||
|
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||||
|
QUuid clientId = m_clientList.key(client);
|
||||||
|
|
||||||
|
qCDebug(dcWebSocketServer()) << "Client disconnected:" << client->peerAddress().toString() << clientId;
|
||||||
|
|
||||||
|
m_clientList.take(clientId)->deleteLater();
|
||||||
|
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());
|
||||||
|
qCDebug(dcWebSocketServerTraffic()) << "Text message from" << client->peerAddress().toString() << ":" << message;
|
||||||
|
emit dataAvailable(m_clientList.key(client), message.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::onClientError(QAbstractSocket::SocketError error)
|
||||||
|
{
|
||||||
|
QWebSocket *client = static_cast<QWebSocket *>(sender());
|
||||||
|
qCWarning(dcWebSocketServer()) << "Client error occured:" << error << client->errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
m_server->setSslConfiguration(m_sslConfiguration);
|
||||||
|
|
||||||
|
connect (m_server, &QWebSocketServer::newConnection, this, &WebSocketServer::onClientConnected);
|
||||||
|
connect (m_server, &QWebSocketServer::acceptError, this, &WebSocketServer::onServerError);
|
||||||
|
|
||||||
|
qCDebug(dcWebSocketServer()) << "Starting server" << m_server->serverName() << m_serverUrl.toString();
|
||||||
|
if (!m_server->listen(QHostAddress(m_serverUrl.host()), static_cast<quint16>(m_serverUrl.port()))) {
|
||||||
|
qCWarning(dcWebSocketServer()) << "Server" << m_server->serverName() << "could not listen on" << serverUrl().toString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcWebSocketServer()) << "Server started successfully.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebSocketServer::stopServer()
|
||||||
|
{
|
||||||
|
|
||||||
|
// Clean up client connections
|
||||||
|
foreach (QWebSocket *client, m_clientList.values()) {
|
||||||
|
client->close(QWebSocketProtocol::CloseCodeNormal, "Stop server");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the server object
|
||||||
|
if (m_server) {
|
||||||
|
qCDebug(dcWebSocketServer()) << "Stop server" << m_server->serverName() << m_serverUrl.toString();
|
||||||
|
m_server->close();
|
||||||
|
delete m_server;
|
||||||
|
m_server = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
53
libnymea-remoteproxy/websocketserver.h
Normal file
53
libnymea-remoteproxy/websocketserver.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef WEBSOCKETSERVER_H
|
||||||
|
#define WEBSOCKETSERVER_H
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWebSocket>
|
||||||
|
#include <QWebSocketServer>
|
||||||
|
#include <QSslConfiguration>
|
||||||
|
|
||||||
|
#include "transportinterface.h"
|
||||||
|
|
||||||
|
class WebSocketServer : public TransportInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit WebSocketServer(const QSslConfiguration &sslConfiguration, QObject *parent = nullptr);
|
||||||
|
~WebSocketServer() override;
|
||||||
|
|
||||||
|
QUrl serverUrl() const;
|
||||||
|
void setServerUrl(const QUrl &serverUrl);
|
||||||
|
|
||||||
|
bool running() const;
|
||||||
|
|
||||||
|
QSslConfiguration sslConfiguration() const;
|
||||||
|
|
||||||
|
void sendData(const QUuid &clientId, const QByteArray &data) override;
|
||||||
|
void sendData(const QList<QUuid> &clients, const QByteArray &data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QUrl m_serverUrl;
|
||||||
|
QWebSocketServer *m_server = nullptr;
|
||||||
|
QSslConfiguration m_sslConfiguration;
|
||||||
|
bool m_enabled = false;
|
||||||
|
|
||||||
|
QHash<QUuid, QWebSocket *> m_clientList;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onClientConnected();
|
||||||
|
void onClientDisconnected();
|
||||||
|
void onBinaryMessageReceived(const QByteArray &data);
|
||||||
|
void onTextMessageReceived(const QString &message);
|
||||||
|
void onClientError(QAbstractSocket::SocketError error);
|
||||||
|
void onServerError(QAbstractSocket::SocketError error);
|
||||||
|
void onPing(quint64 elapsedTime, const QByteArray & payload);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool startServer() override;
|
||||||
|
bool stopServer() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBSOCKETSERVER_H
|
||||||
20
libnymea-remoteproxyclient/libnymea-remoteproxyclient.pro
Normal file
20
libnymea-remoteproxyclient/libnymea-remoteproxyclient.pro
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
include(../nymea-remoteproxy.pri)
|
||||||
|
|
||||||
|
TEMPLATE = lib
|
||||||
|
TARGET = nymea-remoteproxyclient
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
remoteproxyconnector.h
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
remoteproxyconnector.cpp
|
||||||
|
|
||||||
|
|
||||||
|
# install header file with relative subdirectory
|
||||||
|
for(header, HEADERS) {
|
||||||
|
path = /usr/include/nymea-remoteproxyclient/$${dirname(header)}
|
||||||
|
eval(headers_$${path}.files += $${header})
|
||||||
|
eval(headers_$${path}.path = $${path})
|
||||||
|
eval(INSTALLS *= headers_$${path})
|
||||||
|
}
|
||||||
6
libnymea-remoteproxyclient/remoteproxyconnector.cpp
Normal file
6
libnymea-remoteproxyclient/remoteproxyconnector.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "remoteproxyconnector.h"
|
||||||
|
|
||||||
|
RemoteProxyConnector::RemoteProxyConnector(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
18
libnymea-remoteproxyclient/remoteproxyconnector.h
Normal file
18
libnymea-remoteproxyclient/remoteproxyconnector.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef REMOTEPROXYCONNECTOR_H
|
||||||
|
#define REMOTEPROXYCONNECTOR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class RemoteProxyConnector : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit RemoteProxyConnector(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REMOTEPROXYCONNECTOR_H
|
||||||
@ -1,4 +1,4 @@
|
|||||||
QT *= network
|
QT *= network websockets
|
||||||
QT -= gui
|
QT -= gui
|
||||||
|
|
||||||
CONFIG += c++11 console
|
CONFIG += c++11 console
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
include(nymea-remoteproxy.pri)
|
include(nymea-remoteproxy.pri)
|
||||||
|
|
||||||
TEMPLATE=subdirs
|
TEMPLATE=subdirs
|
||||||
SUBDIRS += server libnymea-remoteproxy tests
|
SUBDIRS += server libnymea-remoteproxy libnymea-remoteproxyclient tests
|
||||||
|
|
||||||
server.depends = libnymea-remoteproxy
|
server.depends = libnymea-remoteproxy
|
||||||
tests.depends = libnymea-remoteproxy
|
tests.depends = libnymea-remoteproxy libnymea-remoteproxyclient
|
||||||
|
|
||||||
|
|||||||
@ -97,25 +97,28 @@ int main(int argc, char *argv[])
|
|||||||
// command line parser
|
// command line parser
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.setApplicationDescription(QString("\nThe nymea remote proxy server.\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)));
|
"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);
|
parser.addOption(logfileOption);
|
||||||
|
|
||||||
QCommandLineOption serverOption(QStringList() << "s" << "server", "The authentication server url.", "url", "http://localhost:8000");
|
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);
|
parser.addOption(serverOption);
|
||||||
|
|
||||||
QCommandLineOption portOption(QStringList() << "p" << "port", "The proxy server port.", "port", "1212");
|
QCommandLineOption portOption(QStringList() << "p" << "port", "The proxy server port. Default is 1212", "port", "1212");
|
||||||
parser.addOption(portOption);
|
parser.addOption(portOption);
|
||||||
|
|
||||||
QCommandLineOption certOption(QStringList() << "c" <<"certificate", "The path to the SSL certificate.", "certificate");
|
QCommandLineOption certOption(QStringList() << "c" <<"certificate", "The path to the SSL certificate used for this proxy server.", "certificate");
|
||||||
parser.addOption(certOption);
|
parser.addOption(certOption);
|
||||||
|
|
||||||
QCommandLineOption certKeyOption(QStringList() << "k" << "certificate-key", "The path to the SSL certificate key (KEY).", "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);
|
parser.addOption(certKeyOption);
|
||||||
|
|
||||||
QCommandLineOption verboseOption(QStringList() << "v" << "verbose", "Print the whole traffic.");
|
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.");
|
||||||
parser.addOption(verboseOption);
|
parser.addOption(verboseOption);
|
||||||
|
|
||||||
parser.process(application);
|
parser.process(application);
|
||||||
@ -141,37 +144,24 @@ int main(int argc, char *argv[])
|
|||||||
s_loggingEnabled = true;
|
s_loggingEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcApplication()) << "==============================================";
|
// Proxy server host address
|
||||||
qCDebug(dcApplication()) << "Starting" << application.applicationName() << application.applicationVersion();
|
QHostAddress serverHostAddress = QHostAddress(parser.value(serverOption));
|
||||||
qCDebug(dcApplication()) << "==============================================";
|
if (serverHostAddress.isNull()) {
|
||||||
|
qCCritical(dcApplication()) << "Invalid hostaddress for the proxy server:" << parser.value(serverOption);
|
||||||
if (s_loggingEnabled)
|
|
||||||
qCDebug(dcApplication()) << "Logging enabled. Writing logs to" << s_logFile.fileName();
|
|
||||||
|
|
||||||
// Authentication server url
|
|
||||||
QUrl serverUrl("http://localhost:8000");
|
|
||||||
if (parser.isSet(serverOption))
|
|
||||||
serverUrl = QUrl(parser.value(serverOption));
|
|
||||||
|
|
||||||
if (!serverUrl.isValid()) {
|
|
||||||
qCCritical(dcApplication()) << "Invalid authentication server url:" << parser.value(serverOption);
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Port
|
// Port
|
||||||
uint port = 1212;
|
bool ok = false;
|
||||||
if (parser.isSet(portOption)) {
|
uint port = parser.value(portOption).toUInt(&ok);
|
||||||
bool ok = false;
|
if (!ok) {
|
||||||
port = parser.value(portOption).toUInt(&ok);
|
qCCritical(dcApplication()) << "Invalid port value:" << parser.value(portOption);
|
||||||
if (!ok) {
|
exit(-1);
|
||||||
qCCritical(dcApplication()) << "Invalud port value:" << parser.value(portOption);
|
}
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port > 65535) {
|
if (port > 65535) {
|
||||||
qCCritical(dcApplication()) << "Port value is out of range:" << parser.value(portOption);
|
qCCritical(dcApplication()) << "Port value is out of range:" << parser.value(portOption);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSL certificate
|
// SSL certificate
|
||||||
@ -198,18 +188,40 @@ int main(int argc, char *argv[])
|
|||||||
if (parser.isSet(certKeyOption)) {
|
if (parser.isSet(certKeyOption)) {
|
||||||
QFile certKeyFile(parser.value(certKeyOption));
|
QFile certKeyFile(parser.value(certKeyOption));
|
||||||
if (!certKeyFile.open(QIODevice::ReadOnly)) {
|
if (!certKeyFile.open(QIODevice::ReadOnly)) {
|
||||||
qCCritical(dcApplication()) << "ERROR: Could not open certificate key file:" << parser.value(certKeyOption) << certKeyFile.errorString();
|
qCCritical(dcApplication()) << "Could not open certificate key file:" << parser.value(certKeyOption) << certKeyFile.errorString();
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSslKey sslKey(&certKeyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
|
QSslKey sslKey(&certKeyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
|
||||||
qCDebug(dcApplication()) << "Loaded successfully certificate key" << parser.value(certKeyOption);
|
qCDebug(dcApplication()) << "Loaded successfully certificate key" << parser.value(certKeyOption);
|
||||||
certKeyFile.close();
|
certKeyFile.close();
|
||||||
sslConfiguration.setPrivateKey(sslKey);
|
sslConfiguration.setPrivateKey(sslKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::instance()->setAuthenticationServerUrl(serverUrl);
|
if (sslConfiguration.isNull()) {
|
||||||
Engine::instance()->setPort(static_cast<quint16>(port));
|
qCCritical(dcApplication()) << "No SSL configuration specified. The server does not suppoert insecure connections.";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authentication server url
|
||||||
|
QUrl authenticationServerUrl(parser.value(authenticationUrlOption));
|
||||||
|
if (!authenticationServerUrl.isValid()) {
|
||||||
|
qCCritical(dcApplication()) << "Invalid authentication server url:" << parser.value(authenticationUrlOption);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcApplication()) << "==============================================";
|
||||||
|
qCDebug(dcApplication()) << "Starting" << application.applicationName() << application.applicationVersion();
|
||||||
|
qCDebug(dcApplication()) << "==============================================";
|
||||||
|
|
||||||
|
if (s_loggingEnabled)
|
||||||
|
qCDebug(dcApplication()) << "Logging enabled. Writing logs to" << s_logFile.fileName();
|
||||||
|
|
||||||
|
// Configure and start the engines
|
||||||
|
Engine::instance()->setWebSocketServerHostAddress(serverHostAddress);
|
||||||
|
Engine::instance()->setWebSocketServerPort(static_cast<quint16>(port));
|
||||||
Engine::instance()->setSslConfiguration(sslConfiguration);
|
Engine::instance()->setSslConfiguration(sslConfiguration);
|
||||||
|
Engine::instance()->setAuthenticationServerUrl(authenticationServerUrl);
|
||||||
Engine::instance()->start();
|
Engine::instance()->start();
|
||||||
|
|
||||||
return application.exec();
|
return application.exec();
|
||||||
|
|||||||
6
tests/certificate.qrc
Normal file
6
tests/certificate.qrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource>
|
||||||
|
<file>test-certificate.crt</file>
|
||||||
|
<file>test-certificate.key</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@ -6,7 +6,28 @@
|
|||||||
RemoteProxyTests::RemoteProxyTests(QObject *parent) :
|
RemoteProxyTests::RemoteProxyTests(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
|
QFile certificateFile(":/test-certificate.crt");
|
||||||
|
if (!certificateFile.open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning() << "Could not open resource file" << certificateFile.fileName();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray certificateData = certificateFile.readAll();
|
||||||
|
//qDebug() << "Certificate:" << endl << qUtf8Printable(certificateData);
|
||||||
|
|
||||||
|
QFile keyFile(":/test-certificate.key");
|
||||||
|
if (!keyFile.open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning() << "Could not open resource file" << keyFile.fileName();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray keyData = keyFile.readAll();
|
||||||
|
//qDebug() << "Certificate key:" << endl << qUtf8Printable(keyData);
|
||||||
|
|
||||||
|
m_sslConfiguration.setPrivateKey(QSslKey(keyData, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey));
|
||||||
|
m_sslConfiguration.setLocalCertificate(QSslCertificate(certificateData, QSsl::Pem));
|
||||||
|
m_sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
|
m_sslConfiguration.setProtocol(QSsl::TlsV1_2OrLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteProxyTests::cleanUpEngine()
|
void RemoteProxyTests::cleanUpEngine()
|
||||||
@ -25,6 +46,17 @@ void RemoteProxyTests::restartEngine()
|
|||||||
QVERIFY(Engine::exists());
|
QVERIFY(Engine::exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteProxyTests::startServer()
|
||||||
|
{
|
||||||
|
restartEngine();
|
||||||
|
|
||||||
|
Engine::instance()->setWebSocketServerPort(m_port);
|
||||||
|
Engine::instance()->setWebSocketServerHostAddress(QHostAddress::LocalHost);
|
||||||
|
Engine::instance()->setSslConfiguration(m_sslConfiguration);
|
||||||
|
Engine::instance()->start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteProxyTests::initTestCase()
|
void RemoteProxyTests::initTestCase()
|
||||||
{
|
{
|
||||||
qCDebug(dcApplication()) << "Init test case.";
|
qCDebug(dcApplication()) << "Init test case.";
|
||||||
@ -37,6 +69,14 @@ void RemoteProxyTests::cleanupTestCase()
|
|||||||
cleanUpEngine();
|
cleanUpEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteProxyTests::authenticate()
|
||||||
|
{
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
|
||||||
|
Engine::instance()->stop();
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteProxyTests::startStopServer()
|
void RemoteProxyTests::startStopServer()
|
||||||
{
|
{
|
||||||
cleanUpEngine();
|
cleanUpEngine();
|
||||||
|
|||||||
@ -2,7 +2,11 @@
|
|||||||
#define NYMEA_REMOTEPROXY_TESTS_H
|
#define NYMEA_REMOTEPROXY_TESTS_H
|
||||||
|
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
|
#include <QSslKey>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QSslCertificate>
|
||||||
|
#include <QSslConfiguration>
|
||||||
|
|
||||||
class RemoteProxyTests : public QObject
|
class RemoteProxyTests : public QObject
|
||||||
{
|
{
|
||||||
@ -11,8 +15,13 @@ public:
|
|||||||
explicit RemoteProxyTests(QObject *parent = nullptr);
|
explicit RemoteProxyTests(QObject *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
quint16 m_port = 1212;
|
||||||
|
QHostAddress m_serverAddress = QHostAddress::LocalHost;
|
||||||
|
QSslConfiguration m_sslConfiguration;
|
||||||
|
|
||||||
void cleanUpEngine();
|
void cleanUpEngine();
|
||||||
void restartEngine();
|
void restartEngine();
|
||||||
|
void startServer();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
@ -21,9 +30,7 @@ protected slots:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void startStopServer();
|
void startStopServer();
|
||||||
|
void authenticate();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
23
tests/test-certificate.crt
Normal file
23
tests/test-certificate.crt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID4TCCAsmgAwIBAgIJAPikDhNDwsqGMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD
|
||||||
|
VQQGEwJBVDEPMA0GA1UECAwGVmllbm5hMQ8wDQYDVQQHDAZWaWVubmExEjAQBgNV
|
||||||
|
BAoMCWd1aCBHbWJILjELMAkGA1UECwwCUUExEjAQBgNVBAMMCWxvY2FsaG9zdDEf
|
||||||
|
MB0GCSqGSIb3DQEJARYQZGV2ZWxvcGVyQGd1aC5pbzAgFw0xODA4MDIxNDU3NTZa
|
||||||
|
GA8yMTE4MDcwOTE0NTc1NlowgYUxCzAJBgNVBAYTAkFUMQ8wDQYDVQQIDAZWaWVu
|
||||||
|
bmExDzANBgNVBAcMBlZpZW5uYTESMBAGA1UECgwJZ3VoIEdtYkguMQswCQYDVQQL
|
||||||
|
DAJRQTESMBAGA1UEAwwJbG9jYWxob3N0MR8wHQYJKoZIhvcNAQkBFhBkZXZlbG9w
|
||||||
|
ZXJAZ3VoLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoNm4oJfX
|
||||||
|
4E7RNzJsscs1+sAgDG2I0fDAwHM1evStk9hjZTHy+T2aLPih1nkAiZvt5mso8v6W
|
||||||
|
rrRc1a3MtHinJRXP4wv/WPLxACmEzNhEzRpl4d+JmcOHwNclT3xjRJCBsW5SNxr1
|
||||||
|
Z2GQICTFJeIBmyHzVcLNGnlrXL61tkSeDCaY3TiaxCRXgtPBtdoJttFFJTXWld2P
|
||||||
|
V4QSlkPA+9edQmdG6jr5MW/LxxdEyp1kqp+9erZ0BbLFly/sNv2hL1Gy6rlPBdxJ
|
||||||
|
S09IYXAvqCjSwzA1VN0P35/iHZLigrwe9bt5jMC8bYAU1yOKrMHVwQhSBe6fij7g
|
||||||
|
EezK1C90BWLOgwIDAQABo1AwTjAdBgNVHQ4EFgQUrT5VDdjUEOzKPWRYelLAI3Nw
|
||||||
|
4uUwHwYDVR0jBBgwFoAUrT5VDdjUEOzKPWRYelLAI3Nw4uUwDAYDVR0TBAUwAwEB
|
||||||
|
/zANBgkqhkiG9w0BAQsFAAOCAQEARHMVjrBEKbfNXTsfNAQcSRkAMkCbWG5/NQDl
|
||||||
|
wHbNEu+VV0OF0AJ0IE1NCC4ZLuyUxSztMJdTOSM2lLmSGjCWyUlKhGvq79MDlomN
|
||||||
|
jHYLPhSV3pYwaO86qNTtBqAQ1YXuauFboxHrpvsXx5a6ivPl1UyiDP9EtHDvkUpo
|
||||||
|
tSW0HBC0n+o78vHbGXyzvlyI25UE9jnIDPD2K3jm7bcGqiqrDgT06QyE7GD43eeL
|
||||||
|
0X6dBKYQWUWcG6cBR9Cvoj1Ec3IcXuprHwfbNrVtYOwdO7678U6gJuk1GeblcsgX
|
||||||
|
9HfkjP61NIqUpu2U0BQrd3mDkjsNuta2IKLW7ojALRpP1shorA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
28
tests/test-certificate.key
Normal file
28
tests/test-certificate.key
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCg2bigl9fgTtE3
|
||||||
|
MmyxyzX6wCAMbYjR8MDAczV69K2T2GNlMfL5PZos+KHWeQCJm+3mayjy/pautFzV
|
||||||
|
rcy0eKclFc/jC/9Y8vEAKYTM2ETNGmXh34mZw4fA1yVPfGNEkIGxblI3GvVnYZAg
|
||||||
|
JMUl4gGbIfNVws0aeWtcvrW2RJ4MJpjdOJrEJFeC08G12gm20UUlNdaV3Y9XhBKW
|
||||||
|
Q8D7151CZ0bqOvkxb8vHF0TKnWSqn716tnQFssWXL+w2/aEvUbLquU8F3ElLT0hh
|
||||||
|
cC+oKNLDMDVU3Q/fn+IdkuKCvB71u3mMwLxtgBTXI4qswdXBCFIF7p+KPuAR7MrU
|
||||||
|
L3QFYs6DAgMBAAECggEAIp+bAV6OBmeQ21vMT90ZKneOrn4pdF9pbkOeYHAoqOls
|
||||||
|
Q80jqwjalhGS7JKxTe21oOKyNtQcZVDHpus5ZCOQfwgZ7pqXhXMN82X8gweOj8O9
|
||||||
|
6Ifwm5ueLiFhk6GH0Kt2b1X69oekCXPTzUd89HGYvObq9SvwcGFwfc9DWA+fIagZ
|
||||||
|
3PRZunEIJlWYRtksMCdsiHMOCeUt2alz4XMYLb0ng+dHEmjnQEWPGPbKMBUnIM0t
|
||||||
|
g5yKZCJ0i/FG+to27+hio9dzG4K/bRLvwlFswLZRfEcvqkBXpQ+aATUNA7jQpRxp
|
||||||
|
e6sWAhpiS+tn2nMniLI+voe0W+v0s+5XLtDRX7LFUQKBgQDQhBTcKXXdnykIOslm
|
||||||
|
p9D+rFaUf10aXpFz3aq0jjy5lHkCXOPc1NTG29e7Ysi8xKwlZdSca6l+zu0zQf1m
|
||||||
|
cW4r/ejzwKM3qrLLeh4Hn7wpoWpliH5Z7BCdkTmeqGJI/9h1VxXgjc6j1DTGsyGb
|
||||||
|
nezNEsNEYmaSZZreConLVGHcuwKBgQDFet79wnbTnqPohySLJy4Q3j+zYXHs/+3I
|
||||||
|
dgRSg9Q/W2uE2ki58oDc10CRgGCet3iyXL5Pbq+QO/N50jpJHKow0DZqka3PTaLz
|
||||||
|
hqqj1FK08/Ual6cZ4TViZ09DE6TnQYXEKtdqakr+iNhNu1O4NQpvW+fjMUaSTqTy
|
||||||
|
DCfqMVrc2QKBgDc6JIRDfvJaC3Ygi+Nio1owryXZrgEj9wZnOaVk3vSQPJTBoaCF
|
||||||
|
xm19IOCCw4Qr2yR0miFr6pKpn+2plsIhXPrN33tgFFrUHVMDXxzJ0/56wEFwK3cJ
|
||||||
|
rUTuiAJbutx21xANJsA5DvgZZnkSTN54r5WJWKquHVi9DI2u4Nw310utAoGBALRm
|
||||||
|
m6DbbivB52A7XLHWF+oG7dBTu3xTDAitbyNmFJXQUPdrZTahBwE3jl+dFCbJ2nOt
|
||||||
|
75imt7EeYzytRNuXWQ4Al0VhUZNoC+1F30qMYwW1OvqRAXDN4DPFxo2zO1ia7bUX
|
||||||
|
ofQvp9TAdEEGWOOVaLP0FHDiieKL/3iyjCAP+D55AoGBAMKi7ZkIBqzRhknwp13v
|
||||||
|
iutRynDO8lXUeLxp/WhPj5Go5S7LbUxEwTlEikxAEdYqtCl7DMxWBgaDojxOahY6
|
||||||
|
LBuK53LWCG9y06laGy8gxbNJ86VbjpwwTm1eQeryPg/CSRPVb4G5Rhe4hZJEMdv3
|
||||||
|
Kt0IfWn4z2YLCtPtOrqMERSk
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@ -8,6 +8,8 @@ TARGET = nymea-remoteproxy-tests
|
|||||||
INCLUDEPATH += ../libnymea-remoteproxy
|
INCLUDEPATH += ../libnymea-remoteproxy
|
||||||
LIBS += -L$$top_builddir/libnymea-remoteproxy/ -lnymea-remoteproxy
|
LIBS += -L$$top_builddir/libnymea-remoteproxy/ -lnymea-remoteproxy
|
||||||
|
|
||||||
|
RESOURCES += certificate.qrc
|
||||||
|
|
||||||
HEADERS += nymea-remoteproxy-tests.h
|
HEADERS += nymea-remoteproxy-tests.h
|
||||||
SOURCES += nymea-remoteproxy-tests.cpp
|
SOURCES += nymea-remoteproxy-tests.cpp
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user