diff --git a/server/guhconfiguration.cpp b/server/guhconfiguration.cpp new file mode 100644 index 00000000..fff70b2b --- /dev/null +++ b/server/guhconfiguration.cpp @@ -0,0 +1,356 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 Simon Stürz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "loggingcategories.h" +#include "guhconfiguration.h" +#include "guhsettings.h" + +#include +#include + +namespace guhserver { + +GuhConfiguration::GuhConfiguration(QObject *parent) : + QObject(parent) +{ + // Load guhd settings + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("guhd"); + m_serverName = settings.value("name", "guhIO").toString(); + m_timeZone = settings.value("timeZone", QTimeZone::systemTimeZoneId()).toByteArray(); + m_locale = QLocale(settings.value("language", "en_US").toString()); + m_serverUuid = settings.value("uuid", QUuid()).toUuid(); + if (m_serverUuid.isNull()) { + m_serverUuid = QUuid::createUuid(); + settings.setValue("uuid", m_serverUuid); + } + settings.endGroup(); + +#ifndef TESTING_ENABLED + // TcpServer + if (settings.childGroups().contains("TcpServer")) { + settings.beginGroup("TcpServer"); + foreach (const QString &key, settings.childGroups()) { + qDebug() << "have key" << key; + ServerConfiguration config = readServerConfig("TcpServer", key); + m_tcpServerConfigs[config.id] = config; + } + settings.endGroup(); + } else { + qCWarning(dcApplication) << "No TCP Server configuration found. Generating default of 0.0.0.0:2222"; + ServerConfiguration config; + config.id = "default"; + config.address = QHostAddress("0.0.0.0"); + config.port = 2222; + // TODO enable encryption/authentication by default once the important clients are supporting it + config.sslEnabled = false; + config.authenticationEnabled = false; + m_tcpServerConfigs[config.id] = config; + storeServerConfig("TcpServer", config); + } + + // Webserver + if (settings.childGroups().contains("WebServer")) { + settings.beginGroup("WebServer"); + foreach (const QString &key, settings.childGroups()) { + ServerConfiguration tmp = readServerConfig("WebServer", key); + WebServerConfiguration config; + config.id = tmp.id; + config.address = tmp.address; + config.port = tmp.port; + config.sslEnabled = tmp.sslEnabled; + config.authenticationEnabled = tmp.authenticationEnabled; + settings.beginGroup(key); + config.publicFolder = settings.value("publicFolder").toString(); + settings.endGroup(); + m_webServerConfigs[config.id] = config; + } + settings.endGroup(); + } else { + qCWarning(dcApplication) << "No WebServer configuration found. Generating default of 0.0.0.0:3333"; + WebServerConfiguration config; + config.id = "default"; + config.address = QHostAddress("0.0.0.0"); + config.port = 3333; + // TODO enable encryption/authentication by default once the important clients are supporting it + config.sslEnabled = false; + config.authenticationEnabled = false; + config.publicFolder = settings.value("publicFolder", "/usr/share/guh-webinterface/public/").toString(); +#ifdef SNAPPY + // Override default public folder path for snappy + config.publicFolder = settings.value("publicFolder", QString(qgetenv("SNAP")) + "/guh-webinterface/").toString(); +#endif + m_webServerConfigs[config.id] = config; + storeServerConfig("WebServer", config); + } + + // WebSocket Server + if (settings.childGroups().contains("WebSocketServer")) { + settings.beginGroup("WebSocketServer"); + foreach (const QString &key, settings.childGroups()) { + qWarning() << "have key" << key; + ServerConfiguration config = readServerConfig("WebSocketServer", key); + m_webSocketServerConfigs[config.id] = config; + qWarning() << "cound:" << m_webSocketServerConfigs.keys(); + } + settings.endGroup(); + } else { + qCWarning(dcApplication) << "No WebSocketServer configuration found. Generating default of 0.0.0.0:4444"; + ServerConfiguration config; + config.id = "default"; + config.address = QHostAddress("0.0.0.0"); + config.port = 4444; + // TODO enable encryption/authentication by default once the important clients are supporting it + config.sslEnabled = false; + config.authenticationEnabled = false; + m_webSocketServerConfigs[config.id] = config; + storeServerConfig("WebSocketServer", config); + } + + +#else + ServerConfiguration tcpConfig; + tcpConfig.id = "default"; + tcpConfig.address = QHostAddress("127.0.0.1"); + tcpConfig.port = 2222; + tcpConfig.sslEnabled = true; + tcpConfig.authenticationEnabled = true; + m_tcpServerConfigs[tcpConfig.id] = tcpConfig; + + WebServerConfiguration wsConfig; + wsConfig.id = "default"; + wsConfig.address = QHostAddress("127.0.0.1"); + wsConfig.port = 3333; + wsConfig.sslEnabled = true; + wsConfig.authenticationEnabled = true; + wsConfig.publicFolder = qApp->applicationDirPath(); + m_webServerConfigs[wsConfig.id] = wsConfig; + + ServerConfiguration wssConfig; + wssConfig.id = "default"; + wssConfig.address = QHostAddress("127.0.0.1"); + wssConfig.port = 4444; + wssConfig.sslEnabled = true; + wssConfig.authenticationEnabled = true; + m_webSocketServerConfigs[wssConfig.id] = wssConfig; +#endif + + // Bluetooth server + settings.beginGroup("BluetoothServer"); + setBluetoothServerEnabled(settings.value("enabled", false).toBool()); + settings.endGroup(); + + // SSL configuration + settings.beginGroup("SSL"); + setSslCertificate(settings.value("certificate", "/etc/ssl/certs/guhd-certificate.crt").toString(), settings.value("certificate-key", "/etc/ssl/certs/guhd-certificate.key").toString()); + settings.endGroup(); +} + +QUuid GuhConfiguration::serverUuid() const +{ + return m_serverUuid; +} + +QString GuhConfiguration::serverName() const +{ + return m_serverName; +} + +void GuhConfiguration::setServerName(const QString &serverName) +{ + qCDebug(dcApplication()) << "Configuration: Server name:" << serverName; + + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("guhd"); + settings.setValue("name", serverName); + settings.endGroup(); + + m_serverName = serverName; + emit serverNameChanged(); +} + +QByteArray GuhConfiguration::timeZone() const +{ + return m_timeZone; +} + +void GuhConfiguration::setTimeZone(const QByteArray &timeZone) +{ + qCDebug(dcApplication()) << "Configuration: Time zone:" << QString::fromUtf8(timeZone); + + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("guhd"); + settings.setValue("timeZone", timeZone); + settings.endGroup(); + + m_timeZone = timeZone; + emit timeZoneChanged(); +} + +QLocale GuhConfiguration::locale() const +{ + return m_locale; +} + +void GuhConfiguration::setLocale(const QLocale &locale) +{ + qCDebug(dcApplication()) << "Configuration: set locale:" << locale.name() << locale.nativeCountryName() << locale.nativeLanguageName(); + + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("guhd"); + settings.setValue("language", locale.name()); + settings.endGroup(); + + m_locale = locale; + emit localeChanged(); +} + +QHash GuhConfiguration::tcpServerConfigurations() const +{ + return m_tcpServerConfigs; +} + +void GuhConfiguration::setTcpServerConfiguration(const ServerConfiguration &config) +{ + m_tcpServerConfigs[config.id] = config; + storeServerConfig("TcpServer", config); + emit tcpServerConfigurationChanged(config.id); +} + +QHash GuhConfiguration::webServerConfigurations() const +{ + return m_webServerConfigs; +} + +void GuhConfiguration::setWebServerConfiguration(const WebServerConfiguration &config) +{ + m_webServerConfigs[config.id] = config; + + storeServerConfig("WebServer", config); + + // This is a bit odd that we need to open the config once more just for the publicFolder... + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("WebServer"); + settings.beginGroup(config.id); + settings.setValue("publicFolder", config.publicFolder); + settings.endGroup(); + settings.endGroup(); + + emit webServerConfigurationChanged(config.id); +} + +QHash GuhConfiguration::webSocketServerConfigurations() const +{ + return m_webSocketServerConfigs; +} + +void GuhConfiguration::setWebSocketServerConfiguration(const ServerConfiguration &config) +{ + m_webSocketServerConfigs[config.id] = config; + storeServerConfig("WebSocketServer", config); + emit webSocketServerConfigurationChanged(config.id); +} + +bool GuhConfiguration::bluetoothServerEnabled() const +{ + return m_bluetoothServerEnabled; +} + +void GuhConfiguration::setBluetoothServerEnabled(const bool &enabled) +{ + qCDebug(dcApplication()) << "Configuration: Bluetooth server" << (enabled ? "enabled" : "disabled"); + + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("BluetoothServer"); + settings.setValue("enabled", enabled); + settings.endGroup(); + + m_bluetoothServerEnabled = enabled; + emit bluetoothServerEnabled(); +} + +QString GuhConfiguration::sslCertificate() const +{ + return m_sslCertificate; +} + +QString GuhConfiguration::sslCertificateKey() const +{ + return m_sslCertificateKey; +} + +void GuhConfiguration::setSslCertificate(const QString &sslCertificate, const QString &sslCertificateKey) +{ + qCDebug(dcApplication()) << "Configuration: SSL certificate:" << sslCertificate << "SSL certificate key:" << sslCertificateKey; + + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("SSL"); + settings.setValue("certificate", sslCertificate); + settings.setValue("certificate-key", sslCertificateKey); + settings.endGroup(); + + m_sslCertificate = sslCertificate; + m_sslCertificateKey = sslCertificateKey; + + emit sslCertificateChanged(); +} + +void GuhConfiguration::setServerUuid(const QUuid &uuid) +{ + qCDebug(dcApplication()) << "Configuration: Server uuid:" << uuid.toString(); + + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup("guhd"); + settings.setValue("uuid", uuid); + settings.endGroup(); + + m_serverUuid = uuid; +} + +void GuhConfiguration::storeServerConfig(const QString &group, const ServerConfiguration &config) +{ + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup(group); + settings.beginGroup(config.id); + settings.setValue("address", config.address.toString()); + settings.setValue("port", config.port); + settings.setValue("sslEnabled", config.sslEnabled); + settings.setValue("authenticationEnabled", config.authenticationEnabled); + settings.endGroup(); + settings.endGroup(); +} + +ServerConfiguration GuhConfiguration::readServerConfig(const QString &group, const QString &id) +{ + ServerConfiguration config; + GuhSettings settings(GuhSettings::SettingsRoleGlobal); + settings.beginGroup(group); + settings.beginGroup(id); + config.id = id; + config.address = QHostAddress(settings.value("address").toString()); + config.port = settings.value("port").toUInt(); + config.sslEnabled = settings.value("sslEnabled", true).toBool(); + config.authenticationEnabled = settings.value("authenticationEnabled", true).toBool(); + settings.endGroup(); + settings.endGroup(); + return config; +} + +} diff --git a/server/guhconfiguration.h b/server/guhconfiguration.h new file mode 100644 index 00000000..c72e61ba --- /dev/null +++ b/server/guhconfiguration.h @@ -0,0 +1,134 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 Simon Stürz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef GUHCONFIGURATION_H +#define GUHCONFIGURATION_H + +#include +#include +#include +#include +#include + +namespace guhserver { + +class ServerConfiguration { +public: + QString id; + QHostAddress address; + uint port = 0; + bool sslEnabled = true; + bool authenticationEnabled = true; +}; +class WebServerConfiguration: public ServerConfiguration +{ +public: + QString publicFolder; +}; + +class GuhConfiguration : public QObject +{ + Q_OBJECT + Q_ENUMS(ConfigurationError) + +public: + enum ConfigurationError { + ConfigurationErrorNoError, + ConfigurationErrorInvalidTimeZone, + ConfigurationErrorInvalidStationName, + ConfigurationErrorInvalidPort, + ConfigurationErrorInvalidHostAddress, + ConfigurationErrorBluetoothHardwareNotAvailable, + ConfigurationErrorInvalidCertificate + }; + + explicit GuhConfiguration(QObject *parent = 0); + + // Global settings + QUuid serverUuid() const; + + QString serverName() const; + void setServerName(const QString &serverName); + + QByteArray timeZone() const; + void setTimeZone(const QByteArray &timeZone); + + QLocale locale() const; + void setLocale(const QLocale &locale); + + // TCP server + QHash tcpServerConfigurations() const; + void setTcpServerConfiguration(const ServerConfiguration &config); + void removeTcpServerConfiguration(const QUuid &id); + + // Web server + QHash webServerConfigurations() const; + void setWebServerConfiguration(const WebServerConfiguration &config); + + // Websocket + QHash webSocketServerConfigurations() const; + void setWebSocketServerConfiguration(const ServerConfiguration &config); + + // Bluetooth + bool bluetoothServerEnabled() const; + void setBluetoothServerEnabled(const bool &enabled); + + QString sslCertificate() const; + QString sslCertificateKey() const; + void setSslCertificate(const QString &sslCertificate, const QString &sslCertificateKey); + +private: + QUuid m_serverUuid; + QString m_serverName; + QByteArray m_timeZone; + QLocale m_locale; + + QHash m_tcpServerConfigs; + QHash m_webServerConfigs; + QHash m_webSocketServerConfigs; + + bool m_bluetoothServerEnabled; + + QString m_sslCertificate; + QString m_sslCertificateKey; + + void setServerUuid(const QUuid &uuid); + void setWebServerPublicFolder(const QString & path); + + void storeServerConfig(const QString &group, const ServerConfiguration &config); + ServerConfiguration readServerConfig(const QString &group, const QString &id); + +signals: + void serverNameChanged(); + void timeZoneChanged(); + void localeChanged(); + + void tcpServerConfigurationChanged(const QString &configId); + void webServerConfigurationChanged(const QString &configId); + void webSocketServerConfigurationChanged(const QString &configId); + + void bluetoothServerEnabledChanged(); + + void sslCertificateChanged(); +}; + +} + +#endif // GUHCONFIGURATION_H diff --git a/server/guhcore.cpp b/server/guhcore.cpp index fab88a65..fba15f36 100644 --- a/server/guhcore.cpp +++ b/server/guhcore.cpp @@ -367,18 +367,6 @@ TimeManager *GuhCore::timeManager() const return m_timeManager; } -/*! Returns a pointer to the \l{WebServer} instance owned by GuhCore.*/ -WebServer *GuhCore::webServer() const -{ - return m_serverManager->webServer(); -} - -/*! Returns a pointer to the \l{WebSocketServer} instance owned by GuhCore.*/ -WebSocketServer *GuhCore::webSocketServer() const -{ - return m_serverManager->webSocketServer(); -} - /*! Returns a pointer to the \l{ServerManager} instance owned by GuhCore. */ ServerManager *GuhCore::serverManager() const { @@ -409,17 +397,6 @@ UserManager *GuhCore::userManager() const return m_userManager; } -#ifdef TESTING_ENABLED -MockTcpServer -#else -/*! Returns a pointer to the \l{TcpServer} instance owned by GuhCore. */ -TcpServer -#endif -*GuhCore::tcpServer() const -{ - return m_serverManager->tcpServer(); -} - /*! Constructs GuhCore with the given \a parent. This is private. Use \l{GuhCore::instance()} to access the single instance.*/ GuhCore::GuhCore(QObject *parent) : diff --git a/server/guhcore.h b/server/guhcore.h index c7f89f23..136a56ca 100644 --- a/server/guhcore.h +++ b/server/guhcore.h @@ -43,8 +43,6 @@ class Device; namespace guhserver { class JsonRPCServer; -class WebSocketServer; -class TcpServer; class LogEngine; class NetworkManager; @@ -75,8 +73,6 @@ public: DeviceManager *deviceManager() const; RuleEngine *ruleEngine() const; TimeManager *timeManager() const; - WebServer *webServer() const; - WebSocketServer *webSocketServer() const; ServerManager *serverManager() const; BluetoothServer *bluetoothServer() const; NetworkManager *networkManager() const; @@ -84,12 +80,6 @@ public: static QStringList getAvailableLanguages(); -#ifdef TESTING_ENABLED - MockTcpServer *tcpServer() const; -#else - TcpServer *tcpServer() const; -#endif - signals: void pluginConfigChanged(const PluginId &id, const ParamList &config); void eventTriggered(const Event &event); diff --git a/server/jsonrpc/configurationhandler.cpp b/server/jsonrpc/configurationhandler.cpp index 4e1eba58..ddcbb2b7 100644 --- a/server/jsonrpc/configurationhandler.cpp +++ b/server/jsonrpc/configurationhandler.cpp @@ -204,12 +204,25 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap ¶ms) co Q_UNUSED(params) QVariantMap returns; returns.insert("basicConfiguration", JsonTypes::packBasicConfiguration()); - returns.insert("tcpServerConfiguration", JsonTypes::packTcpServerConfiguration()); - returns.insert("webServerConfiguration", JsonTypes::packWebServerConfiguration()); - returns.insert("webSocketServerConfiguration", JsonTypes::packWebSocketServerConfiguration()); - QVariantMap sslConfiguration; - sslConfiguration.insert("enabled", GuhCore::instance()->configuration()->sslEnabled()); - returns.insert("sslConfiguration", sslConfiguration); + QVariantList tcpServerConfigs; + foreach (const ServerConfiguration &config, GuhCore::instance()->configuration()->tcpServerConfigurations()) { + tcpServerConfigs.append(JsonTypes::packServerConfiguration(config)); + } + returns.insert("tcpServerConfigurations", tcpServerConfigs); + + QVariantList webServerConfigs; + foreach (const WebServerConfiguration &config, GuhCore::instance()->configuration()->webServerConfigurations()) { + webServerConfigs.append(JsonTypes::packWebServerConfiguration(config)); + + } + returns.insert("webServerConfigurations", tcpServerConfigs); + + QVariantList webSocketServerConfigs; + foreach (const ServerConfiguration &config, GuhCore::instance()->configuration()->webSocketServerConfigurations()) { + tcpServerConfigs.append(JsonTypes::packServerConfiguration(config)); + } + returns.insert("webServerConfigurations", tcpServerConfigs); + return createReply(returns); } @@ -269,65 +282,60 @@ JsonReply *ConfigurationHandler::SetLanguage(const QVariantMap ¶ms) const JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap ¶ms) const { - QHostAddress host = QHostAddress(params.value("host").toString()); - if (host.isNull()) + ServerConfiguration config = JsonTypes::unpackServerConfiguration(params); + if (config.address.isNull()) return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress)); - uint port = params.value("port").toUInt(); - if (port <= 0 || port > 65535) { + if (config.port <= 0 || config.port > 65535) { qCWarning(dcJsonRpc()) << "Port out of range"; return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidPort)); } - qCDebug(dcJsonRpc()) << QString("Configure TCP server %1:%2").arg(host.toString()).arg(port); + qCDebug(dcJsonRpc()) << QString("Configure TCP server %1:%2").arg(config.address.toString()).arg(config.port); - if (!GuhCore::instance()->tcpServer()->reconfigureServer(host, port)) - return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidPort)); + GuhCore::instance()->configuration()->setTcpServerConfiguration(config); - GuhCore::instance()->configuration()->setTcpServerConfiguration(port, host); +// GuhCore::instance()->tcpServer()->reconfigureServer(config); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError)); } JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap ¶ms) const { - QHostAddress host = QHostAddress(params.value("host").toString()); - if (host.isNull()) + WebServerConfiguration config = JsonTypes::unpackWebServerConfiguration(params); + + if (config.address.isNull()) return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress)); - uint port = params.value("port").toUInt(); - if (port <= 0 || port > 65535) { + if (config.port <= 0 || config.port > 65535) { qCWarning(dcJsonRpc()) << "Port out of range"; return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidPort)); } - qCDebug(dcJsonRpc()) << QString("Configure web server %1:%2").arg(host.toString()).arg(port); + qCDebug(dcJsonRpc()) << QString("Configure web server %1:%2").arg(config.address.toString()).arg(config.port); - if (!GuhCore::instance()->webServer()->reconfigureServer(host, port)) - return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidPort)); + GuhCore::instance()->configuration()->setWebServerConfiguration(config); +// GuhCore::instance()->webServer()->reconfigureServer(config); - GuhCore::instance()->configuration()->setWebServerConfiguration(port, host); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError)); } JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap ¶ms) const { - QHostAddress host = QHostAddress(params.value("host").toString()); - if (host.isNull()) + ServerConfiguration config = JsonTypes::unpackServerConfiguration(params); + if (config.address.isNull()) return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress)); - uint port = params.value("port").toUInt(); - if (port <= 0 || port > 65535) { + if (config.port <= 0 || config.port > 65535) { qCWarning(dcJsonRpc()) << "Port out of range"; return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidPort)); } - qCDebug(dcJsonRpc()) << QString("Configure web socket server %1:%2").arg(host.toString()).arg(port); + qCDebug(dcJsonRpc()) << QString("Configure web socket server %1:%2").arg(config.address.toString()).arg(config.port); - if (!GuhCore::instance()->webSocketServer()->reconfigureServer(host, port)) - return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidPort)); + GuhCore::instance()->configuration()->setWebSocketServerConfiguration(config); +// GuhCore::instance()->webSocketServer()->reconfigureServer(config); - GuhCore::instance()->configuration()->setWebServerConfiguration(port, host); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError)); } @@ -339,27 +347,27 @@ void ConfigurationHandler::onBasicConfigurationChanged() emit BasicConfigurationChanged(params); } -void ConfigurationHandler::onTcpServerConfigurationChanged() +void ConfigurationHandler::onTcpServerConfigurationChanged(const QString &id) { QVariantMap params; qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed"; - params.insert("tcpServerConfiguration", JsonTypes::packTcpServerConfiguration()); + params.insert("tcpServerConfiguration", JsonTypes::packServerConfiguration(GuhCore::instance()->configuration()->tcpServerConfigurations().value(id))); emit TcpServerConfigurationChanged(params); } -void ConfigurationHandler::onWebServerConfigurationChanged() +void ConfigurationHandler::onWebServerConfigurationChanged(const QString &id) { QVariantMap params; qCDebug(dcJsonRpc()) << "Notification: web server configuration changed"; - params.insert("webServerConfiguration", JsonTypes::packWebServerConfiguration()); + params.insert("webServerConfiguration", JsonTypes::packWebServerConfiguration(GuhCore::instance()->configuration()->webServerConfigurations().value(id))); emit WebServerConfigurationChanged(params); } -void ConfigurationHandler::onWebSocketServerConfigurationChanged() +void ConfigurationHandler::onWebSocketServerConfigurationChanged(const QString &id) { QVariantMap params; qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed"; - params.insert("webSocketServerConfiguration", JsonTypes::packWebSocketServerConfiguration()); + params.insert("webSocketServerConfiguration", JsonTypes::packServerConfiguration(GuhCore::instance()->configuration()->webSocketServerConfigurations().value(id))); emit WebSocketServerConfigurationChanged(params); } diff --git a/server/jsonrpc/configurationhandler.h b/server/jsonrpc/configurationhandler.h index 55dff816..5d2afabe 100644 --- a/server/jsonrpc/configurationhandler.h +++ b/server/jsonrpc/configurationhandler.h @@ -54,9 +54,9 @@ signals: private slots: void onBasicConfigurationChanged(); - void onTcpServerConfigurationChanged(); - void onWebServerConfigurationChanged(); - void onWebSocketServerConfigurationChanged(); + void onTcpServerConfigurationChanged(const QString &id); + void onWebServerConfigurationChanged(const QString &id); + void onWebSocketServerConfigurationChanged(const QString &id); void onLanguageChanged(); }; diff --git a/server/jsonrpc/jsontypes.cpp b/server/jsonrpc/jsontypes.cpp index 4a385246..af228d4e 100644 --- a/server/jsonrpc/jsontypes.cpp +++ b/server/jsonrpc/jsontypes.cpp @@ -1088,32 +1088,23 @@ QVariantMap JsonTypes::packBasicConfiguration() return basicConfiguration; } -/*! Returns a variant map with the current tcp configuration of the server. */ -QVariantMap JsonTypes::packTcpServerConfiguration() +QVariantMap JsonTypes::packServerConfiguration(const ServerConfiguration &config) { - QVariantMap tcpServerConfiguration; - tcpServerConfiguration.insert("host", GuhCore::instance()->configuration()->tcpServerAddress().toString()); - tcpServerConfiguration.insert("port", GuhCore::instance()->configuration()->tcpServerPort()); - return tcpServerConfiguration; + QVariantMap serverConfiguration; + serverConfiguration.insert("host", config.address.toString()); + serverConfiguration.insert("port", config.port); + serverConfiguration.insert("sslEnabled", config.sslEnabled); + serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled); + return serverConfiguration; } -/*! Returns a variant map with the current web server configuration of the server. */ -QVariantMap JsonTypes::packWebServerConfiguration() +QVariantMap JsonTypes::packWebServerConfiguration(const WebServerConfiguration &config) { - QVariantMap webServerConfiguration; - webServerConfiguration.insert("host", GuhCore::instance()->configuration()->webServerAddress().toString()); - webServerConfiguration.insert("port", GuhCore::instance()->configuration()->webServerPort()); + QVariantMap webServerConfiguration = packServerConfiguration(config); + webServerConfiguration.insert("publicFolder", config.publicFolder); return webServerConfiguration; } -/*! Returns a variant map with the current web socket server configuration of the server. */ -QVariantMap JsonTypes::packWebSocketServerConfiguration() -{ - QVariantMap webSocketServerConfiguration; - webSocketServerConfiguration.insert("host", GuhCore::instance()->configuration()->webSocketAddress().toString()); - webSocketServerConfiguration.insert("port", GuhCore::instance()->configuration()->webSocketPort()); - return webSocketServerConfiguration; -} /*! Returns a variant list containing all rule descriptions. */ QVariantList JsonTypes::packRuleDescriptions() @@ -1527,6 +1518,30 @@ TimeDescriptor JsonTypes::unpackTimeDescriptor(const QVariantMap &timeDescriptor return timeDescriptor; } +ServerConfiguration JsonTypes::unpackServerConfiguration(const QVariantMap &serverConfigurationMap) +{ + ServerConfiguration serverConfiguration; + serverConfiguration.id = serverConfigurationMap.value("id").toString(); + serverConfiguration.address = QHostAddress(serverConfigurationMap.value("address").toString()); + serverConfiguration.port = serverConfigurationMap.value("port").toUInt(); + serverConfiguration.sslEnabled = serverConfigurationMap.value("sslEnabled", true).toBool(); + serverConfiguration.authenticationEnabled = serverConfigurationMap.value("authenticationEnabled", true).toBool(); + return serverConfiguration; +} + +WebServerConfiguration JsonTypes::unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap) +{ + ServerConfiguration tmp = unpackServerConfiguration(webServerConfigurationMap); + WebServerConfiguration webServerConfiguration; + webServerConfiguration.id = tmp.id; + webServerConfiguration.address = tmp.address; + webServerConfiguration.port = tmp.port; + webServerConfiguration.sslEnabled = tmp.sslEnabled; + webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled; + webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString(); + return webServerConfiguration; +} + /*! Compairs the given \a map with the given \a templateMap. Returns the error string and false if the params are not valid. */ QPair JsonTypes::validateMap(const QVariantMap &templateMap, const QVariantMap &map) diff --git a/server/jsonrpc/jsontypes.h b/server/jsonrpc/jsontypes.h index c60a2c54..63413e89 100644 --- a/server/jsonrpc/jsontypes.h +++ b/server/jsonrpc/jsontypes.h @@ -207,9 +207,8 @@ public: static QVariantList packDeviceDescriptors(const QList deviceDescriptors); static QVariantMap packBasicConfiguration(); - static QVariantMap packTcpServerConfiguration(); - static QVariantMap packWebServerConfiguration(); - static QVariantMap packWebSocketServerConfiguration(); + static QVariantMap packServerConfiguration(const ServerConfiguration &config); + static QVariantMap packWebServerConfiguration(const WebServerConfiguration &config); static QVariantList packRuleDescriptions(); static QVariantList packRuleDescriptions(const QList &rules); @@ -241,6 +240,9 @@ public: static TimeEventItem unpackTimeEventItem(const QVariantMap &timeEventItemMap); static TimeDescriptor unpackTimeDescriptor(const QVariantMap &timeDescriptorMap); + static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap); + static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap); + // validate static QPair validateMap(const QVariantMap &templateMap, const QVariantMap &map); static QPair validateProperty(const QVariant &templateValue, const QVariant &value); diff --git a/server/servermanager.cpp b/server/servermanager.cpp index 2cc4611e..0e22a3d7 100644 --- a/server/servermanager.cpp +++ b/server/servermanager.cpp @@ -48,10 +48,10 @@ ServerManager::ServerManager(GuhConfiguration* configuration, QObject *parent) : QObject(parent), m_sslConfiguration(QSslConfiguration()) { - // check SSL - if (!configuration->sslEnabled()) { - qCDebug(dcConnection) << "SSL encryption disabled by config."; - } else if (!QSslSocket::supportsSsl()) { + // TODO: check this + + + if (!QSslSocket::supportsSsl()) { qCWarning(dcConnection) << "SSL is not supported/installed on this platform."; } else { qCDebug(dcConnection) << "SSL library version:" << QSslSocket::sslLibraryVersionString(); @@ -93,23 +93,28 @@ ServerManager::ServerManager(GuhConfiguration* configuration, QObject *parent) : // Transports #ifdef TESTING_ENABLED - m_tcpServer = new MockTcpServer(this); + MockTcpServer *tcpServer = new MockTcpServer(this); + m_jsonServer->registerTransportInterface(tcpServer); #else - m_tcpServer = new TcpServer(configuration->tcpServerAddress(), configuration->tcpServerPort(), configuration->sslEnabled(), m_sslConfiguration, this); + foreach (const ServerConfiguration &config, configuration->tcpServerConfigurations()) { + TcpServer *tcpServer = new TcpServer(config.address, config.port, config.sslEnabled, m_sslConfiguration, this); + m_jsonServer->registerTransportInterface(tcpServer); + } #endif - m_webSocketServer = new WebSocketServer(configuration->webSocketAddress(), configuration->webSocketPort(), configuration->sslEnabled(), m_sslConfiguration, this); + foreach (const ServerConfiguration &config, configuration->webSocketServerConfigurations()) { + qWarning() << "Have websockeserver config" << config.id; + WebSocketServer *webSocketServer = new WebSocketServer(config.address, config.port, config.sslEnabled, m_sslConfiguration, this); + m_jsonServer->registerTransportInterface(webSocketServer); + } m_bluetoothServer = new BluetoothServer(this); - - // Register transport interfaces for the JSON RPC server - m_jsonServer->registerTransportInterface(m_tcpServer); - m_jsonServer->registerTransportInterface(m_webSocketServer); m_jsonServer->registerTransportInterface(m_bluetoothServer, configuration->bluetoothServerEnabled()); - // Register transport itnerfaces for the Webserver - m_webServer = new WebServer(configuration->webServerAddress(), configuration->webServerPort(), configuration->webServerPublicFolder(), configuration->sslEnabled(), m_sslConfiguration, this); - m_restServer->registerWebserver(m_webServer); + foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) { + WebServer *webServer = new WebServer(config.address, config.port, config.publicFolder, config.sslEnabled, m_sslConfiguration, this); + m_restServer->registerWebserver(webServer); + } } /*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */ @@ -124,31 +129,11 @@ RestServer *ServerManager::restServer() const return m_restServer; } -WebServer *ServerManager::webServer() const -{ - return m_webServer; -} - -WebSocketServer *ServerManager::webSocketServer() const -{ - return m_webSocketServer; -} - BluetoothServer *ServerManager::bluetoothServer() const { return m_bluetoothServer; } -#ifdef TESTING_ENABLED -MockTcpServer -#else -TcpServer -#endif -*ServerManager::tcpServer() const -{ - return m_tcpServer; -} - bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName) { QFile certificateKeyFile(certificateKeyFileName); diff --git a/server/servermanager.h b/server/servermanager.h index 401ef7a5..6b51cfb7 100644 --- a/server/servermanager.h +++ b/server/servermanager.h @@ -67,14 +67,6 @@ private: JsonRPCServer *m_jsonServer; RestServer *m_restServer; - // Transports -#ifdef TESTING_ENABLED - MockTcpServer *m_tcpServer; -#else - TcpServer *m_tcpServer; -#endif - WebSocketServer *m_webSocketServer; - WebServer *m_webServer; BluetoothServer *m_bluetoothServer; // Encrytption and stuff diff --git a/server/webserver.cpp b/server/webserver.cpp index da208938..0dfc3655 100644 --- a/server/webserver.cpp +++ b/server/webserver.cpp @@ -564,7 +564,6 @@ bool WebServer::startServer() #ifndef TESTING_ENABLED // Note: reversed order QHash txt; - txt.insert("sslEnabled", GuhCore::instance()->configuration()->sslEnabled() ? "true" : "false"); txt.insert("jsonrpcVersion", JSON_PROTOCOL_VERSION); txt.insert("serverVersion", GUH_VERSION_STRING); txt.insert("manufacturer", "guh GmbH"); @@ -598,7 +597,11 @@ bool WebServer::stopServer() QByteArray WebServer::createServerXmlDocument(QHostAddress address) { QByteArray uuid = GuhCore::instance()->configuration()->serverUuid().toByteArray(); - uint websocketPort = GuhCore::instance()->configuration()->webSocketPort(); + + // TODO: support multiple (or none) configured servers here, let's just use the first valid config for now + Q_ASSERT_X(GuhCore::instance()->configuration()->webSocketServerConfigurations().count() > 0, "WebServer", "No WebSocket Server config found. This is not supported"); + + uint websocketPort = GuhCore::instance()->configuration()->webSocketServerConfigurations().values().first().port; QByteArray data; QXmlStreamWriter writer(&data); diff --git a/server/websocketserver.cpp b/server/websocketserver.cpp index 601c8e1e..7882ff2f 100644 --- a/server/websocketserver.cpp +++ b/server/websocketserver.cpp @@ -246,7 +246,6 @@ bool WebSocketServer::startServer() #ifndef TESTING_ENABLED // Note: reversed order QHash txt; - txt.insert("sslEnabled", GuhCore::instance()->configuration()->sslEnabled() ? "true" : "false"); txt.insert("jsonrpcVersion", JSON_PROTOCOL_VERSION); txt.insert("serverVersion", GUH_VERSION_STRING); txt.insert("manufacturer", "guh GmbH");