Update client and implement ssl server improvements
This commit is contained in:
parent
3625e6e46c
commit
d4d34a86c2
50
README.md
50
README.md
@ -328,6 +328,56 @@ The client allowes you to test the proxy server and create a dummy client for te
|
||||
-p, --port <port> The proxy server port. Default 1212
|
||||
|
||||
|
||||
# Testing a local server
|
||||
|
||||
|
||||
## Start the server
|
||||
|
||||
In order to test a connection and play with the server API, you can install the proxy server on your machine and try to connect to it.
|
||||
|
||||
$ sudo apt update
|
||||
$ sudo apt install nymea-remoteproxy nymea-remoteproxy-client
|
||||
|
||||
Once installed, the `nymea-remoteproxy` will start automatically using the default configurations shipped in `/etc/nymea/nymea-remoteproxy.conf`.
|
||||
Using this file allowes you to configure the server for your test purposes.
|
||||
|
||||
The only thing you need is a certificate, which can be loaded from the server. The server does not support insecure connection for now. If you don't have any certificate, you can create one for testing.
|
||||
|
||||
> *Note:* you can enter whatever you like for the certificate.
|
||||
|
||||
$ cd /tmp/
|
||||
$ openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout test-proxy-certificate.key -out test-proxy-certificate.crt
|
||||
|
||||
Now place the certificate and the key where they belong:
|
||||
|
||||
$ sudo cp /tmp/test-proxy-certificate.crt /etc/ssl/certs/
|
||||
$ sudo cp /tmp/test-proxy-certificate.key /etc/ssl/private/
|
||||
|
||||
Change following configuration in the `/etc/nymea/nymea-remoteproxy.conf`:
|
||||
|
||||
|
||||
...
|
||||
certificate=/etc/ssl/certs/test-proxy-certificate.crt
|
||||
certificateKey=/etc/ssl/private/test-proxy-certificate.key
|
||||
...
|
||||
|
||||
Now stop the proxy server and start it manually:
|
||||
|
||||
$ sudo systemctl stop nymea-remoteproxy.conf
|
||||
|
||||
> *Note*: the `-m` starts the proxy with a dummy authenticator, which allowes to use any token, it will always be authenticated and should be used only on localhost running servers.
|
||||
|
||||
$ sudo nymea-remoteproxy -c /etc/nymea/nymea-remoteproxy -m
|
||||
|
||||
## Connect two clients
|
||||
|
||||
Once the server is up and running with the dummy authenticator, you can try to connect to the service using the `nymea-remoteproxy-client` in a different terminal.
|
||||
|
||||
> *Note:* assuming you are starting the client on the same system as the server:
|
||||
|
||||
$ nymea-remoteproxy-client -a 127.0.0.1 -p 443 -t "dummytoken1"
|
||||
|
||||
Open a second terminal and start the same command again.
|
||||
|
||||
|
||||
# License
|
||||
|
||||
115
client/main.cpp
115
client/main.cpp
@ -1,4 +1,5 @@
|
||||
#include <QUrl>
|
||||
#include <QHash>
|
||||
#include <QCoreApplication>
|
||||
#include <QLoggingCategory>
|
||||
#include <QCommandLineParser>
|
||||
@ -6,51 +7,133 @@
|
||||
|
||||
#include "proxyclient.h"
|
||||
|
||||
static QHash<QString, bool> s_loggingFilters;
|
||||
static const char *const normal = "\033[0m";
|
||||
static const char *const warning = "\e[33m";
|
||||
static const char *const error = "\e[31m";
|
||||
|
||||
static void loggingCategoryFilter(QLoggingCategory *category)
|
||||
{
|
||||
if (s_loggingFilters.contains(category->categoryName())) {
|
||||
bool debugEnabled = s_loggingFilters.value(category->categoryName());
|
||||
category->setEnabled(QtDebugMsg, debugEnabled);
|
||||
category->setEnabled(QtWarningMsg, debugEnabled || s_loggingFilters.value("Warnings"));
|
||||
} else {
|
||||
// Enable default debug output
|
||||
category->setEnabled(QtDebugMsg, true);
|
||||
category->setEnabled(QtWarningMsg, s_loggingFilters.value("qml") || s_loggingFilters.value("Warnings"));
|
||||
}
|
||||
}
|
||||
|
||||
static void consoleLogHandler(QtMsgType type, const QMessageLogContext& context, const QString& message)
|
||||
{
|
||||
switch (type) {
|
||||
case QtInfoMsg:
|
||||
fprintf(stdout, "%s: %s\n", context.category, message.toUtf8().data());
|
||||
break;
|
||||
case QtDebugMsg:
|
||||
fprintf(stdout, "%s: %s\n", context.category, message.toUtf8().data());
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stdout, "%s%s: %s%s\n", warning, context.category, message.toUtf8().data(), normal);
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stdout, "%s%s: %s%s\n", error, context.category, message.toUtf8().data(), normal);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stdout, "%s%s: %s%s\n", error, context.category, message.toUtf8().data(), normal);
|
||||
break;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
qInstallMessageHandler(consoleLogHandler);
|
||||
|
||||
QCoreApplication application(argc, argv);
|
||||
application.setApplicationName(SERVER_NAME_STRING);
|
||||
application.setOrganizationName("guh");
|
||||
application.setOrganizationName("nymea");
|
||||
application.setApplicationVersion(SERVER_VERSION_STRING);
|
||||
|
||||
// Default debug categories
|
||||
s_loggingFilters.insert("ProxyClient", true);
|
||||
s_loggingFilters.insert("RemoteProxyClientJsonRpc", false);
|
||||
s_loggingFilters.insert("RemoteProxyClientWebSocket", false);
|
||||
s_loggingFilters.insert("RemoteProxyClientConnection", false);
|
||||
s_loggingFilters.insert("RemoteProxyClientJsonRpcTraffic", false);
|
||||
s_loggingFilters.insert("RemoteProxyClientConnectionTraffic", false);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.setApplicationDescription(QString("\nThe nymea remote proxy server client application. This client allowes to test "
|
||||
parser.setApplicationDescription(QString("\nThe nymea remote proxy client application. This client allowes to test "
|
||||
"a server application as client perspective.\n\n"
|
||||
"Server version: %1\n"
|
||||
"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 urlOption(QStringList() << "u" << "url", "The proxy server url. Default wss://dev-remoteproxy.nymea.io:443", "url");
|
||||
urlOption.setDefaultValue("wss://dev-remoteproxy.nymea.io:443");
|
||||
parser.addOption(urlOption);
|
||||
|
||||
QCommandLineOption tokenOption(QStringList() << "t" << "token", "The AWS token for authentication.", "token");
|
||||
parser.addOption(tokenOption);
|
||||
|
||||
QCommandLineOption addressOption(QStringList() << "a" << "address", "The proxy server host address. Default 127.0.0.1", "address");
|
||||
addressOption.setDefaultValue("127.0.0.1");
|
||||
parser.addOption(addressOption);
|
||||
QCommandLineOption insecureOption(QStringList() << "i" << "igore-ssl", "Ignore SSL certificate errors.");
|
||||
parser.addOption(insecureOption);
|
||||
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", "The proxy server port. Default 1212", "port");
|
||||
portOption.setDefaultValue("1212");
|
||||
parser.addOption(portOption);
|
||||
QCommandLineOption nameOption(QStringList() << "name", "The name of the client. Default nymea-remoteproxyclient", "name");
|
||||
nameOption.setDefaultValue("nymea-remoteproxyclient");
|
||||
parser.addOption(nameOption);
|
||||
|
||||
QCommandLineOption uuidOption(QStringList() << "uuid", "The uuid of the client. If not specified, a new one will be created", "uuid");
|
||||
parser.addOption(uuidOption);
|
||||
|
||||
QCommandLineOption verboseOption(QStringList() << "verbose", "Print more information about the connection.");
|
||||
parser.addOption(verboseOption);
|
||||
|
||||
QCommandLineOption veryVerboseOption(QStringList() << "very-verbose", "Print the complete traffic information from the connection.");
|
||||
parser.addOption(veryVerboseOption);
|
||||
|
||||
parser.process(application);
|
||||
|
||||
// Enable verbose
|
||||
if (parser.isSet(verboseOption) || parser.isSet(veryVerboseOption)) {
|
||||
s_loggingFilters["RemoteProxyClientJsonRpc"] = true;
|
||||
s_loggingFilters["RemoteProxyClientWebSocket"] = true;
|
||||
s_loggingFilters["RemoteProxyClientConnection"] = true;
|
||||
}
|
||||
|
||||
// Enable very verbose
|
||||
if (parser.isSet(veryVerboseOption)) {
|
||||
s_loggingFilters["RemoteProxyClientJsonRpcTraffic"] = true;
|
||||
s_loggingFilters["RemoteProxyClientConnectionTraffic"] = true;
|
||||
}
|
||||
QLoggingCategory::installFilter(loggingCategoryFilter);
|
||||
|
||||
if (!parser.isSet(tokenOption)) {
|
||||
qWarning() << "Please specify the token for authentication." << endl;
|
||||
qCCritical(dcProxyClient()) << "Please specify the token for authentication using -t <token> or --token <token>." << endl << endl;
|
||||
parser.showHelp(-1);
|
||||
}
|
||||
|
||||
QUrl serverUrl(parser.value(urlOption));
|
||||
if (!serverUrl.isValid()) {
|
||||
qCCritical(dcProxyClient()) << "Invalid proxy server url passed." << parser.value(urlOption);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ProxyClient client;
|
||||
client.setHostAddress(QHostAddress(parser.value(addressOption)));
|
||||
client.setPort(parser.value(portOption).toInt());
|
||||
client.start(parser.value(tokenOption));
|
||||
QUuid uuid(parser.value(uuidOption));
|
||||
if (uuid.isNull()) {
|
||||
uuid = QUuid::createUuid();
|
||||
}
|
||||
|
||||
ProxyClient client(parser.value(nameOption), uuid);
|
||||
client.setInsecure(parser.isSet(insecureOption));
|
||||
client.start(serverUrl, parser.value(tokenOption));
|
||||
|
||||
return application.exec();
|
||||
}
|
||||
|
||||
@ -1,51 +1,73 @@
|
||||
#include "proxyclient.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(dcProxyClient, "ProxyClient")
|
||||
|
||||
ProxyClient::ProxyClient(QObject *parent) :
|
||||
QObject(parent)
|
||||
ProxyClient::ProxyClient(const QString &name, const QUuid &uuid, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_name(name),
|
||||
m_uuid(uuid)
|
||||
{
|
||||
m_connection = new RemoteProxyConnection(QUuid::createUuid(), "nymea-remoteproxy-client", this);
|
||||
m_connection->setInsecureConnection(true);
|
||||
m_connection = new RemoteProxyConnection(m_uuid, m_name, this);
|
||||
qCDebug(dcProxyClient()) << "Creating remote proxy connection" << m_name << m_uuid.toString();
|
||||
connect(m_connection, &RemoteProxyConnection::ready, this, &ProxyClient::onClientReady);
|
||||
connect(m_connection, &RemoteProxyConnection::authenticated, this, &ProxyClient::onAuthenticationFinished);
|
||||
connect(m_connection, &RemoteProxyConnection::remoteConnectionEstablished, this, &ProxyClient::onRemoteConnectionEstablished);
|
||||
connect(m_connection, &RemoteProxyConnection::errorOccured, this, &ProxyClient::onErrorOccured);
|
||||
connect(m_connection, &RemoteProxyConnection::disconnected, this, &ProxyClient::onClientDisconnected);
|
||||
|
||||
connect(m_connection, &RemoteProxyConnection::sslErrors, this, &ProxyClient::onSslErrors);
|
||||
}
|
||||
|
||||
void ProxyClient::setHostAddress(const QHostAddress &hostAddress)
|
||||
void ProxyClient::setInsecure(bool insecure)
|
||||
{
|
||||
m_hostAddress = hostAddress;
|
||||
}
|
||||
|
||||
void ProxyClient::setPort(int port)
|
||||
{
|
||||
m_port = port;
|
||||
m_insecure = insecure;
|
||||
}
|
||||
|
||||
void ProxyClient::onErrorOccured(RemoteProxyConnection::Error error)
|
||||
{
|
||||
qDebug() << "Error occured" << error << m_connection->errorString();
|
||||
qCWarning(dcProxyClient()) << "Error occured" << error << m_connection->errorString();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void ProxyClient::onClientReady()
|
||||
{
|
||||
qCDebug(dcProxyClient()) << "Connected to proxy server" << m_connection->serverUrl().toString();
|
||||
qCDebug(dcProxyClient()) << "Start authentication";
|
||||
m_connection->authenticate(m_token);
|
||||
}
|
||||
|
||||
void ProxyClient::onAuthenticationFinished()
|
||||
{
|
||||
qDebug() << "Authentication finished.";
|
||||
qCDebug(dcProxyClient()) << "Authentication finished successfully.";
|
||||
}
|
||||
|
||||
void ProxyClient::onRemoteConnectionEstablished()
|
||||
{
|
||||
qCDebug(dcProxyClient()) << "----------------------------------------------------------------------------------";
|
||||
qCDebug(dcProxyClient()) << "Remote connection established with" << m_connection->tunnelPartnerName() << m_connection->tunnelPartnerUuid();
|
||||
qCDebug(dcProxyClient()) << "----------------------------------------------------------------------------------";
|
||||
}
|
||||
|
||||
void ProxyClient::onClientDisconnected()
|
||||
{
|
||||
qDebug() << "Disconnected from" << m_connection;
|
||||
qCDebug(dcProxyClient()) << "Disconnected from" << m_connection->serverUrl().toString();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void ProxyClient::start(const QString &token)
|
||||
void ProxyClient::onSslErrors(const QList<QSslError> errors)
|
||||
{
|
||||
if (m_insecure) {
|
||||
qCDebug(dcProxyClient()) << "SSL errors occured. Ignoring because explicit specified.";
|
||||
m_connection->ignoreSslErrors();
|
||||
} else {
|
||||
qCWarning(dcProxyClient()) << "SSL errors occured:";
|
||||
foreach (const QSslError &sslError, errors) {
|
||||
qCWarning(dcProxyClient()) << " --> " << sslError.errorString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProxyClient::start(const QUrl &url, const QString &token)
|
||||
{
|
||||
m_token = token;
|
||||
m_connection->connectServer(m_hostAddress, static_cast<quint16>(m_port));
|
||||
m_connection->connectServer(url);
|
||||
}
|
||||
|
||||
@ -2,38 +2,40 @@
|
||||
#define PROXYCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include "remoteproxyconnection.h"
|
||||
|
||||
using namespace remoteproxyclient;
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcProxyClient)
|
||||
|
||||
class ProxyClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ProxyClient(QObject *parent = nullptr);
|
||||
explicit ProxyClient(const QString &name, const QUuid &uuid, QObject *parent = nullptr);
|
||||
|
||||
void setHostAddress(const QHostAddress &hostAddress);
|
||||
void setPort(int port);
|
||||
void setInsecure(bool insecure);
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QUuid m_uuid;
|
||||
QString m_token;
|
||||
QHostAddress m_hostAddress = QHostAddress::LocalHost;
|
||||
int m_port = 1212;
|
||||
bool m_insecure = false;
|
||||
|
||||
RemoteProxyConnection *m_connection = nullptr;
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
private slots:
|
||||
void onErrorOccured(RemoteProxyConnection::Error error);
|
||||
void onClientReady();
|
||||
void onAuthenticationFinished();
|
||||
void onRemoteConnectionEstablished();
|
||||
void onClientDisconnected();
|
||||
void onSslErrors(const QList<QSslError> errors);
|
||||
|
||||
public slots:
|
||||
void start(const QString &token);
|
||||
void start(const QUrl &url, const QString &token);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -166,7 +166,8 @@ void JsonRpcServer::asyncReplyFinished()
|
||||
|
||||
if (!reply->timedOut()) {
|
||||
Q_ASSERT_X(reply->handler()->validateReturns(reply->method(), reply->data()).first
|
||||
,"validating return value", formatAssertion(reply->handler()->name(), reply->method(), reply->handler(), reply->data()).toLatin1().data());
|
||||
,"validating return value", formatAssertion(reply->handler()->name(),
|
||||
reply->method(), reply->handler(), reply->data()).toLatin1().data());
|
||||
sendResponse(proxyClient, reply->commandId(), reply->data());
|
||||
if (!reply->success()) {
|
||||
// Disconnect this client since the request was not successfully
|
||||
|
||||
@ -34,6 +34,7 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
|
||||
setLogFileName(settings.value("logFile", "/var/log/nymea-remoteproxy.log").toString());
|
||||
setSslCertificateFileName(settings.value("certificate", "/etc/ssl/certs/ssl-cert-snakeoil.pem").toString());
|
||||
setSslCertificateKeyFileName(settings.value("certificateKey", "/etc/ssl/private/ssl-cert-snakeoil.key").toString());
|
||||
setSslCertificateChainFileName(settings.value("certificateChain", "").toString());
|
||||
|
||||
settings.beginGroup("WebSocketServer");
|
||||
setWebSocketServerHost(QHostAddress(settings.value("host", "127.0.0.1").toString()));
|
||||
@ -45,35 +46,44 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
|
||||
setTcpServerPort(static_cast<quint16>(settings.value("port", 1213).toInt()));
|
||||
settings.endGroup();
|
||||
|
||||
// Load ssl configuration
|
||||
// Load SSL configuration
|
||||
QSslConfiguration sslConfiguration;
|
||||
// Load certificate
|
||||
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
sslConfiguration.setProtocol(QSsl::TlsV1_2OrLater);
|
||||
|
||||
// SSL certificate
|
||||
QFile certFile(sslCertificateFileName());
|
||||
if (!certFile.open(QIODevice::ReadOnly)) {
|
||||
qCWarning(dcApplication()) << "Could not open certificate file" << sslCertificateFileName() << certFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QSslCertificate certificate(&certFile, QSsl::Pem);
|
||||
qCDebug(dcApplication()) << "Loaded successfully certificate" << sslCertificateFileName();
|
||||
certFile.close();
|
||||
|
||||
// Create SSL configuration
|
||||
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
sslConfiguration.setLocalCertificate(certificate);
|
||||
sslConfiguration.setProtocol(QSsl::TlsV1_2OrLater);
|
||||
|
||||
// SSL key
|
||||
// SSL certificate key
|
||||
QFile certKeyFile(sslCertificateKeyFileName());
|
||||
if (!certKeyFile.open(QIODevice::ReadOnly)) {
|
||||
qCWarning(dcApplication()) << "Could not open certificate key file:" << sslCertificateKeyFileName() << certKeyFile.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QSslKey sslKey(&certKeyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
|
||||
qCDebug(dcApplication()) << "Loaded successfully certificate key" << sslCertificateKeyFileName();
|
||||
certKeyFile.close();
|
||||
sslConfiguration.setPrivateKey(sslKey);
|
||||
|
||||
// SSL certificate chain
|
||||
if (!sslCertificateChainFileName().isEmpty()) {
|
||||
QFile certChainFile(sslCertificateChainFileName());
|
||||
if (!certChainFile.open(QIODevice::ReadOnly)) {
|
||||
qCWarning(dcApplication()) << "Could not open certificate chain file:" << sslCertificateChainFileName() << certChainFile.errorString();
|
||||
return false;
|
||||
}
|
||||
QSslCertificate certificate(&certKeyFile, QSsl::Pem);
|
||||
sslConfiguration.setLocalCertificateChain( { certificate } );
|
||||
}
|
||||
|
||||
m_sslConfiguration = sslConfiguration;
|
||||
|
||||
return true;
|
||||
@ -129,6 +139,16 @@ void ProxyConfiguration::setSslCertificateKeyFileName(const QString &fileName)
|
||||
m_sslCertificateKeyFileName = fileName;
|
||||
}
|
||||
|
||||
QString ProxyConfiguration::sslCertificateChainFileName() const
|
||||
{
|
||||
return m_sslCertificateChainFileName;
|
||||
}
|
||||
|
||||
void ProxyConfiguration::setSslCertificateChainFileName(const QString &fileName)
|
||||
{
|
||||
m_sslCertificateChainFileName = fileName;
|
||||
}
|
||||
|
||||
QSslConfiguration ProxyConfiguration::sslConfiguration() const
|
||||
{
|
||||
return m_sslConfiguration;
|
||||
@ -183,6 +203,7 @@ QDebug operator<<(QDebug debug, ProxyConfiguration *configuration)
|
||||
debug.nospace() << " - logfile:" << configuration->logFileName() << endl;
|
||||
debug.nospace() << " - certificate:" << configuration->sslCertificateFileName() << endl;
|
||||
debug.nospace() << " - certificate key:" << configuration->sslCertificateKeyFileName() << endl;
|
||||
debug.nospace() << " - certificate chain:" << configuration->sslCertificateChainFileName() << endl;
|
||||
debug.nospace() << " - SSL certificate information:";
|
||||
debug.nospace() << " Common name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::CommonName) << endl;
|
||||
debug.nospace() << " Organisation:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::Organization) << endl;
|
||||
|
||||
@ -32,6 +32,9 @@ public:
|
||||
QString sslCertificateKeyFileName() const;
|
||||
void setSslCertificateKeyFileName(const QString &fileName);
|
||||
|
||||
QString sslCertificateChainFileName() const;
|
||||
void setSslCertificateChainFileName(const QString &fileName);
|
||||
|
||||
QSslConfiguration sslConfiguration() const;
|
||||
|
||||
// WebSocketServer
|
||||
@ -55,6 +58,7 @@ private:
|
||||
QString m_logFileName = "/var/log/nymea-remoteproxy.log";
|
||||
QString m_sslCertificateFileName = "/etc/ssl/certs/ssl-cert-snakeoil.pem";
|
||||
QString m_sslCertificateKeyFileName = "/etc/ssl/private/ssl-cert-snakeoil.key";
|
||||
QString m_sslCertificateChainFileName;
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
|
||||
// WebSocketServer
|
||||
|
||||
@ -35,10 +35,10 @@ QVariantMap JsonReply::params() const
|
||||
QVariantMap JsonReply::requestMap()
|
||||
{
|
||||
QVariantMap request;
|
||||
request.insert("id", m_commandId);
|
||||
request.insert("method", m_nameSpace + "." + m_method);
|
||||
request.insert("id", commandId());
|
||||
request.insert("method", nameSpace() + "." + method());
|
||||
if (!m_params.isEmpty())
|
||||
request.insert("params", m_params);
|
||||
request.insert("params", params());
|
||||
|
||||
m_commandId++;
|
||||
return request;
|
||||
|
||||
@ -7,19 +7,23 @@ ProxyConnection::ProxyConnection(QObject *parent) : QObject(parent)
|
||||
|
||||
}
|
||||
|
||||
bool ProxyConnection::connected()
|
||||
{
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
void ProxyConnection::setConnected(bool connected)
|
||||
{
|
||||
if (m_connected == connected)
|
||||
return;
|
||||
|
||||
m_connected = connected;
|
||||
emit connectedChanged(m_connected);
|
||||
}
|
||||
|
||||
ProxyConnection::~ProxyConnection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool ProxyConnection::allowSslErrors() const
|
||||
{
|
||||
return m_allowSslErrors;
|
||||
}
|
||||
|
||||
void ProxyConnection::setAllowSslErrors(bool allowSslErrors)
|
||||
{
|
||||
m_allowSslErrors = allowSslErrors;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define SOCKETCONNECTOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSslError>
|
||||
#include <QHostAddress>
|
||||
|
||||
namespace remoteproxyclient {
|
||||
@ -14,24 +15,28 @@ public:
|
||||
virtual ~ProxyConnection() = 0;
|
||||
|
||||
virtual void sendData(const QByteArray &data) = 0;
|
||||
virtual bool isConnected() = 0;
|
||||
|
||||
virtual QUrl serverUrl() const = 0;
|
||||
|
||||
bool allowSslErrors() const;
|
||||
void setAllowSslErrors(bool allowSslErrors);
|
||||
virtual void ignoreSslErrors() = 0;
|
||||
virtual void ignoreSslErrors(const QList<QSslError> &errors) = 0;
|
||||
|
||||
bool connected();
|
||||
|
||||
private:
|
||||
bool m_allowSslErrors = false;
|
||||
bool m_connected = false;
|
||||
|
||||
protected:
|
||||
void setConnected(bool connected);
|
||||
|
||||
signals:
|
||||
void connectedChanged(bool connected);
|
||||
void dataReceived(const QByteArray &data);
|
||||
void errorOccured();
|
||||
void sslErrorOccured();
|
||||
void sslErrors(const QList<QSslError> &errors);
|
||||
|
||||
public slots:
|
||||
virtual void connectServer(const QHostAddress &address, quint16 port) = 0;
|
||||
virtual void connectServer(const QUrl &serverUrl) = 0;
|
||||
virtual void disconnectServer() = 0;
|
||||
|
||||
};
|
||||
|
||||
@ -32,7 +32,7 @@ JsonReply *JsonRpcClient::callAuthenticate(const QUuid &clientUuid, const QStrin
|
||||
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()) << reply->params();
|
||||
qCDebug(dcRemoteProxyClientJsonRpc()) << "Calling" << QString("%1.%2").arg(reply->nameSpace()).arg(reply->method());
|
||||
sendRequest(reply->requestMap());
|
||||
m_replies.insert(m_commandId, reply);
|
||||
return reply;
|
||||
@ -66,6 +66,7 @@ void JsonRpcClient::processData(const QByteArray &data)
|
||||
|
||||
if (dataMap.value("status").toString() == "error") {
|
||||
qCWarning(dcRemoteProxyClientJsonRpc()) << "Api error happend" << dataMap.value("error").toString();
|
||||
// FIMXME: handle json layer errors
|
||||
}
|
||||
|
||||
reply->setResponse(dataMap);
|
||||
|
||||
@ -38,6 +38,9 @@ QString RemoteProxyConnection::errorString() const
|
||||
case ErrorNoError:
|
||||
errorString = "";
|
||||
break;
|
||||
case ErrorHostNotFound:
|
||||
errorString = "The proxy host url could not be resolved.";
|
||||
break;
|
||||
case ErrorSocketError:
|
||||
errorString = "Socket connection error occured.";
|
||||
break;
|
||||
@ -55,6 +58,16 @@ QString RemoteProxyConnection::errorString() const
|
||||
return errorString;
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::ignoreSslErrors()
|
||||
{
|
||||
m_connection->ignoreSslErrors();
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::ignoreSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
m_connection->ignoreSslErrors(errors);
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::isConnected() const
|
||||
{
|
||||
return m_state == StateConnected
|
||||
@ -67,8 +80,7 @@ bool RemoteProxyConnection::isConnected() const
|
||||
|
||||
bool RemoteProxyConnection::isAuthenticated() const
|
||||
{
|
||||
return m_state == StateWaitTunnel
|
||||
|| m_state == StateRemoteConnected;
|
||||
return m_state == StateWaitTunnel || m_state == StateRemoteConnected;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::isRemoteConnected() const
|
||||
@ -81,19 +93,9 @@ RemoteProxyConnection::ConnectionType RemoteProxyConnection::connectionType() co
|
||||
return m_connectionType;
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::setConnectionType(RemoteProxyConnection::ConnectionType connectionType)
|
||||
QUrl RemoteProxyConnection::serverUrl() const
|
||||
{
|
||||
m_connectionType = connectionType;
|
||||
}
|
||||
|
||||
QHostAddress RemoteProxyConnection::serverAddress() const
|
||||
{
|
||||
return m_serverAddress;
|
||||
}
|
||||
|
||||
quint16 RemoteProxyConnection::serverPort() const
|
||||
{
|
||||
return m_serverPort;
|
||||
return m_serverUrl;
|
||||
}
|
||||
|
||||
QString RemoteProxyConnection::serverName() const
|
||||
@ -116,14 +118,14 @@ QString RemoteProxyConnection::proxyServerApiVersion() const
|
||||
return m_proxyServerApiVersion;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::insecureConnection() const
|
||||
QString RemoteProxyConnection::tunnelPartnerName() const
|
||||
{
|
||||
return m_insecureConnection;
|
||||
return m_tunnelPartnerName;
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::setInsecureConnection(bool insecureConnection)
|
||||
QString RemoteProxyConnection::tunnelPartnerUuid() const
|
||||
{
|
||||
m_insecureConnection = insecureConnection;
|
||||
return m_tunnelPartnerUuid;
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::sendData(const QByteArray &data)
|
||||
@ -170,6 +172,24 @@ void RemoteProxyConnection::setState(RemoteProxyConnection::State state)
|
||||
m_state = state;
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "State changed" << m_state;
|
||||
emit stateChanged(m_state);
|
||||
|
||||
switch (m_state) {
|
||||
case StateConnected:
|
||||
emit connected();
|
||||
break;
|
||||
case StateDisconnected:
|
||||
emit disconnected();
|
||||
break;
|
||||
case StateReady:
|
||||
emit ready();
|
||||
break;
|
||||
case StateRemoteConnected:
|
||||
emit remoteConnectionEstablished();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::setError(RemoteProxyConnection::Error error)
|
||||
@ -185,16 +205,14 @@ void RemoteProxyConnection::setError(RemoteProxyConnection::Error error)
|
||||
void RemoteProxyConnection::onConnectionChanged(bool isConnected)
|
||||
{
|
||||
if (isConnected) {
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Connected from proxy server.";
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Connected to proxy server.";
|
||||
setState(StateConnected);
|
||||
emit connected();
|
||||
|
||||
setState(StateInitializing);
|
||||
JsonReply *reply = m_jsonClient->callHello();
|
||||
connect(reply, &JsonReply::finished, this, &RemoteProxyConnection::onHelloFinished);
|
||||
} else {
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Disconnected from proxy server.";
|
||||
emit disconnected();
|
||||
setState(StateDisconnected);
|
||||
cleanUp();
|
||||
}
|
||||
@ -226,11 +244,6 @@ void RemoteProxyConnection::onConnectionSocketError()
|
||||
setError(ErrorSocketError);
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onConnectionSslError()
|
||||
{
|
||||
setError(ErrorSslError);
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onHelloFinished()
|
||||
{
|
||||
JsonReply *reply = static_cast<JsonReply *>(sender());
|
||||
@ -255,7 +268,6 @@ void RemoteProxyConnection::onHelloFinished()
|
||||
m_proxyServerApiVersion = responseParams.value("apiVersion").toString();
|
||||
|
||||
setState(StateReady);
|
||||
emit ready();
|
||||
}
|
||||
|
||||
void RemoteProxyConnection::onAuthenticateFinished()
|
||||
@ -280,15 +292,23 @@ void RemoteProxyConnection::onAuthenticateFinished()
|
||||
|
||||
void RemoteProxyConnection::onTunnelEstablished(const QString &clientName, const QString &clientUuid)
|
||||
{
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "####### Remote connection established with" << clientName << clientUuid;
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Remote connection established successfully with" << clientName << clientUuid;
|
||||
m_tunnelPartnerName = clientName;
|
||||
m_tunnelPartnerUuid = clientUuid;
|
||||
setState(StateRemoteConnected);
|
||||
emit remoteConnectionEstablished();
|
||||
}
|
||||
|
||||
bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, quint16 port)
|
||||
{
|
||||
m_serverAddress = serverAddress;
|
||||
m_serverPort = port;
|
||||
bool RemoteProxyConnection::connectServer(const QUrl &url)
|
||||
{
|
||||
// Verify url
|
||||
// FIXME: support also tcp
|
||||
if (url.scheme() != "wss") {
|
||||
qCWarning(dcRemoteProxyClientConnection()) << "Unsupported connection type" << url.scheme() << "Default to wss";
|
||||
m_serverUrl.setScheme("wss");
|
||||
}
|
||||
|
||||
m_serverUrl = url;
|
||||
m_connectionType = ConnectionTypeWebSocket;
|
||||
m_error = ErrorNoError;
|
||||
|
||||
cleanUp();
|
||||
@ -296,22 +316,23 @@ bool RemoteProxyConnection::connectServer(const QHostAddress &serverAddress, qui
|
||||
switch (m_connectionType) {
|
||||
case ConnectionTypeWebSocket:
|
||||
m_connection = qobject_cast<ProxyConnection *>(new WebSocketConnection(this));
|
||||
break;
|
||||
case ConnectionTypeTcpSocket:
|
||||
// FIXME:
|
||||
m_connection = qobject_cast<ProxyConnection *>(new WebSocketConnection(this));
|
||||
break;
|
||||
}
|
||||
|
||||
m_connection->setAllowSslErrors(m_insecureConnection);
|
||||
|
||||
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::sslErrorOccured, this, &RemoteProxyConnection::onConnectionSslError);
|
||||
connect(m_connection, &ProxyConnection::sslErrors, this, &RemoteProxyConnection::sslErrors);
|
||||
|
||||
m_jsonClient = new JsonRpcClient(m_connection, this);
|
||||
connect(m_jsonClient, &JsonRpcClient::tunnelEstablished, this, &RemoteProxyConnection::onTunnelEstablished);
|
||||
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Connecting to" << QString("%1:%2").arg(serverAddress.toString()).arg(port);
|
||||
m_connection->connectServer(serverAddress, port);
|
||||
|
||||
setState(StateConnecting);
|
||||
qCDebug(dcRemoteProxyClientConnection()) << "Connecting to" << m_serverUrl.toString();
|
||||
m_connection->connectServer(m_serverUrl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <QUuid>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QHostInfo>
|
||||
#include <QWebSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QLoggingCategory>
|
||||
@ -21,11 +22,13 @@ class RemoteProxyConnection : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ConnectionType {
|
||||
ConnectionTypeWebSocket
|
||||
ConnectionTypeWebSocket,
|
||||
ConnectionTypeTcpSocket
|
||||
};
|
||||
Q_ENUM(ConnectionType)
|
||||
|
||||
enum State {
|
||||
StateHostLookup,
|
||||
StateConnecting,
|
||||
StateConnected,
|
||||
StateInitializing,
|
||||
@ -39,6 +42,7 @@ public:
|
||||
|
||||
enum Error {
|
||||
ErrorNoError,
|
||||
ErrorHostNotFound,
|
||||
ErrorSocketError,
|
||||
ErrorSslError,
|
||||
ErrorProxyNotResponding,
|
||||
@ -53,23 +57,24 @@ public:
|
||||
RemoteProxyConnection::Error error() const;
|
||||
QString errorString() const;
|
||||
|
||||
void ignoreSslErrors();
|
||||
void ignoreSslErrors(const QList<QSslError> &errors);
|
||||
|
||||
bool isConnected() const;
|
||||
bool isAuthenticated() const;
|
||||
bool isRemoteConnected() const;
|
||||
|
||||
RemoteProxyConnection::ConnectionType connectionType() const;
|
||||
void setConnectionType(RemoteProxyConnection::ConnectionType connectionType);
|
||||
|
||||
QHostAddress serverAddress() const;
|
||||
quint16 serverPort() const;
|
||||
QUrl serverUrl() const;
|
||||
|
||||
QString serverName() const;
|
||||
QString proxyServerName() const;
|
||||
QString proxyServerVersion() const;
|
||||
QString proxyServerApiVersion() const;
|
||||
|
||||
bool insecureConnection() const;
|
||||
void setInsecureConnection(bool insecureConnection);
|
||||
QString tunnelPartnerName() const;
|
||||
QString tunnelPartnerUuid() const;
|
||||
|
||||
bool sendData(const QByteArray &data);
|
||||
|
||||
@ -78,8 +83,7 @@ private:
|
||||
QUuid m_clientUuid;
|
||||
QString m_clientName;
|
||||
|
||||
QHostAddress m_serverAddress;
|
||||
quint16 m_serverPort = 443;
|
||||
QUrl m_serverUrl;
|
||||
|
||||
State m_state = StateDisconnected;
|
||||
Error m_error = ErrorNoError;
|
||||
@ -96,6 +100,10 @@ private:
|
||||
QString m_proxyServerVersion;
|
||||
QString m_proxyServerApiVersion;
|
||||
|
||||
// Tunnel
|
||||
QString m_tunnelPartnerName;
|
||||
QString m_tunnelPartnerUuid;
|
||||
|
||||
void cleanUp();
|
||||
|
||||
void setState(State state);
|
||||
@ -110,6 +118,7 @@ signals:
|
||||
|
||||
void stateChanged(RemoteProxyConnection::State state);
|
||||
void errorOccured(RemoteProxyConnection::Error error);
|
||||
void sslErrors(const QList<QSslError> &errors);
|
||||
|
||||
void dataReady(const QByteArray &data);
|
||||
|
||||
@ -117,14 +126,13 @@ private slots:
|
||||
void onConnectionChanged(bool isConnected);
|
||||
void onConnectionDataAvailable(const QByteArray &data);
|
||||
void onConnectionSocketError();
|
||||
void onConnectionSslError();
|
||||
|
||||
void onHelloFinished();
|
||||
void onAuthenticateFinished();
|
||||
void onTunnelEstablished(const QString &clientName, const QString &clientUuid);
|
||||
|
||||
public slots:
|
||||
bool connectServer(const QHostAddress &serverAddress, quint16 port);
|
||||
bool connectServer(const QUrl &url);
|
||||
bool authenticate(const QString &token);
|
||||
void disconnectServer();
|
||||
|
||||
|
||||
@ -9,14 +9,13 @@ WebSocketConnection::WebSocketConnection(QObject *parent) :
|
||||
{
|
||||
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);
|
||||
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(sslErrors(QList<QSslError>)), this, SLOT(onSslError(QList<QSslError>)));
|
||||
connect(m_webSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onStateChanged(QAbstractSocket::SocketState)));
|
||||
connect(m_webSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SIGNAL(sslErrors(QList<QSslError>)));
|
||||
}
|
||||
|
||||
WebSocketConnection::~WebSocketConnection()
|
||||
@ -34,15 +33,14 @@ void WebSocketConnection::sendData(const QByteArray &data)
|
||||
m_webSocket->sendTextMessage(QString::fromUtf8(data));
|
||||
}
|
||||
|
||||
bool WebSocketConnection::isConnected()
|
||||
void WebSocketConnection::ignoreSslErrors()
|
||||
{
|
||||
return m_webSocket->state() == QAbstractSocket::ConnectedState;
|
||||
m_webSocket->ignoreSslErrors();
|
||||
}
|
||||
|
||||
void WebSocketConnection::onConnected()
|
||||
void WebSocketConnection::ignoreSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Connected with" << m_webSocket->requestUrl().toString();
|
||||
emit connectedChanged(true);
|
||||
m_webSocket->ignoreSslErrors(errors);
|
||||
}
|
||||
|
||||
void WebSocketConnection::onDisconnected()
|
||||
@ -57,23 +55,19 @@ void WebSocketConnection::onError(QAbstractSocket::SocketError error)
|
||||
emit errorOccured();
|
||||
}
|
||||
|
||||
void WebSocketConnection::onSslError(const QList<QSslError> &errors)
|
||||
{
|
||||
if (allowSslErrors()) {
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Ignore ssl errors because the developer explicitly allowed to use an insecure connection.";
|
||||
m_webSocket->ignoreSslErrors();
|
||||
} else {
|
||||
qCWarning(dcRemoteProxyClientWebSocket()) << "SSL errors occured:";
|
||||
foreach (const QSslError sslError, errors) {
|
||||
qCWarning(dcRemoteProxyClientWebSocket()) << " -->" << static_cast<int>(sslError.error()) << sslError.errorString();
|
||||
}
|
||||
emit sslErrorOccured();
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
|
||||
{
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Socket state changed" << state;
|
||||
|
||||
switch (state) {
|
||||
case QAbstractSocket::ConnectedState:
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Connected with" << m_webSocket->requestUrl().toString();
|
||||
setConnected(true);
|
||||
break;
|
||||
default:
|
||||
setConnected(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketConnection::onTextMessageReceived(const QString &message)
|
||||
@ -86,28 +80,19 @@ void WebSocketConnection::onBinaryMessageReceived(const QByteArray &message)
|
||||
Q_UNUSED(message)
|
||||
}
|
||||
|
||||
void WebSocketConnection::connectServer(const QHostAddress &address, quint16 port)
|
||||
void WebSocketConnection::connectServer(const QUrl &serverUrl)
|
||||
{
|
||||
if (isConnected()) {
|
||||
if (connected()) {
|
||||
m_webSocket->close();
|
||||
}
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("wss");
|
||||
url.setHost(address.toString());
|
||||
url.setPort(port);
|
||||
|
||||
m_serverUrl = url;
|
||||
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Connecting to" << serverUrl().toString();
|
||||
m_serverUrl = serverUrl;
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Connecting to" << m_serverUrl.toString();
|
||||
m_webSocket->open(m_serverUrl);
|
||||
}
|
||||
|
||||
void WebSocketConnection::disconnectServer()
|
||||
{
|
||||
if (!isConnected())
|
||||
return;
|
||||
|
||||
qCDebug(dcRemoteProxyClientWebSocket()) << "Disconnecting from" << serverUrl().toString();
|
||||
m_webSocket->close();
|
||||
}
|
||||
|
||||
@ -22,23 +22,23 @@ public:
|
||||
QUrl serverUrl() const override;
|
||||
|
||||
void sendData(const QByteArray &data) override;
|
||||
bool isConnected() override;
|
||||
|
||||
void ignoreSslErrors() override;
|
||||
void ignoreSslErrors(const QList<QSslError> &errors) override;
|
||||
|
||||
private:
|
||||
QUrl m_serverUrl;
|
||||
QWebSocket *m_webSocket = nullptr;
|
||||
|
||||
private slots:
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
void onSslError(const QList<QSslError> &errors);
|
||||
void onStateChanged(QAbstractSocket::SocketState state);
|
||||
void onTextMessageReceived(const QString &message);
|
||||
void onBinaryMessageReceived(const QByteArray &message);
|
||||
|
||||
public slots:
|
||||
void connectServer(const QHostAddress &address, quint16 port) override;
|
||||
void connectServer(const QUrl &serverUrl) override;
|
||||
void disconnectServer() override;
|
||||
};
|
||||
|
||||
|
||||
@ -3,11 +3,12 @@ writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy.log
|
||||
certificate=/etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
certificateKey=/etc/ssl/private/ssl-cert-snakeoil.key
|
||||
certificateChain=
|
||||
|
||||
[WebSocketServer]
|
||||
host=0.0.0.0
|
||||
host=127.0.0.1
|
||||
port=443
|
||||
|
||||
[TcpServer]
|
||||
host=0.0.0.0
|
||||
host=127.0.0.1
|
||||
port=80
|
||||
|
||||
@ -114,7 +114,7 @@ int main(int argc, char *argv[])
|
||||
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"
|
||||
"Server version: %1\n"
|
||||
"Version: %1\n"
|
||||
"API version: %2\n\n"
|
||||
"Copyright %3 2018 Simon Stürz <simon.stuerz@guh.io>\n")
|
||||
.arg(SERVER_VERSION_STRING)
|
||||
@ -202,7 +202,6 @@ int main(int argc, char *argv[])
|
||||
qCDebug(dcApplication()) << "==========================================================";
|
||||
qCDebug(dcApplication()) << "Starting" << application.applicationName() << application.applicationVersion();
|
||||
qCDebug(dcApplication()) << "==========================================================";
|
||||
|
||||
if (parser.isSet(developmentOption)) {
|
||||
qCWarning(dcApplication()) << "##########################################################";
|
||||
qCWarning(dcApplication()) << "# DEVELOPMENT MODE #";
|
||||
@ -212,6 +211,8 @@ int main(int argc, char *argv[])
|
||||
if (s_loggingEnabled)
|
||||
qCDebug(dcApplication()) << "Logging enabled. Writing logs to" << s_logFile.fileName();
|
||||
|
||||
qCDebug(dcApplication()) << "Using ssl version:" << QSslSocket::sslLibraryVersionString();
|
||||
|
||||
Authenticator *authenticator = nullptr;
|
||||
if (parser.isSet(mockAuthenticatorOption)) {
|
||||
authenticator = qobject_cast<Authenticator *>(new DummyAuthenticator(nullptr));
|
||||
|
||||
@ -57,7 +57,7 @@ void RemoteProxyOfflineTests::webserverConnectionBlocked()
|
||||
{
|
||||
// Create a dummy server which blocks the port
|
||||
QWebSocketServer dummyServer("dummy-server", QWebSocketServer::NonSecureMode);
|
||||
dummyServer.listen(QHostAddress::LocalHost, m_port);
|
||||
dummyServer.listen(QHostAddress::LocalHost, 1212);
|
||||
|
||||
// Start proxy webserver
|
||||
QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged);
|
||||
@ -208,21 +208,19 @@ void RemoteProxyOfflineTests::clientConnection()
|
||||
|
||||
// Connect to the server (insecure disabled)
|
||||
RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this);
|
||||
connection->setInsecureConnection(true);
|
||||
connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
// Connect to server (insecue enabled for testing)
|
||||
QSignalSpy readySpy(connection, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connection->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connection->connectServer(m_serverUrl));
|
||||
readySpy.wait();
|
||||
QVERIFY(readySpy.count() == 1);
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(!connection->isRemoteConnected());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateReady);
|
||||
QVERIFY(connection->error() == RemoteProxyConnection::ErrorNoError);
|
||||
QVERIFY(connection->serverAddress() == QHostAddress::LocalHost);
|
||||
QVERIFY(connection->serverPort() == m_port);
|
||||
QVERIFY(connection->serverUrl() == m_serverUrl);
|
||||
QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeWebSocket);
|
||||
QVERIFY(connection->insecureConnection() == true);
|
||||
QVERIFY(connection->serverName() == SERVER_NAME_STRING);
|
||||
QVERIFY(connection->proxyServerName() == Engine::instance()->serverName());
|
||||
QVERIFY(connection->proxyServerVersion() == SERVER_VERSION_STRING);
|
||||
@ -241,6 +239,7 @@ void RemoteProxyOfflineTests::clientConnection()
|
||||
connection->disconnectServer();
|
||||
// FIXME: check why it waits the full time here
|
||||
spyDisconnected.wait(100);
|
||||
|
||||
QVERIFY(spyDisconnected.count() == 1);
|
||||
QVERIFY(!connection->isConnected());
|
||||
|
||||
@ -259,21 +258,21 @@ void RemoteProxyOfflineTests::remoteConnection()
|
||||
|
||||
// Create two connection
|
||||
RemoteProxyConnection *connectionOne = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this);
|
||||
connectionOne->setInsecureConnection(true);
|
||||
connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(QUuid::createUuid(), "Test client two", this);
|
||||
connectionTwo->setInsecureConnection(true);
|
||||
connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
// Connect one
|
||||
QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionOne->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connectionOne->connectServer(m_serverUrl));
|
||||
connectionOneReadySpy.wait();
|
||||
QVERIFY(connectionOneReadySpy.count() == 1);
|
||||
QVERIFY(connectionOne->isConnected());
|
||||
|
||||
// Connect two
|
||||
QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionTwo->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connectionTwo->connectServer(m_serverUrl));
|
||||
connectionTwoReadySpy.wait();
|
||||
QVERIFY(connectionTwoReadySpy.count() == 1);
|
||||
QVERIFY(connectionTwo->isConnected());
|
||||
@ -345,31 +344,31 @@ void RemoteProxyOfflineTests::trippleConnection()
|
||||
|
||||
// Create two connection
|
||||
RemoteProxyConnection *connectionOne = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this);
|
||||
connectionOne->setInsecureConnection(true);
|
||||
connect(connectionOne, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
RemoteProxyConnection *connectionTwo = new RemoteProxyConnection(QUuid::createUuid(), "Test client two", this);
|
||||
connectionTwo->setInsecureConnection(true);
|
||||
connect(connectionTwo, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
RemoteProxyConnection *connectionThree = new RemoteProxyConnection(QUuid::createUuid(), "Token thief ^w^", this);
|
||||
connectionThree->setInsecureConnection(true);
|
||||
connect(connectionThree, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
// Connect one
|
||||
QSignalSpy connectionOneReadySpy(connectionOne, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionOne->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connectionOne->connectServer(m_serverUrl));
|
||||
connectionOneReadySpy.wait();
|
||||
QVERIFY(connectionOneReadySpy.count() == 1);
|
||||
QVERIFY(connectionOne->isConnected());
|
||||
|
||||
// Connect two
|
||||
QSignalSpy connectionTwoReadySpy(connectionTwo, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionTwo->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connectionTwo->connectServer(m_serverUrl));
|
||||
connectionTwoReadySpy.wait();
|
||||
QVERIFY(connectionTwoReadySpy.count() == 1);
|
||||
QVERIFY(connectionTwo->isConnected());
|
||||
|
||||
// Connect two
|
||||
QSignalSpy connectionThreeReadySpy(connectionThree, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connectionThree->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connectionThree->connectServer(m_serverUrl));
|
||||
connectionThreeReadySpy.wait();
|
||||
QVERIFY(connectionThreeReadySpy.count() == 1);
|
||||
QVERIFY(connectionThree->isConnected());
|
||||
@ -422,16 +421,16 @@ void RemoteProxyOfflineTests::sslConfigurations()
|
||||
// Connect to the server (insecure disabled)
|
||||
RemoteProxyConnection *connector = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this);
|
||||
QSignalSpy spyError(connector, &RemoteProxyConnection::errorOccured);
|
||||
QVERIFY(connector->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connector->connectServer(m_serverUrl));
|
||||
spyError.wait();
|
||||
QVERIFY(spyError.count() == 2);
|
||||
QVERIFY(spyError.count() == 1);
|
||||
QVERIFY(connector->error() == RemoteProxyConnection::ErrorSocketError);
|
||||
QVERIFY(connector->state() == RemoteProxyConnection::StateDisconnected);
|
||||
|
||||
// Connect to server (insecue enabled)
|
||||
QSignalSpy spyConnected(connector, &RemoteProxyConnection::connected);
|
||||
connector->setInsecureConnection(true);
|
||||
connector->connectServer(QHostAddress::LocalHost, m_port);
|
||||
connect(connector, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
connector->connectServer(m_serverUrl);
|
||||
spyConnected.wait();
|
||||
|
||||
QVERIFY(connector->isConnected());
|
||||
|
||||
@ -22,21 +22,19 @@ void RemoteProxyOnlineTests::awsStaticCredentials()
|
||||
|
||||
// Connect to the server (insecure disabled)
|
||||
RemoteProxyConnection *connection = new RemoteProxyConnection(QUuid::createUuid(), "Test client one", this);
|
||||
connection->setInsecureConnection(true);
|
||||
connect(connection, &RemoteProxyConnection::sslErrors, this, &BaseTest::ignoreConnectionSslError);
|
||||
|
||||
// Connect to server (insecue enabled for testing)
|
||||
QSignalSpy readySpy(connection, &RemoteProxyConnection::ready);
|
||||
QVERIFY(connection->connectServer(QHostAddress::LocalHost, m_port));
|
||||
QVERIFY(connection->connectServer(m_serverUrl));
|
||||
readySpy.wait();
|
||||
QVERIFY(readySpy.count() == 1);
|
||||
QVERIFY(connection->isConnected());
|
||||
QVERIFY(!connection->isRemoteConnected());
|
||||
QVERIFY(connection->state() == RemoteProxyConnection::StateReady);
|
||||
QVERIFY(connection->error() == RemoteProxyConnection::ErrorNoError);
|
||||
QVERIFY(connection->serverAddress() == QHostAddress::LocalHost);
|
||||
QVERIFY(connection->serverPort() == m_port);
|
||||
QVERIFY(connection->serverUrl() == m_serverUrl);
|
||||
QVERIFY(connection->connectionType() == RemoteProxyConnection::ConnectionTypeWebSocket);
|
||||
QVERIFY(connection->insecureConnection() == true);
|
||||
QVERIFY(connection->serverName() == SERVER_NAME_STRING);
|
||||
QVERIFY(connection->proxyServerName() == Engine::instance()->serverName());
|
||||
QVERIFY(connection->proxyServerVersion() == SERVER_VERSION_STRING);
|
||||
|
||||
@ -146,6 +146,7 @@ QVariant BaseTest::injectSocketData(const QByteArray &data)
|
||||
{
|
||||
QWebSocket *socket = new QWebSocket("proxy-testclient", QWebSocketProtocol::Version13);
|
||||
connect(socket, &QWebSocket::sslErrors, this, &BaseTest::sslErrors);
|
||||
|
||||
QSignalSpy spyConnection(socket, SIGNAL(connected()));
|
||||
socket->open(Engine::instance()->webSocketServer()->serverUrl());
|
||||
spyConnection.wait();
|
||||
|
||||
@ -29,8 +29,7 @@ public:
|
||||
protected:
|
||||
ProxyConfiguration *m_configuration = nullptr;
|
||||
|
||||
quint16 m_port = 1212;
|
||||
QHostAddress m_serverAddress = QHostAddress::LocalHost;
|
||||
QUrl m_serverUrl = QUrl("wss://127.0.0.1:1212");
|
||||
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
|
||||
@ -65,6 +64,11 @@ public slots:
|
||||
socket->ignoreSslErrors();
|
||||
}
|
||||
|
||||
void ignoreConnectionSslError(const QList<QSslError> &) {
|
||||
RemoteProxyConnection *connection = static_cast<RemoteProxyConnection *>(sender());
|
||||
connection->ignoreSslErrors();
|
||||
}
|
||||
|
||||
inline void verifyError(const QVariant &response, const QString &fieldName, const QString &error)
|
||||
{
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(response);
|
||||
|
||||
Reference in New Issue
Block a user