diff --git a/README.md b/README.md index 41a0f4c..19e273d 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,56 @@ The client allowes you to test the proxy server and create a dummy client for te -p, --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 diff --git a/client/main.cpp b/client/main.cpp index 7204f4b..80e44e7 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,51 +7,133 @@ #include "proxyclient.h" +static QHash 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 \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 or --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(); } diff --git a/client/proxyclient.cpp b/client/proxyclient.cpp index 7f3aac7..57a5bd0 100644 --- a/client/proxyclient.cpp +++ b/client/proxyclient.cpp @@ -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 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(m_port)); + m_connection->connectServer(url); } diff --git a/client/proxyclient.h b/client/proxyclient.h index ae50634..a0929c1 100644 --- a/client/proxyclient.h +++ b/client/proxyclient.h @@ -2,38 +2,40 @@ #define PROXYCLIENT_H #include +#include #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 errors); public slots: - void start(const QString &token); + void start(const QUrl &url, const QString &token); }; diff --git a/libnymea-remoteproxy/jsonrpcserver.cpp b/libnymea-remoteproxy/jsonrpcserver.cpp index 386f5d0..31c32b1 100644 --- a/libnymea-remoteproxy/jsonrpcserver.cpp +++ b/libnymea-remoteproxy/jsonrpcserver.cpp @@ -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 diff --git a/libnymea-remoteproxy/proxyconfiguration.cpp b/libnymea-remoteproxy/proxyconfiguration.cpp index 4f2f308..6af1578 100644 --- a/libnymea-remoteproxy/proxyconfiguration.cpp +++ b/libnymea-remoteproxy/proxyconfiguration.cpp @@ -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(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; diff --git a/libnymea-remoteproxy/proxyconfiguration.h b/libnymea-remoteproxy/proxyconfiguration.h index 41b5ebe..411a7c7 100644 --- a/libnymea-remoteproxy/proxyconfiguration.h +++ b/libnymea-remoteproxy/proxyconfiguration.h @@ -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 diff --git a/libnymea-remoteproxyclient/jsonreply.cpp b/libnymea-remoteproxyclient/jsonreply.cpp index 1ab1cf1..f03122a 100644 --- a/libnymea-remoteproxyclient/jsonreply.cpp +++ b/libnymea-remoteproxyclient/jsonreply.cpp @@ -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; diff --git a/libnymea-remoteproxyclient/proxyconnection.cpp b/libnymea-remoteproxyclient/proxyconnection.cpp index c18738c..b8c121e 100644 --- a/libnymea-remoteproxyclient/proxyconnection.cpp +++ b/libnymea-remoteproxyclient/proxyconnection.cpp @@ -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; -} - } diff --git a/libnymea-remoteproxyclient/proxyconnection.h b/libnymea-remoteproxyclient/proxyconnection.h index cbbfea6..9110524 100644 --- a/libnymea-remoteproxyclient/proxyconnection.h +++ b/libnymea-remoteproxyclient/proxyconnection.h @@ -2,6 +2,7 @@ #define SOCKETCONNECTOR_H #include +#include #include 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 &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 &errors); public slots: - virtual void connectServer(const QHostAddress &address, quint16 port) = 0; + virtual void connectServer(const QUrl &serverUrl) = 0; virtual void disconnectServer() = 0; }; diff --git a/libnymea-remoteproxyclient/proxyjsonrpcclient.cpp b/libnymea-remoteproxyclient/proxyjsonrpcclient.cpp index ba9ad7c..7e2368e 100644 --- a/libnymea-remoteproxyclient/proxyjsonrpcclient.cpp +++ b/libnymea-remoteproxyclient/proxyjsonrpcclient.cpp @@ -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); diff --git a/libnymea-remoteproxyclient/remoteproxyconnection.cpp b/libnymea-remoteproxyclient/remoteproxyconnection.cpp index 498fc01..9c2951c 100644 --- a/libnymea-remoteproxyclient/remoteproxyconnection.cpp +++ b/libnymea-remoteproxyclient/remoteproxyconnection.cpp @@ -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 &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(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(new WebSocketConnection(this)); + break; + case ConnectionTypeTcpSocket: + // FIXME: + m_connection = qobject_cast(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; } diff --git a/libnymea-remoteproxyclient/remoteproxyconnection.h b/libnymea-remoteproxyclient/remoteproxyconnection.h index cbc264a..156e846 100644 --- a/libnymea-remoteproxyclient/remoteproxyconnection.h +++ b/libnymea-remoteproxyclient/remoteproxyconnection.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -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 &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 &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(); diff --git a/libnymea-remoteproxyclient/websocketconnection.cpp b/libnymea-remoteproxyclient/websocketconnection.cpp index b1acaac..bcf5d53 100644 --- a/libnymea-remoteproxyclient/websocketconnection.cpp +++ b/libnymea-remoteproxyclient/websocketconnection.cpp @@ -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)), this, SLOT(onSslError(QList))); connect(m_webSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onStateChanged(QAbstractSocket::SocketState))); + connect(m_webSocket, SIGNAL(sslErrors(QList)), this, SIGNAL(sslErrors(QList))); } 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 &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 &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(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(); } diff --git a/libnymea-remoteproxyclient/websocketconnection.h b/libnymea-remoteproxyclient/websocketconnection.h index 57bb9d5..390fee3 100644 --- a/libnymea-remoteproxyclient/websocketconnection.h +++ b/libnymea-remoteproxyclient/websocketconnection.h @@ -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 &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 &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; }; diff --git a/nymea-remoteproxy.conf b/nymea-remoteproxy.conf index d5036bc..c75cda8 100644 --- a/nymea-remoteproxy.conf +++ b/nymea-remoteproxy.conf @@ -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 diff --git a/server/main.cpp b/server/main.cpp index 0cfe70f..f5507c6 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -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 \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(new DummyAuthenticator(nullptr)); diff --git a/tests/test-offline/nymea-remoteproxy-tests-offline.cpp b/tests/test-offline/nymea-remoteproxy-tests-offline.cpp index 4188ce3..6b056a3 100644 --- a/tests/test-offline/nymea-remoteproxy-tests-offline.cpp +++ b/tests/test-offline/nymea-remoteproxy-tests-offline.cpp @@ -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()); diff --git a/tests/test-online/nymea-remoteproxy-tests-online.cpp b/tests/test-online/nymea-remoteproxy-tests-online.cpp index 452b53e..10d7b42 100644 --- a/tests/test-online/nymea-remoteproxy-tests-online.cpp +++ b/tests/test-online/nymea-remoteproxy-tests-online.cpp @@ -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); diff --git a/tests/testbase/basetest.cpp b/tests/testbase/basetest.cpp index 6db3d13..ef4c64d 100644 --- a/tests/testbase/basetest.cpp +++ b/tests/testbase/basetest.cpp @@ -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(); diff --git a/tests/testbase/basetest.h b/tests/testbase/basetest.h index 260a951..11336df 100644 --- a/tests/testbase/basetest.h +++ b/tests/testbase/basetest.h @@ -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 &) { + RemoteProxyConnection *connection = static_cast(sender()); + connection->ignoreSslErrors(); + } + inline void verifyError(const QVariant &response, const QString &fieldName, const QString &error) { QJsonDocument jsonDoc = QJsonDocument::fromVariant(response);