added ability to configure each server interface individually

This commit is contained in:
Michael Zanetti 2017-09-03 23:19:04 +02:00
parent 63ffc163ba
commit 44dd07950b
25 changed files with 508 additions and 225 deletions

View File

@ -5,7 +5,7 @@ GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"')
GUH_PLUGINS_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/guh/plugins/ GUH_PLUGINS_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/guh/plugins/
# define protocol versions # define protocol versions
JSON_PROTOCOL_VERSION=49 JSON_PROTOCOL_VERSION=50
REST_API_VERSION=1 REST_API_VERSION=1
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \ DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \

View File

@ -45,7 +45,7 @@ namespace guhserver {
static const QBluetoothUuid serviceUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b")); static const QBluetoothUuid serviceUuid(QUuid("997936b5-d2cd-4c57-b41b-c6048320cd2b"));
/*! Constructs a \l{BluetoothServer} with the given \a parent. */ /*! Constructs a \l{BluetoothServer} with the given \a parent. */
BluetoothServer::BluetoothServer(QObject *parent) : BluetoothServer::BluetoothServer(QObject *parent) :
TransportInterface(parent), TransportInterface(ServerConfiguration(), parent),
m_server(0) m_server(0)
{ {

View File

@ -48,7 +48,6 @@ GuhConfiguration::GuhConfiguration(QObject *parent) :
if (settings.childGroups().contains("TcpServer")) { if (settings.childGroups().contains("TcpServer")) {
settings.beginGroup("TcpServer"); settings.beginGroup("TcpServer");
foreach (const QString &key, settings.childGroups()) { foreach (const QString &key, settings.childGroups()) {
qDebug() << "have key" << key;
ServerConfiguration config = readServerConfig("TcpServer", key); ServerConfiguration config = readServerConfig("TcpServer", key);
m_tcpServerConfigs[config.id] = config; m_tcpServerConfigs[config.id] = config;
} }
@ -70,16 +69,7 @@ GuhConfiguration::GuhConfiguration(QObject *parent) :
if (settings.childGroups().contains("WebServer")) { if (settings.childGroups().contains("WebServer")) {
settings.beginGroup("WebServer"); settings.beginGroup("WebServer");
foreach (const QString &key, settings.childGroups()) { foreach (const QString &key, settings.childGroups()) {
ServerConfiguration tmp = readServerConfig("WebServer", key); WebServerConfiguration config = readWebServerConfig(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; m_webServerConfigs[config.id] = config;
} }
settings.endGroup(); settings.endGroup();
@ -92,23 +82,21 @@ GuhConfiguration::GuhConfiguration(QObject *parent) :
// TODO enable encryption/authentication by default once the important clients are supporting it // TODO enable encryption/authentication by default once the important clients are supporting it
config.sslEnabled = false; config.sslEnabled = false;
config.authenticationEnabled = false; config.authenticationEnabled = false;
config.publicFolder = settings.value("publicFolder", "/usr/share/guh-webinterface/public/").toString(); config.publicFolder = "/usr/share/guh-webinterface/public/";
#ifdef SNAPPY #ifdef SNAPPY
// Override default public folder path for snappy // Override default public folder path for snappy
config.publicFolder = settings.value("publicFolder", QString(qgetenv("SNAP")) + "/guh-webinterface/").toString(); config.publicFolder = settings.value("publicFolder", QString(qgetenv("SNAP")) + "/guh-webinterface/").toString();
#endif #endif
m_webServerConfigs[config.id] = config; m_webServerConfigs[config.id] = config;
storeServerConfig("WebServer", config); storeWebServerConfig(config);
} }
// WebSocket Server // WebSocket Server
if (settings.childGroups().contains("WebSocketServer")) { if (settings.childGroups().contains("WebSocketServer")) {
settings.beginGroup("WebSocketServer"); settings.beginGroup("WebSocketServer");
foreach (const QString &key, settings.childGroups()) { foreach (const QString &key, settings.childGroups()) {
qWarning() << "have key" << key;
ServerConfiguration config = readServerConfig("WebSocketServer", key); ServerConfiguration config = readServerConfig("WebSocketServer", key);
m_webSocketServerConfigs[config.id] = config; m_webSocketServerConfigs[config.id] = config;
qWarning() << "cound:" << m_webSocketServerConfigs.keys();
} }
settings.endGroup(); settings.endGroup();
} else { } else {
@ -234,6 +222,13 @@ void GuhConfiguration::setTcpServerConfiguration(const ServerConfiguration &conf
emit tcpServerConfigurationChanged(config.id); emit tcpServerConfigurationChanged(config.id);
} }
void GuhConfiguration::removeTcpServerConfiguration(const QString &id)
{
m_tcpServerConfigs.take(id);
deleteServerConfig("TcpServer", id);
emit tcpServerConfigurationRemoved(id);
}
QHash<QString, WebServerConfiguration> GuhConfiguration::webServerConfigurations() const QHash<QString, WebServerConfiguration> GuhConfiguration::webServerConfigurations() const
{ {
return m_webServerConfigs; return m_webServerConfigs;
@ -256,6 +251,13 @@ void GuhConfiguration::setWebServerConfiguration(const WebServerConfiguration &c
emit webServerConfigurationChanged(config.id); emit webServerConfigurationChanged(config.id);
} }
void GuhConfiguration::removeWebServerConfiguration(const QString &id)
{
m_webServerConfigs.take(id);
deleteServerConfig("WebServer", id);
emit webServerConfigurationRemoved(id);
}
QHash<QString, ServerConfiguration> GuhConfiguration::webSocketServerConfigurations() const QHash<QString, ServerConfiguration> GuhConfiguration::webSocketServerConfigurations() const
{ {
return m_webSocketServerConfigs; return m_webSocketServerConfigs;
@ -268,6 +270,13 @@ void GuhConfiguration::setWebSocketServerConfiguration(const ServerConfiguration
emit webSocketServerConfigurationChanged(config.id); emit webSocketServerConfigurationChanged(config.id);
} }
void GuhConfiguration::removeWebSocketServerConfiguration(const QString &id)
{
m_webSocketServerConfigs.take(id);
deleteServerConfig("WebSocketServer", id);
emit webSocketServerConfigurationRemoved(id);
}
bool GuhConfiguration::bluetoothServerEnabled() const bool GuhConfiguration::bluetoothServerEnabled() const
{ {
return m_bluetoothServerEnabled; return m_bluetoothServerEnabled;
@ -328,6 +337,7 @@ void GuhConfiguration::storeServerConfig(const QString &group, const ServerConfi
{ {
GuhSettings settings(GuhSettings::SettingsRoleGlobal); GuhSettings settings(GuhSettings::SettingsRoleGlobal);
settings.beginGroup(group); settings.beginGroup(group);
settings.remove("disabled");
settings.beginGroup(config.id); settings.beginGroup(config.id);
settings.setValue("address", config.address.toString()); settings.setValue("address", config.address.toString());
settings.setValue("port", config.port); settings.setValue("port", config.port);
@ -353,4 +363,43 @@ ServerConfiguration GuhConfiguration::readServerConfig(const QString &group, con
return config; return config;
} }
void GuhConfiguration::deleteServerConfig(const QString &group, const QString &id)
{
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
settings.beginGroup(group);
settings.remove(id);
if (settings.childGroups().isEmpty()) {
settings.setValue("disabled", true);
}
settings.endGroup();
}
void GuhConfiguration::storeWebServerConfig(const WebServerConfiguration &config)
{
storeServerConfig("WebServer", config);
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
settings.beginGroup("WebServer");
settings.beginGroup(config.id);
settings.setValue("publicFolder", config.publicFolder);
settings.endGroup();
settings.endGroup();
}
WebServerConfiguration GuhConfiguration::readWebServerConfig(const QString &id)
{
WebServerConfiguration config;
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
settings.beginGroup("WebServer");
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();
config.publicFolder = settings.value("publicFolder").toString();
settings.endGroup();
settings.endGroup();
return config;
}
} }

View File

@ -36,6 +36,14 @@ public:
uint port = 0; uint port = 0;
bool sslEnabled = true; bool sslEnabled = true;
bool authenticationEnabled = true; bool authenticationEnabled = true;
bool operator==(const ServerConfiguration &other) {
return id == other.id
&& address == other.address
&& port == other.port
&& sslEnabled == other.sslEnabled
&& authenticationEnabled == other.authenticationEnabled;
}
}; };
class WebServerConfiguration: public ServerConfiguration class WebServerConfiguration: public ServerConfiguration
{ {
@ -53,6 +61,7 @@ public:
ConfigurationErrorNoError, ConfigurationErrorNoError,
ConfigurationErrorInvalidTimeZone, ConfigurationErrorInvalidTimeZone,
ConfigurationErrorInvalidStationName, ConfigurationErrorInvalidStationName,
ConfigurationErrorInvalidId,
ConfigurationErrorInvalidPort, ConfigurationErrorInvalidPort,
ConfigurationErrorInvalidHostAddress, ConfigurationErrorInvalidHostAddress,
ConfigurationErrorBluetoothHardwareNotAvailable, ConfigurationErrorBluetoothHardwareNotAvailable,
@ -76,15 +85,17 @@ public:
// TCP server // TCP server
QHash<QString, ServerConfiguration> tcpServerConfigurations() const; QHash<QString, ServerConfiguration> tcpServerConfigurations() const;
void setTcpServerConfiguration(const ServerConfiguration &config); void setTcpServerConfiguration(const ServerConfiguration &config);
void removeTcpServerConfiguration(const QUuid &id); void removeTcpServerConfiguration(const QString &id);
// Web server // Web server
QHash<QString, WebServerConfiguration> webServerConfigurations() const; QHash<QString, WebServerConfiguration> webServerConfigurations() const;
void setWebServerConfiguration(const WebServerConfiguration &config); void setWebServerConfiguration(const WebServerConfiguration &config);
void removeWebServerConfiguration(const QString &id);
// Websocket // Websocket
QHash<QString, ServerConfiguration> webSocketServerConfigurations() const; QHash<QString, ServerConfiguration> webSocketServerConfigurations() const;
void setWebSocketServerConfiguration(const ServerConfiguration &config); void setWebSocketServerConfiguration(const ServerConfiguration &config);
void removeWebSocketServerConfiguration(const QString &id);
// Bluetooth // Bluetooth
bool bluetoothServerEnabled() const; bool bluetoothServerEnabled() const;
@ -114,6 +125,9 @@ private:
void storeServerConfig(const QString &group, const ServerConfiguration &config); void storeServerConfig(const QString &group, const ServerConfiguration &config);
ServerConfiguration readServerConfig(const QString &group, const QString &id); ServerConfiguration readServerConfig(const QString &group, const QString &id);
void deleteServerConfig(const QString &group, const QString &id);
void storeWebServerConfig(const WebServerConfiguration &config);
WebServerConfiguration readWebServerConfig(const QString &id);
signals: signals:
void serverNameChanged(); void serverNameChanged();
@ -121,8 +135,11 @@ signals:
void localeChanged(); void localeChanged();
void tcpServerConfigurationChanged(const QString &configId); void tcpServerConfigurationChanged(const QString &configId);
void tcpServerConfigurationRemoved(const QString &configId);
void webServerConfigurationChanged(const QString &configId); void webServerConfigurationChanged(const QString &configId);
void webServerConfigurationRemoved(const QString &configId);
void webSocketServerConfigurationChanged(const QString &configId); void webSocketServerConfigurationChanged(const QString &configId);
void webSocketServerConfigurationRemoved(const QString &configId);
void bluetoothServerEnabledChanged(); void bluetoothServerEnabledChanged();

View File

@ -402,6 +402,10 @@ UserManager *GuhCore::userManager() const
GuhCore::GuhCore(QObject *parent) : GuhCore::GuhCore(QObject *parent) :
QObject(parent) QObject(parent)
{ {
staticMetaObject.invokeMethod(this, "init", Qt::QueuedConnection);
}
void GuhCore::init() {
qCDebug(dcApplication()) << "Loading guh configurations" << GuhSettings(GuhSettings::SettingsRoleGlobal).fileName(); qCDebug(dcApplication()) << "Loading guh configurations" << GuhSettings(GuhSettings::SettingsRoleGlobal).fileName();
m_configuration = new GuhConfiguration(this); m_configuration = new GuhConfiguration(this);
@ -447,6 +451,7 @@ GuhCore::GuhCore(QObject *parent) :
connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManager::timeTick); connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManager::timeTick);
m_logger->logSystemEvent(m_timeManager->currentDateTime(), true); m_logger->logSystemEvent(m_timeManager->currentDateTime(), true);
emit initialized();
} }
/*! Connected to the DeviceManager's emitEvent signal. Events received in /*! Connected to the DeviceManager's emitEvent signal. Events received in

View File

@ -81,6 +81,8 @@ public:
static QStringList getAvailableLanguages(); static QStringList getAvailableLanguages();
signals: signals:
void initialized();
void pluginConfigChanged(const PluginId &id, const ParamList &config); void pluginConfigChanged(const PluginId &id, const ParamList &config);
void eventTriggered(const Event &event); void eventTriggered(const Event &event);
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value); void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
@ -115,6 +117,7 @@ private:
QHash<ActionId, Action> m_pendingActions; QHash<ActionId, Action> m_pendingActions;
private slots: private slots:
void init();
void gotEvent(const Event &event); void gotEvent(const Event &event);
void onDateTimeChanged(const QDateTime &dateTime); void onDateTimeChanged(const QDateTime &dateTime);
void onLocaleChanged(); void onLocaleChanged();

View File

@ -90,21 +90,15 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
basicConfiguration.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String)); basicConfiguration.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String));
basicConfiguration.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); basicConfiguration.insert("language", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("basicConfiguration", basicConfiguration); returns.insert("basicConfiguration", basicConfiguration);
QVariantMap tcpServerConfiguration; QVariantList tcpServerConfigurations;
tcpServerConfiguration.insert("host", JsonTypes::basicTypeToString(JsonTypes::String)); tcpServerConfigurations.append(JsonTypes::serverConfigurationRef());
tcpServerConfiguration.insert("port", JsonTypes::basicTypeToString(JsonTypes::Uint)); returns.insert("tcpServerConfigurations", tcpServerConfigurations);
returns.insert("tcpServerConfiguration", tcpServerConfiguration); QVariantList webServerConfigurations;
QVariantMap webServerConfiguration; webServerConfigurations.append(JsonTypes::webServerConfigurationRef());
webServerConfiguration.insert("host", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("webServerConfigurations", webServerConfigurations);
webServerConfiguration.insert("port", JsonTypes::basicTypeToString(JsonTypes::Uint)); QVariantList webSocketServerConfigurations;
returns.insert("webServerConfiguration", webServerConfiguration); webSocketServerConfigurations.append(JsonTypes::serverConfigurationRef());
QVariantMap webSocketServerConfiguration; returns.insert("webSocketServerConfigurations", webSocketServerConfigurations);
webSocketServerConfiguration.insert("host", JsonTypes::basicTypeToString(JsonTypes::String));
webSocketServerConfiguration.insert("port", JsonTypes::basicTypeToString(JsonTypes::Uint));
returns.insert("webSocketServerConfiguration", webSocketServerConfiguration);
QVariantMap sslConfiguration;
sslConfiguration.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
returns.insert("sslConfiguration", sslConfiguration);
setReturns("GetConfigurations", returns); setReturns("GetConfigurations", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
@ -129,29 +123,47 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
setReturns("SetLanguage", returns); setReturns("SetLanguage", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetTcpServerConfiguration", "Configure the TCP interface of the server. Note: if you are using the TCP server for this call you will loose the connection."); setDescription("SetTcpServerConfiguration", "Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped.");
params.insert("host", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("configuration", JsonTypes::serverConfigurationRef());
params.insert("port", JsonTypes::basicTypeToString(JsonTypes::Uint));
setParams("SetTcpServerConfiguration", params); setParams("SetTcpServerConfiguration", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef()); returns.insert("configurationError", JsonTypes::configurationErrorRef());
setReturns("SetTcpServerConfiguration", returns); setReturns("SetTcpServerConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetWebSocketServerConfiguration", "Configure the web socket interface of the server. Note: if you are using the web socket server for this call you will loose the connection."); setDescription("DeleteTcpServerConfiguration", "Delete a TCP interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped.");
params.insert("host", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("id", JsonTypes::basicTypeToString(QVariant::String));
params.insert("port", JsonTypes::basicTypeToString(JsonTypes::Uint)); setParams("DeleteTcpServerConfiguration", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef());
setReturns("DeleteTcpServerConfiguration", returns);
params.clear(); returns.clear();
setDescription("SetWebSocketServerConfiguration", "Configure a WebSocket Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped.");
params.insert("configuration", JsonTypes::serverConfigurationRef());
setParams("SetWebSocketServerConfiguration", params); setParams("SetWebSocketServerConfiguration", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef()); returns.insert("configurationError", JsonTypes::configurationErrorRef());
setReturns("SetWebSocketServerConfiguration", returns); setReturns("SetWebSocketServerConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetWebServerConfiguration", "Configure the web server of the server."); setDescription("DeleteWebSocketServerConfiguration", "Delete a WebSocket Server interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped.");
params.insert("host", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("id", JsonTypes::basicTypeToString(QVariant::String));
params.insert("port", JsonTypes::basicTypeToString(JsonTypes::Uint)); setParams("DeleteWebSocketServerConfiguration", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef());
setReturns("DeleteWebSocketServerConfiguration", returns);
params.clear(); returns.clear();
setDescription("SetWebServerConfiguration", "Configure a WebServer interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added.");
params.insert("configuration", JsonTypes::webServerConfigurationRef());
setParams("SetWebServerConfiguration", params); setParams("SetWebServerConfiguration", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef()); returns.insert("configurationError", JsonTypes::configurationErrorRef());
setReturns("SetWebServerConfiguration", returns); setReturns("SetWebServerConfiguration", returns);
params.clear(); returns.clear();
setDescription("DeleteWebServerConfiguration", "Delete a WebServer interface of the server.");
params.insert("id", JsonTypes::basicTypeToString(QVariant::String));
setParams("DeleteWebServerConfiguration", params);
returns.insert("configurationError", JsonTypes::configurationErrorRef());
setReturns("DeleteWebServerConfiguration", returns);
// Notifications // Notifications
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("BasicConfigurationChanged", "Emitted whenever the basic configuration of this server changes."); setDescription("BasicConfigurationChanged", "Emitted whenever the basic configuration of this server changes.");
@ -215,13 +227,13 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap &params) co
webServerConfigs.append(JsonTypes::packWebServerConfiguration(config)); webServerConfigs.append(JsonTypes::packWebServerConfiguration(config));
} }
returns.insert("webServerConfigurations", tcpServerConfigs); returns.insert("webServerConfigurations", webServerConfigs);
QVariantList webSocketServerConfigs; QVariantList webSocketServerConfigs;
foreach (const ServerConfiguration &config, GuhCore::instance()->configuration()->webSocketServerConfigurations()) { foreach (const ServerConfiguration &config, GuhCore::instance()->configuration()->webSocketServerConfigurations()) {
tcpServerConfigs.append(JsonTypes::packServerConfiguration(config)); webSocketServerConfigs.append(JsonTypes::packServerConfiguration(config));
} }
returns.insert("webServerConfigurations", tcpServerConfigs); returns.insert("webSocketServerConfigurations", webSocketServerConfigs);
return createReply(returns); return createReply(returns);
} }
@ -282,7 +294,10 @@ JsonReply *ConfigurationHandler::SetLanguage(const QVariantMap &params) const
JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &params) const
{ {
ServerConfiguration config = JsonTypes::unpackServerConfiguration(params); ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) {
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidId));
}
if (config.address.isNull()) if (config.address.isNull())
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress)); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress));
@ -300,10 +315,24 @@ JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &pa
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
} }
JsonReply *ConfigurationHandler::DeleteTcpServerConfiguration(const QVariantMap &params) const
{
QString id = params.value("id").toString();
if (id.isEmpty() || !GuhCore::instance()->configuration()->tcpServerConfigurations().contains(id)) {
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidId));
}
GuhCore::instance()->configuration()->removeTcpServerConfiguration(id);
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
}
JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &params) const
{ {
WebServerConfiguration config = JsonTypes::unpackWebServerConfiguration(params); qWarning() << params;
WebServerConfiguration config = JsonTypes::unpackWebServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) {
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidId));
}
if (config.address.isNull()) if (config.address.isNull())
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress)); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress));
@ -320,9 +349,22 @@ JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &pa
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
} }
JsonReply *ConfigurationHandler::DeleteWebServerConfiguration(const QVariantMap &params) const
{
QString id = params.value("id").toString();
if (id.isEmpty() || !GuhCore::instance()->configuration()->webServerConfigurations().contains(id)) {
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidId));
}
GuhCore::instance()->configuration()->removeWebServerConfiguration(id);
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
}
JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap &params) const
{ {
ServerConfiguration config = JsonTypes::unpackServerConfiguration(params); ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) {
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidId));
}
if (config.address.isNull()) if (config.address.isNull())
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress)); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidHostAddress));
@ -334,11 +376,20 @@ JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantM
qCDebug(dcJsonRpc()) << QString("Configure web socket server %1:%2").arg(config.address.toString()).arg(config.port); qCDebug(dcJsonRpc()) << QString("Configure web socket server %1:%2").arg(config.address.toString()).arg(config.port);
GuhCore::instance()->configuration()->setWebSocketServerConfiguration(config); GuhCore::instance()->configuration()->setWebSocketServerConfiguration(config);
// GuhCore::instance()->webSocketServer()->reconfigureServer(config);
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
} }
JsonReply *ConfigurationHandler::DeleteWebSocketServerConfiguration(const QVariantMap &params) const
{
QString id = params.value("id").toString();
if (id.isEmpty() || !GuhCore::instance()->configuration()->webSocketServerConfigurations().contains(id)) {
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorInvalidId));
}
GuhCore::instance()->configuration()->removeWebSocketServerConfiguration(id);
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
}
void ConfigurationHandler::onBasicConfigurationChanged() void ConfigurationHandler::onBasicConfigurationChanged()
{ {
QVariantMap params; QVariantMap params;

View File

@ -42,8 +42,11 @@ public:
Q_INVOKABLE JsonReply *SetTimeZone(const QVariantMap &params) const; Q_INVOKABLE JsonReply *SetTimeZone(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetLanguage(const QVariantMap &params) const; Q_INVOKABLE JsonReply *SetLanguage(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetTcpServerConfiguration(const QVariantMap &params) const; Q_INVOKABLE JsonReply *SetTcpServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *DeleteTcpServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetWebServerConfiguration(const QVariantMap &params) const; Q_INVOKABLE JsonReply *SetWebServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *DeleteWebServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetWebSocketServerConfiguration(const QVariantMap &params) const; Q_INVOKABLE JsonReply *SetWebSocketServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *DeleteWebSocketServerConfiguration(const QVariantMap &params) const;
signals: signals:
void BasicConfigurationChanged(const QVariantMap &params); void BasicConfigurationChanged(const QVariantMap &params);

View File

@ -237,18 +237,23 @@ QHash<QString, JsonHandler *> JsonRPCServer::handlers() const
return m_handlers; return m_handlers;
} }
/*! Register a new \l{TransportInterface} to the JSON server. The \a enabled flag indivates if the given \a interface sould be enebeld on startup. */ /*! Register a new \l{TransportInterface} to the JSON server. If the given interface is already registered, just the authenticationRequired flag will be updated. */
void JsonRPCServer::registerTransportInterface(TransportInterface *interface, bool enabled, bool authenticationRequired) void JsonRPCServer::registerTransportInterface(TransportInterface *interface, bool authenticationRequired)
{ {
connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); if (!m_interfaces.contains(interface)) {
connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected);
connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected);
connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData);
m_interfaces.insert(interface, authenticationRequired);
if (enabled) {
QMetaObject::invokeMethod(interface, "startServer", Qt::QueuedConnection);
} }
m_interfaces[interface] = authenticationRequired;
}
void JsonRPCServer::unregisterTransportInterface(TransportInterface *interface)
{
disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected);
disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected);
disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData);
m_interfaces.take(interface);
} }
/*! Send a JSON success response to the client with the given \a clientId, /*! Send a JSON success response to the client with the given \a clientId,
@ -454,7 +459,8 @@ void JsonRPCServer::clientConnected(const QUuid &clientId)
handshake.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString()); handshake.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString());
handshake.insert("language", GuhCore::instance()->configuration()->locale().name()); handshake.insert("language", GuhCore::instance()->configuration()->locale().name());
handshake.insert("protocol version", JSON_PROTOCOL_VERSION); handshake.insert("protocol version", JSON_PROTOCOL_VERSION);
handshake.insert("initialSetupRequired", GuhCore::instance()->userManager()->users().isEmpty()); handshake.insert("initialSetupRequired", (interface->configuration().authenticationEnabled ? GuhCore::instance()->userManager()->users().isEmpty() : false));
handshake.insert("authenticationRequired", interface->configuration().authenticationEnabled);
interface->sendData(clientId, QJsonDocument::fromVariant(handshake).toJson()); interface->sendData(clientId, QJsonDocument::fromVariant(handshake).toJson());
} }

View File

@ -58,7 +58,8 @@ public:
QHash<QString, JsonHandler *> handlers() const; QHash<QString, JsonHandler *> handlers() const;
void registerTransportInterface(TransportInterface *interface, bool enabled, bool authenticationRequired); void registerTransportInterface(TransportInterface *interface, bool authenticationRequired);
void unregisterTransportInterface(TransportInterface *interface);
private: private:
void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap &params = QVariantMap()); void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap &params = QVariantMap());

View File

@ -119,6 +119,8 @@ QVariantMap JsonTypes::s_wirelessAccessPoint;
QVariantMap JsonTypes::s_wiredNetworkDevice; QVariantMap JsonTypes::s_wiredNetworkDevice;
QVariantMap JsonTypes::s_wirelessNetworkDevice; QVariantMap JsonTypes::s_wirelessNetworkDevice;
QVariantMap JsonTypes::s_tokenInfo; QVariantMap JsonTypes::s_tokenInfo;
QVariantMap JsonTypes::s_serverConfiguration;
QVariantMap JsonTypes::s_webServerConfiguration;
void JsonTypes::init() void JsonTypes::init()
{ {
@ -359,6 +361,16 @@ void JsonTypes::init()
s_tokenInfo.insert("deviceName", basicTypeToString(QVariant::String)); s_tokenInfo.insert("deviceName", basicTypeToString(QVariant::String));
s_tokenInfo.insert("creationTime", basicTypeToString(QVariant::UInt)); s_tokenInfo.insert("creationTime", basicTypeToString(QVariant::UInt));
// ServerConfiguration
s_serverConfiguration.insert("id", basicTypeToString(QVariant::String));
s_serverConfiguration.insert("address", basicTypeToString(QVariant::String));
s_serverConfiguration.insert("port", basicTypeToString(QVariant::UInt));
s_serverConfiguration.insert("sslEnabled", basicTypeToString(QVariant::Bool));
s_serverConfiguration.insert("authenticationEnabled", basicTypeToString(QVariant::Bool));
s_webServerConfiguration = s_serverConfiguration;
s_webServerConfiguration.insert("publicFolder", basicTypeToString(QVariant::String));
s_initialized = true; s_initialized = true;
} }
@ -437,6 +449,7 @@ QVariantMap JsonTypes::allTypes()
allTypes.insert("WiredNetworkDevice", wiredNetworkDeviceDescription()); allTypes.insert("WiredNetworkDevice", wiredNetworkDeviceDescription());
allTypes.insert("WirelessNetworkDevice", wirelessNetworkDeviceDescription()); allTypes.insert("WirelessNetworkDevice", wirelessNetworkDeviceDescription());
allTypes.insert("TokenInfo", tokenInfoDescription()); allTypes.insert("TokenInfo", tokenInfoDescription());
allTypes.insert("ServerConfiguration", serverConfigurationDescription());
return allTypes; return allTypes;
} }
@ -1091,7 +1104,8 @@ QVariantMap JsonTypes::packBasicConfiguration()
QVariantMap JsonTypes::packServerConfiguration(const ServerConfiguration &config) QVariantMap JsonTypes::packServerConfiguration(const ServerConfiguration &config)
{ {
QVariantMap serverConfiguration; QVariantMap serverConfiguration;
serverConfiguration.insert("host", config.address.toString()); serverConfiguration.insert("id", config.id);
serverConfiguration.insert("address", config.address.toString());
serverConfiguration.insert("port", config.port); serverConfiguration.insert("port", config.port);
serverConfiguration.insert("sslEnabled", config.sslEnabled); serverConfiguration.insert("sslEnabled", config.sslEnabled);
serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled); serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled);
@ -1834,6 +1848,18 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qCWarning(dcJsonRpc) << "TokenInfo not matching"; qCWarning(dcJsonRpc) << "TokenInfo not matching";
return result; return result;
} }
} else if (refName == serverConfigurationRef()) {
QPair<bool, QString> result = validateMap(serverConfigurationDescription(), variant.toMap());
if (!result.first) {
qCWarning(dcJsonRpc) << "ServerConfiguration not matching";
return result;
}
} else if (refName == webServerConfigurationRef()) {
QPair<bool, QString> result = validateMap(webServerConfigurationDescription(), variant.toMap());
if (!result.first) {
qCWarning(dcJsonRpc) << "WebServerConfiguration not matching";
return result;
}
} else if (refName == basicTypeRef()) { } else if (refName == basicTypeRef()) {
QPair<bool, QString> result = validateBasicType(variant); QPair<bool, QString> result = validateBasicType(variant);
if (!result.first) { if (!result.first) {

View File

@ -166,6 +166,8 @@ public:
DECLARE_OBJECT(wiredNetworkDevice, "WiredNetworkDevice") DECLARE_OBJECT(wiredNetworkDevice, "WiredNetworkDevice")
DECLARE_OBJECT(wirelessNetworkDevice, "WirelessNetworkDevice") DECLARE_OBJECT(wirelessNetworkDevice, "WirelessNetworkDevice")
DECLARE_OBJECT(tokenInfo, "TokenInfo") DECLARE_OBJECT(tokenInfo, "TokenInfo")
DECLARE_OBJECT(serverConfiguration, "ServerConfiguration")
DECLARE_OBJECT(webServerConfiguration, "WebServerConfiguration")
// pack types // pack types
static QVariantMap packEventType(const EventType &eventType); static QVariantMap packEventType(const EventType &eventType);

View File

@ -94,27 +94,43 @@ ServerManager::ServerManager(GuhConfiguration* configuration, QObject *parent) :
// Transports // Transports
#ifdef TESTING_ENABLED #ifdef TESTING_ENABLED
MockTcpServer *tcpServer = new MockTcpServer(this); MockTcpServer *tcpServer = new MockTcpServer(this);
m_jsonServer->registerTransportInterface(tcpServer, true, true); m_jsonServer->registerTransportInterface(tcpServer, true);
tcpServer->startServer();
#else #else
foreach (const ServerConfiguration &config, configuration->tcpServerConfigurations()) { foreach (const ServerConfiguration &config, configuration->tcpServerConfigurations()) {
TcpServer *tcpServer = new TcpServer(config.address, config.port, config.sslEnabled, m_sslConfiguration, this); TcpServer *tcpServer = new TcpServer(config, m_sslConfiguration, this);
m_jsonServer->registerTransportInterface(tcpServer, true, config.authenticationEnabled); m_jsonServer->registerTransportInterface(tcpServer, config.authenticationEnabled);
m_tcpServers.insert(config.id, tcpServer);
tcpServer->startServer();
} }
#endif #endif
foreach (const ServerConfiguration &config, configuration->webSocketServerConfigurations()) { foreach (const ServerConfiguration &config, configuration->webSocketServerConfigurations()) {
qWarning() << "Have websockeserver config" << config.id; qWarning() << "Have websockeserver config" << config.id;
WebSocketServer *webSocketServer = new WebSocketServer(config.address, config.port, config.sslEnabled, m_sslConfiguration, this); WebSocketServer *webSocketServer = new WebSocketServer(config, m_sslConfiguration, this);
m_jsonServer->registerTransportInterface(webSocketServer, true, config.authenticationEnabled); m_jsonServer->registerTransportInterface(webSocketServer, config.authenticationEnabled);
m_webSocketServers.insert(config.id, webSocketServer);
webSocketServer->startServer();
} }
m_bluetoothServer = new BluetoothServer(this); m_bluetoothServer = new BluetoothServer(this);
m_jsonServer->registerTransportInterface(m_bluetoothServer, configuration->bluetoothServerEnabled(), true); m_jsonServer->registerTransportInterface(m_bluetoothServer, true);
if (configuration->bluetoothServerEnabled()) {
m_bluetoothServer->startServer();
}
foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) { foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) {
WebServer *webServer = new WebServer(config.address, config.port, config.publicFolder, config.sslEnabled, m_sslConfiguration, this); WebServer *webServer = new WebServer(config, m_sslConfiguration, this);
m_restServer->registerWebserver(webServer); m_restServer->registerWebserver(webServer);
m_webServers.insert(config.id, webServer);
} }
connect(configuration, &GuhConfiguration::tcpServerConfigurationChanged, this, &ServerManager::tcpServerConfigurationChanged);
connect(configuration, &GuhConfiguration::tcpServerConfigurationRemoved, this, &ServerManager::tcpServerConfigurationRemoved);
connect(configuration, &GuhConfiguration::webSocketServerConfigurationChanged, this, &ServerManager::webSocketServerConfigurationChanged);
connect(configuration, &GuhConfiguration::webSocketServerConfigurationRemoved, this, &ServerManager::webSocketServerConfigurationRemoved);
connect(configuration, &GuhConfiguration::webServerConfigurationChanged, this, &ServerManager::webServerConfigurationChanged);
connect(configuration, &GuhConfiguration::webServerConfigurationRemoved, this, &ServerManager::webServerConfigurationRemoved);
} }
/*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */ /*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */
@ -134,6 +150,99 @@ BluetoothServer *ServerManager::bluetoothServer() const
return m_bluetoothServer; return m_bluetoothServer;
} }
void ServerManager::tcpServerConfigurationChanged(const QString &id)
{
#ifndef TESTING_ENABLED
ServerConfiguration config = GuhCore::instance()->configuration()->tcpServerConfigurations().value(id);
TcpServer *server = m_tcpServers.value(id);
if (server) {
qDebug(dcConnection) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcConnection) << "Received a TCP Server config change event but don't have a TCP Server instance for it. Creating new Server instance.";
server = new TcpServer(config, m_sslConfiguration, this);
m_tcpServers.insert(config.id, server);
}
m_jsonServer->registerTransportInterface(server, config.authenticationEnabled);
server->startServer();
#else
qWarning() << "Configure called for" << id << "but disabled in testing";
#endif
}
void ServerManager::tcpServerConfigurationRemoved(const QString &id)
{
#ifndef TESTING_ENABLED
if (!m_tcpServers.contains(id)) {
qWarning(dcConnection) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
return;
}
TcpServer *server = m_tcpServers.take(id);
m_jsonServer->unregisterTransportInterface(server);
server->stopServer();
server->deleteLater();
#else
qWarning() << "Delete configuration called for" << id << "but disabled in testing";
#endif
}
void ServerManager::webSocketServerConfigurationChanged(const QString &id)
{
WebSocketServer *server = m_webSocketServers.value(id);
ServerConfiguration config = GuhCore::instance()->configuration()->webSocketServerConfigurations().value(id);
if (server) {
qDebug(dcConnection) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcConnection) << "Received a WebSocket Server config change event but don't have a WebSocket Server instance for it. Creating new instance.";
server = new WebSocketServer(config, m_sslConfiguration, this);
m_webSocketServers.insert(server->configuration().id, server);
}
m_jsonServer->registerTransportInterface(server, config.authenticationEnabled);
server->startServer();
}
void ServerManager::webSocketServerConfigurationRemoved(const QString &id)
{
if (!m_webSocketServers.contains(id)) {
qWarning(dcConnection) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
return;
}
WebSocketServer *server = m_webSocketServers.take(id);
m_jsonServer->unregisterTransportInterface(server);
server->stopServer();
server->deleteLater();
}
void ServerManager::webServerConfigurationChanged(const QString &id)
{
WebServerConfiguration config = GuhCore::instance()->configuration()->webServerConfigurations().value(id);
WebServer *server = m_webServers.value(id);
if (server) {
qDebug(dcConnection) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
server->stopServer();
server->reconfigureServer(config);
} else {
qDebug(dcConnection) << "Received a Web Server config change event but don't have a Web Server instance for it.";
server = new WebServer(config, m_sslConfiguration, this);
m_webServers.insert(config.id, server);
}
server->startServer();
}
void ServerManager::webServerConfigurationRemoved(const QString &id)
{
if (!m_webServers.contains(id)) {
qWarning(dcConnection) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
return;
}
WebServer *server = m_webServers.take(id);
server->stopServer();
server->deleteLater();
}
bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName) bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName)
{ {
QFile certificateKeyFile(certificateKeyFileName); QFile certificateKeyFile(certificateKeyFileName);

View File

@ -62,12 +62,25 @@ public:
TcpServer *tcpServer() const; TcpServer *tcpServer() const;
#endif #endif
private slots:
void tcpServerConfigurationChanged(const QString &id);
void tcpServerConfigurationRemoved(const QString &id);
void webSocketServerConfigurationChanged(const QString &id);
void webSocketServerConfigurationRemoved(const QString &id);
void webServerConfigurationChanged(const QString &id);
void webServerConfigurationRemoved(const QString &id);
private: private:
// Interfaces // Interfaces
JsonRPCServer *m_jsonServer; JsonRPCServer *m_jsonServer;
RestServer *m_restServer; RestServer *m_restServer;
BluetoothServer *m_bluetoothServer; BluetoothServer *m_bluetoothServer;
#ifndef TESTING_ENABLED
QHash<QString, TcpServer*> m_tcpServers;
#endif
QHash<QString, WebSocketServer*> m_webSocketServers;
QHash<QString, WebServer*> m_webServers;
// Encrytption and stuff // Encrytption and stuff
QSslConfiguration m_sslConfiguration; QSslConfiguration m_sslConfiguration;

View File

@ -45,14 +45,12 @@ namespace guhserver {
* *
* \sa ServerManager * \sa ServerManager
*/ */
TcpServer::TcpServer(const QHostAddress &host, const uint &port, bool sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent) : TcpServer::TcpServer(const ServerConfiguration &configuration, const QSslConfiguration &sslConfiguration, QObject *parent) :
TransportInterface(parent), TransportInterface(configuration, parent),
m_server(NULL), m_server(NULL),
m_host(host),
m_port(port),
m_sslEnabled(sslEnabled),
m_sslConfig(sslConfiguration) m_sslConfig(sslConfiguration)
{ {
qWarning() << "****" << configuration.address << configuration.port;
#ifndef TESTING_ENABLED #ifndef TESTING_ENABLED
m_avahiService = new QtAvahiService(this); m_avahiService = new QtAvahiService(this);
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &TcpServer::onAvahiServiceStateChanged); connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &TcpServer::onAvahiServiceStateChanged);
@ -128,30 +126,18 @@ void TcpServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceS
/*! Returns true if this \l{TcpServer} could be reconfigured with the given \a address and \a port. */ /*! Returns true if this \l{TcpServer} could be reconfigured with the given \a address and \a port. */
bool TcpServer::reconfigureServer(const QHostAddress &address, const uint &port) void TcpServer::reconfigureServer(const ServerConfiguration &config)
{ {
if (m_host == address && m_port == (qint16)port && m_server->isListening()) if (configuration().address == config.address &&
return true; configuration().port == config.port &&
configuration().sslEnabled == config.sslEnabled &&
configuration().authenticationEnabled == config.authenticationEnabled &&
m_server->isListening())
return;
stopServer(); stopServer();
setConfiguration(config);
SslServer *server = new SslServer(m_sslEnabled, m_sslConfig); startServer();
if(!server->listen(address, port)) {
qCWarning(dcConnection) << "Tcp server error: can not listen on" << address.toString() << port;
delete server;
// Restart the server with the old configuration
qCDebug(dcTcpServer()) << "Restart server with old configuration.";
startServer();
return false;
}
// Remove the test server..
server->close();
delete server;
// Start server with new configuration
m_host = address;
m_port = port;
return startServer();
} }
/*! Returns true if this \l{TcpServer} started successfully. /*! Returns true if this \l{TcpServer} started successfully.
@ -160,9 +146,9 @@ bool TcpServer::reconfigureServer(const QHostAddress &address, const uint &port)
*/ */
bool TcpServer::startServer() bool TcpServer::startServer()
{ {
m_server = new SslServer(m_sslEnabled, m_sslConfig); m_server = new SslServer(configuration().sslEnabled, m_sslConfig);
if(!m_server->listen(m_host, m_port)) { if(!m_server->listen(configuration().address, configuration().port)) {
qCWarning(dcConnection) << "Tcp server error: can not listen on" << m_host.toString() << m_port; qCWarning(dcConnection) << "Tcp server error: can not listen on" << configuration().address.toString() << configuration().port;
delete m_server; delete m_server;
m_server = NULL; m_server = NULL;
return false; return false;
@ -177,7 +163,7 @@ bool TcpServer::startServer()
txt.insert("manufacturer", "guh GmbH"); txt.insert("manufacturer", "guh GmbH");
txt.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString()); txt.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString());
txt.insert("name", GuhCore::instance()->configuration()->serverName()); txt.insert("name", GuhCore::instance()->configuration()->serverName());
m_avahiService->registerService("guhIO", m_port, "_jsonrpc._tcp", txt); m_avahiService->registerService("guhIO", configuration().port, "_jsonrpc._tcp", txt);
#endif #endif
qCDebug(dcConnection) << "Started Tcp server on" << m_server->serverAddress().toString() << m_server->serverPort(); qCDebug(dcConnection) << "Started Tcp server on" << m_server->serverAddress().toString() << m_server->serverPort();

View File

@ -71,7 +71,7 @@ class TcpServer : public TransportInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TcpServer(const QHostAddress &host, const uint &port, bool sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent = 0); explicit TcpServer(const ServerConfiguration &configuration, const QSslConfiguration &sslConfiguration, QObject *parent = 0);
~TcpServer(); ~TcpServer();
void sendData(const QUuid &clientId, const QByteArray &data) override; void sendData(const QUuid &clientId, const QByteArray &data) override;
@ -85,10 +85,6 @@ private:
SslServer * m_server; SslServer * m_server;
QHash<QUuid, QTcpSocket *> m_clientList; QHash<QUuid, QTcpSocket *> m_clientList;
QHostAddress m_host;
qint16 m_port;
bool m_sslEnabled = false;
QSslConfiguration m_sslConfig; QSslConfiguration m_sslConfig;
private slots: private slots:
@ -102,7 +98,7 @@ private slots:
public slots: public slots:
bool reconfigureServer(const QHostAddress &address, const uint &port); void reconfigureServer(const ServerConfiguration &configuration);
bool startServer() override; bool startServer() override;
bool stopServer() override; bool stopServer() override;
}; };

View File

@ -78,12 +78,24 @@
namespace guhserver { namespace guhserver {
/*! Constructs a \l{TransportInterface} with the given \a parent. */ /*! Constructs a \l{TransportInterface} with the given \a parent. */
TransportInterface::TransportInterface(QObject *parent) : TransportInterface::TransportInterface(const ServerConfiguration &config, QObject *parent) :
QObject(parent) QObject(parent),
m_config(config)
{ {
} }
/*! Pure virtual destructor for \l{TransportInterface}. */ void TransportInterface::setConfiguration(const ServerConfiguration &config)
{
m_config = config;
}
/*! Returns the \{ServerConfiguration}. */
ServerConfiguration TransportInterface::configuration() const
{
return m_config;
}
/*! Virtual destructor for \l{TransportInterface}. */
TransportInterface::~TransportInterface() TransportInterface::~TransportInterface()
{ {
} }

View File

@ -26,18 +26,23 @@
#include <QList> #include <QList>
#include <QUuid> #include <QUuid>
#include "guhconfiguration.h"
namespace guhserver { namespace guhserver {
class TransportInterface : public QObject class TransportInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TransportInterface(QObject *parent = 0); explicit TransportInterface(const ServerConfiguration &config, QObject *parent = 0);
virtual ~TransportInterface() = 0; virtual ~TransportInterface() = 0;
virtual void sendData(const QUuid &clientId, const QByteArray &data) = 0; virtual void sendData(const QUuid &clientId, const QByteArray &data) = 0;
virtual void sendData(const QList<QUuid> &clients, const QByteArray &data) = 0; virtual void sendData(const QList<QUuid> &clients, const QByteArray &data) = 0;
void setConfiguration(const ServerConfiguration &config);
ServerConfiguration configuration() const;
signals: signals:
void clientConnected(const QUuid &clientId); void clientConnected(const QUuid &clientId);
void clientDisconnected(const QUuid &clientId); void clientDisconnected(const QUuid &clientId);
@ -46,6 +51,9 @@ signals:
public slots: public slots:
virtual bool startServer() = 0; virtual bool startServer() = 0;
virtual bool stopServer() = 0; virtual bool stopServer() = 0;
private:
ServerConfiguration m_config;
}; };
} }

View File

@ -95,20 +95,18 @@ namespace guhserver {
* *
* \sa ServerManager * \sa ServerManager
*/ */
WebServer::WebServer(const QHostAddress &host, const uint &port, const QString &publicFolder, bool sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent) : WebServer::WebServer(const WebServerConfiguration &configuration, const QSslConfiguration &sslConfiguration, QObject *parent) :
QTcpServer(parent), QTcpServer(parent),
m_avahiService(NULL), m_avahiService(NULL),
m_host(host), m_configuration(configuration),
m_port(port),
m_webinterfaceDir(publicFolder),
m_sslConfiguration(sslConfiguration), m_sslConfiguration(sslConfiguration),
m_useSsl(sslEnabled),
m_enabled(false) m_enabled(false)
{ {
if (QCoreApplication::instance()->organizationName() == "guh-test") { if (QCoreApplication::instance()->organizationName() == "guh-test") {
m_webinterfaceDir = QDir(QCoreApplication::applicationDirPath()); m_configuration.publicFolder = QCoreApplication::applicationDirPath();
qCWarning(dcWebServer) << "Using public folder" << m_webinterfaceDir.path(); qCWarning(dcWebServer) << "Using public folder" << m_configuration.publicFolder;
} }
qCDebug(dcWebServer) << "Using public folder" << m_configuration.publicFolder;
#ifndef TESTING_ENABLED #ifndef TESTING_ENABLED
m_avahiService = new QtAvahiService(this); m_avahiService = new QtAvahiService(this);
@ -158,7 +156,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
} }
// make shore the file is in the public directory // make shore the file is in the public directory
if (!file.canonicalFilePath().startsWith(m_webinterfaceDir.path())) { if (!file.canonicalFilePath().startsWith(m_configuration.publicFolder)) {
qCWarning(dcWebServer) << "requested file" << file.fileName() << "is outside the public folder."; qCWarning(dcWebServer) << "requested file" << file.fileName() << "is outside the public folder.";
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
reply->setClientId(m_clientList.key(socket)); reply->setClientId(m_clientList.key(socket));
@ -189,7 +187,7 @@ QString WebServer::fileName(const QString &query)
fileName = query; fileName = query;
} }
return m_webinterfaceDir.path() + fileName; return m_configuration.publicFolder + "/" + fileName;
} }
HttpReply *WebServer::processIconRequest(const QString &fileName) HttpReply *WebServer::processIconRequest(const QString &fileName)
@ -255,7 +253,7 @@ void WebServer::incomingConnection(qintptr socketDescriptor)
qCDebug(dcConnection) << QString("Webserver client %1:%2 connected").arg(socket->peerAddress().toString()).arg(socket->peerPort()); qCDebug(dcConnection) << QString("Webserver client %1:%2 connected").arg(socket->peerAddress().toString()).arg(socket->peerPort());
if (m_useSsl) { if (m_configuration.sslEnabled) {
// configure client connection // configure client connection
socket->setSslConfiguration(m_sslConfiguration); socket->setSslConfiguration(m_sslConfiguration);
connect(socket, SIGNAL(encrypted()), this, SLOT(onEncrypted())); connect(socket, SIGNAL(encrypted()), this, SLOT(onEncrypted()));
@ -365,7 +363,7 @@ void WebServer::readClient()
qCDebug(dcWebServer) << "server XML request call"; qCDebug(dcWebServer) << "server XML request call";
HttpReply *reply = RestResource::createSuccessReply(); HttpReply *reply = RestResource::createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "text/xml"); reply->setHeader(HttpReply::ContentTypeHeader, "text/xml");
reply->setPayload(createServerXmlDocument(m_host)); reply->setPayload(createServerXmlDocument(m_configuration.address));
reply->setClientId(clientId); reply->setClientId(clientId);
sendHttpReply(reply); sendHttpReply(reply);
reply->deleteLater(); reply->deleteLater();
@ -376,8 +374,8 @@ void WebServer::readClient()
// request for a file... // request for a file...
if (request.method() == HttpRequest::Get) { if (request.method() == HttpRequest::Get) {
// check if the webinterface dir does exist, otherwise a filerequest is not relevant // check if the webinterface dir does exist, otherwise a filerequest is not relevant
if (!m_webinterfaceDir.exists()) { if (!QDir(m_configuration.publicFolder).exists()) {
qCWarning(dcWebServer) << "webinterface folder" << m_webinterfaceDir.path() << "does not exist."; qCWarning(dcWebServer) << "webinterface folder" << m_configuration.publicFolder << "does not exist.";
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
reply->setClientId(clientId); reply->setClientId(clientId);
sendHttpReply(reply); sendHttpReply(reply);
@ -489,41 +487,34 @@ void WebServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceS
} }
/*! Returns true if this \l{WebServer} could be reconfigured with the given \a address and \a port. */ /*! Returns true if this \l{WebServer} could be reconfigured with the given \a address and \a port. */
bool WebServer::reconfigureServer(const QHostAddress &address, const uint &port) void WebServer::reconfigureServer(const WebServerConfiguration &config)
{ {
if (m_host == address && m_port == (qint16)port && isListening()) if (m_configuration.address == config.address &&
return true; m_configuration.port == config.port &&
m_configuration.sslEnabled == config.sslEnabled &&
m_configuration.authenticationEnabled == config.authenticationEnabled &&
m_configuration.publicFolder == config.publicFolder &&
isListening())
return;
stopServer(); stopServer();
m_configuration = config;
if (!listen(address, port)) {
qCWarning(dcConnection()) << "Webserver could not listen on" << serverAddress().toString() << m_port;
qCDebug(dcWebServer()) << "Restart server with old configuration.";
startServer();
return false;
}
close();
m_host = address;
m_port = port;
startServer(); startServer();
return true;
} }
/*! Returns true if this \l{WebServer} started successfully. */ /*! Returns true if this \l{WebServer} started successfully. */
bool WebServer::startServer() bool WebServer::startServer()
{ {
if (!listen(m_host, m_port)) { if (!listen(m_configuration.address, m_configuration.port)) {
qCWarning(dcConnection) << "Webserver could not listen on" << serverAddress().toString() << m_port; qCWarning(dcConnection) << "Webserver could not listen on" << m_configuration.address.toString() << m_configuration.port;
m_enabled = false; m_enabled = false;
return false; return false;
} }
if (m_useSsl) { if (m_configuration.sslEnabled) {
qCDebug(dcConnection) << "Started webserver on" << QString("https://%1:%2").arg(m_host.toString()).arg(m_port); qCDebug(dcConnection) << "Started webserver on" << QString("https://%1:%2").arg(m_configuration.address.toString()).arg(m_configuration.port);
} else { } else {
qCDebug(dcConnection) << "Started webserver on" << QString("http://%1:%2").arg(m_host.toString()).arg(m_port); qCDebug(dcConnection) << "Started webserver on" << QString("http://%1:%2").arg(m_configuration.address.toString()).arg(m_configuration.port);
} }
#ifndef TESTING_ENABLED #ifndef TESTING_ENABLED
@ -534,7 +525,7 @@ bool WebServer::startServer()
txt.insert("manufacturer", "guh GmbH"); txt.insert("manufacturer", "guh GmbH");
txt.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString()); txt.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString());
txt.insert("name", GuhCore::instance()->configuration()->serverName()); txt.insert("name", GuhCore::instance()->configuration()->serverName());
m_avahiService->registerService("guhIO", m_port, "_http._tcp", txt); m_avahiService->registerService("guhIO", m_configuration.port, "_http._tcp", txt);
#endif #endif
m_enabled = true; m_enabled = true;
@ -580,13 +571,13 @@ QByteArray WebServer::createServerXmlDocument(QHostAddress address)
writer.writeTextElement("minor", "1"); writer.writeTextElement("minor", "1");
writer.writeEndElement(); // specVersion writer.writeEndElement(); // specVersion
if (m_useSsl) { if (m_configuration.sslEnabled) {
writer.writeTextElement("URLBase", "https://" + address.toString() + ":" + QString::number(m_port)); writer.writeTextElement("URLBase", "https://" + address.toString() + ":" + QString::number(m_configuration.port));
} else { } else {
writer.writeTextElement("URLBase", "http://" + address.toString() + ":" + QString::number(m_port)); writer.writeTextElement("URLBase", "http://" + address.toString() + ":" + QString::number(m_configuration.port));
} }
if (m_useSsl) { if (m_configuration.sslEnabled) {
writer.writeTextElement("websocketURL", "wss://" + address.toString() + ":" + QString::number(websocketPort)); writer.writeTextElement("websocketURL", "wss://" + address.toString() + ":" + QString::number(websocketPort));
} else { } else {
writer.writeTextElement("websocketURL", "ws://" + address.toString() + ":" + QString::number(websocketPort)); writer.writeTextElement("websocketURL", "ws://" + address.toString() + ":" + QString::number(websocketPort));

View File

@ -36,6 +36,8 @@
#include "network/avahi/qtavahiservice.h" #include "network/avahi/qtavahiservice.h"
#include "guhconfiguration.h"
// Note: Hypertext Transfer Protocol (HTTP/1.1) from the Internet Engineering Task Force (IETF): // Note: Hypertext Transfer Protocol (HTTP/1.1) from the Internet Engineering Task Force (IETF):
// https://tools.ietf.org/html/rfc7231 // https://tools.ietf.org/html/rfc7231
@ -72,7 +74,7 @@ class WebServer : public QTcpServer
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WebServer(const QHostAddress &host, const uint &port, const QString &publicFolder, bool sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent = 0); explicit WebServer(const WebServerConfiguration &configuration, const QSslConfiguration &sslConfiguration, QObject *parent = 0);
~WebServer(); ~WebServer();
void sendHttpReply(HttpReply *reply); void sendHttpReply(HttpReply *reply);
@ -84,12 +86,9 @@ private:
QtAvahiService *m_avahiService; QtAvahiService *m_avahiService;
QHostAddress m_host;
qint16 m_port;
QDir m_webinterfaceDir;
WebServerConfiguration m_configuration;
QSslConfiguration m_sslConfiguration; QSslConfiguration m_sslConfiguration;
bool m_useSsl;
bool m_enabled; bool m_enabled;
@ -116,7 +115,7 @@ private slots:
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state); void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
public slots: public slots:
bool reconfigureServer(const QHostAddress &address, const uint &port); void reconfigureServer(const WebServerConfiguration &config);
bool startServer(); bool startServer();
bool stopServer(); bool stopServer();

View File

@ -60,13 +60,10 @@ namespace guhserver {
* *
* \sa ServerManager * \sa ServerManager
*/ */
WebSocketServer::WebSocketServer(const QHostAddress &address, const uint &port, const bool &sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent) : WebSocketServer::WebSocketServer(const ServerConfiguration &configuration, const QSslConfiguration &sslConfiguration, QObject *parent) :
TransportInterface(parent), TransportInterface(configuration, parent),
m_server(0), m_server(0),
m_host(address),
m_port(port),
m_sslConfiguration(sslConfiguration), m_sslConfiguration(sslConfiguration),
m_useSsl(sslEnabled),
m_enabled(false) m_enabled(false)
{ {
#ifndef TESTING_ENABLED #ifndef TESTING_ENABLED
@ -180,41 +177,21 @@ void WebSocketServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiSe
} }
/*! Returns true if this \l{WebSocketServer} could be reconfigured with the given \a address and \a port. */ /*! Returns true if this \l{WebSocketServer} could be reconfigured with the given \a address and \a port. */
bool WebSocketServer::reconfigureServer(const QHostAddress &address, const uint &port) void WebSocketServer::reconfigureServer(const ServerConfiguration &config)
{ {
if (m_host == address && m_port == (qint16)port && m_server->isListening()) { if (configuration() == config && m_server->isListening()) {
qCDebug(dcWebSocketServer()) << "Configuration unchanged. Not restarting the server."; qCDebug(dcWebSocketServer()) << "Configuration unchanged. Not restarting the server.";
return true; return;
} }
stopServer(); stopServer();
qCDebug(dcWebSocketServer()) << "Stopped server for reconfiguration."; qCDebug(dcWebSocketServer()) << "Stopped server for reconfiguration.";
QWebSocketServer *server; setConfiguration(config);
if (m_useSsl) {
server = new QWebSocketServer("guh", QWebSocketServer::SecureMode, this);
server->setSslConfiguration(m_sslConfiguration);
} else {
server = new QWebSocketServer("guh", QWebSocketServer::NonSecureMode, this);
}
if(!server->listen(address, port)) {
qCWarning(dcConnection) << "Websocket server error: can not listen on" << address.toString() << port;
delete server;
// Restart the server with the old configuration
qCDebug(dcWebSocketServer()) << "Restart server with old configuration.";
startServer();
return false;
}
// Remove the test server..
server->close();
delete server;
// Start server with new configuration // Start server with new configuration
m_host = address;
m_port = port;
qCDebug(dcWebSocketServer()) << "Restart server with new configuration."; qCDebug(dcWebSocketServer()) << "Restart server with new configuration.";
return startServer(); startServer();
} }
/*! Returns true if this \l{WebSocketServer} started successfully. /*! Returns true if this \l{WebSocketServer} started successfully.
@ -223,7 +200,7 @@ bool WebSocketServer::reconfigureServer(const QHostAddress &address, const uint
*/ */
bool WebSocketServer::startServer() bool WebSocketServer::startServer()
{ {
if (m_useSsl) { if (configuration().sslEnabled) {
m_server = new QWebSocketServer("guh", QWebSocketServer::SecureMode, this); m_server = new QWebSocketServer("guh", QWebSocketServer::SecureMode, this);
m_server->setSslConfiguration(m_sslConfiguration); m_server->setSslConfiguration(m_sslConfiguration);
} else { } else {
@ -232,15 +209,15 @@ bool WebSocketServer::startServer()
connect (m_server, &QWebSocketServer::newConnection, this, &WebSocketServer::onClientConnected); connect (m_server, &QWebSocketServer::newConnection, this, &WebSocketServer::onClientConnected);
connect (m_server, &QWebSocketServer::acceptError, this, &WebSocketServer::onServerError); connect (m_server, &QWebSocketServer::acceptError, this, &WebSocketServer::onServerError);
if (!m_server->listen(m_host, m_port)) { if (!m_server->listen(configuration().address, configuration().port)) {
qCWarning(dcConnection) << "Websocket server" << m_server->serverName() << QString("could not listen on %1:%2").arg(m_server->serverAddress().toString()).arg(m_port); qCWarning(dcConnection) << "Websocket server" << m_server->serverName() << QString("could not listen on %1:%2").arg(m_server->serverAddress().toString()).arg(configuration().port);
return false; return false;
} }
if (m_server->secureMode() == QWebSocketServer::NonSecureMode) { if (m_server->secureMode() == QWebSocketServer::NonSecureMode) {
qCDebug(dcConnection) << "Started websocket server" << m_server->serverName() << QString("on ws://%1:%2").arg(m_server->serverAddress().toString()).arg(m_port); qCDebug(dcConnection) << "Started websocket server" << m_server->serverName() << QString("on ws://%1:%2").arg(m_server->serverAddress().toString()).arg(configuration().port);
} else { } else {
qCDebug(dcConnection) << "Started websocket server" << m_server->serverName() << QString("on wss://%1:%2").arg(m_server->serverAddress().toString()).arg(m_port); qCDebug(dcConnection) << "Started websocket server" << m_server->serverName() << QString("on wss://%1:%2").arg(m_server->serverAddress().toString()).arg(configuration().port);
} }
#ifndef TESTING_ENABLED #ifndef TESTING_ENABLED
@ -251,7 +228,7 @@ bool WebSocketServer::startServer()
txt.insert("manufacturer", "guh GmbH"); txt.insert("manufacturer", "guh GmbH");
txt.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString()); txt.insert("uuid", GuhCore::instance()->configuration()->serverUuid().toString());
txt.insert("name", GuhCore::instance()->configuration()->serverName()); txt.insert("name", GuhCore::instance()->configuration()->serverName());
m_avahiService->registerService("guhIO", m_port, "_ws._tcp", txt); m_avahiService->registerService("guhIO", configuration().port, "_ws._tcp", txt);
#endif #endif
return true; return true;
@ -272,9 +249,11 @@ bool WebSocketServer::stopServer()
client->close(QWebSocketProtocol::CloseCodeNormal, "Stop server"); client->close(QWebSocketProtocol::CloseCodeNormal, "Stop server");
} }
m_server->close(); if (m_server) {
delete m_server; m_server->close();
m_server = 0; delete m_server;
m_server = nullptr;
}
return true; return true;
} }

View File

@ -42,7 +42,7 @@ class WebSocketServer : public TransportInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WebSocketServer(const QHostAddress &address, const uint &port, const bool &sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent = 0); explicit WebSocketServer(const ServerConfiguration &configuration, const QSslConfiguration &sslConfiguration, QObject *parent = 0);
~WebSocketServer(); ~WebSocketServer();
void sendData(const QUuid &clientId, const QByteArray &data) override; void sendData(const QUuid &clientId, const QByteArray &data) override;
@ -54,11 +54,7 @@ private:
QtAvahiService *m_avahiService; QtAvahiService *m_avahiService;
QHostAddress m_host;
qint16 m_port;
QSslConfiguration m_sslConfiguration; QSslConfiguration m_sslConfiguration;
bool m_useSsl;
bool m_enabled; bool m_enabled;
@ -74,7 +70,7 @@ private slots:
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state); void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
public slots: public slots:
bool reconfigureServer(const QHostAddress &address, const uint &port); void reconfigureServer(const ServerConfiguration &config);
bool startServer() override; bool startServer() override;
bool stopServer() override; bool stopServer() override;
}; };

View File

@ -1,4 +1,4 @@
49 50
{ {
"methods": { "methods": {
"Actions.ExecuteAction": { "Actions.ExecuteAction": {
@ -31,6 +31,33 @@
} }
} }
}, },
"Configuration.DeleteTcpServerConfiguration": {
"description": "Delete a TCP interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped.",
"params": {
"id": "String"
},
"returns": {
"configurationError": "$ref:ConfigurationError"
}
},
"Configuration.DeleteWebServerConfiguration": {
"description": "Delete a WebServer interface of the server.",
"params": {
"id": "String"
},
"returns": {
"configurationError": "$ref:ConfigurationError"
}
},
"Configuration.DeleteWebSocketServerConfiguration": {
"description": "Delete a WebSocket Server interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped.",
"params": {
"id": "String"
},
"returns": {
"configurationError": "$ref:ConfigurationError"
}
},
"Configuration.GetAvailableLanguages": { "Configuration.GetAvailableLanguages": {
"description": "Returns a list of locale codes available for the server. i.e. en_US, de_AT", "description": "Returns a list of locale codes available for the server. i.e. en_US, de_AT",
"params": { "params": {
@ -53,21 +80,15 @@
"serverUuid": "Uuid", "serverUuid": "Uuid",
"timeZone": "String" "timeZone": "String"
}, },
"sslConfiguration": { "tcpServerConfigurations": [
"enabled": "Bool" "$ref:ServerConfiguration"
}, ],
"tcpServerConfiguration": { "webServerConfigurations": [
"host": "String", "$ref:WebServerConfiguration"
"port": "Uint" ],
}, "webSocketServerConfigurations": [
"webServerConfiguration": { "$ref:ServerConfiguration"
"host": "String", ]
"port": "Uint"
},
"webSocketServerConfiguration": {
"host": "String",
"port": "Uint"
}
} }
}, },
"Configuration.GetTimeZones": { "Configuration.GetTimeZones": {
@ -99,10 +120,9 @@
} }
}, },
"Configuration.SetTcpServerConfiguration": { "Configuration.SetTcpServerConfiguration": {
"description": "Configure the TCP interface of the server. Note: if you are using the TCP server for this call you will loose the connection.", "description": "Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped.",
"params": { "params": {
"host": "String", "configuration": "$ref:ServerConfiguration"
"port": "Uint"
}, },
"returns": { "returns": {
"configurationError": "$ref:ConfigurationError" "configurationError": "$ref:ConfigurationError"
@ -118,20 +138,18 @@
} }
}, },
"Configuration.SetWebServerConfiguration": { "Configuration.SetWebServerConfiguration": {
"description": "Configure the web server of the server.", "description": "Configure a WebServer interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added.",
"params": { "params": {
"host": "String", "configuration": "$ref:WebServerConfiguration"
"port": "Uint"
}, },
"returns": { "returns": {
"configurationError": "$ref:ConfigurationError" "configurationError": "$ref:ConfigurationError"
} }
}, },
"Configuration.SetWebSocketServerConfiguration": { "Configuration.SetWebSocketServerConfiguration": {
"description": "Configure the web socket interface of the server. Note: if you are using the web socket server for this call you will loose the connection.", "description": "Configure a WebSocket Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped.",
"params": { "params": {
"host": "String", "configuration": "$ref:ServerConfiguration"
"port": "Uint"
}, },
"returns": { "returns": {
"configurationError": "$ref:ConfigurationError" "configurationError": "$ref:ConfigurationError"
@ -905,6 +923,7 @@
"ConfigurationErrorNoError", "ConfigurationErrorNoError",
"ConfigurationErrorInvalidTimeZone", "ConfigurationErrorInvalidTimeZone",
"ConfigurationErrorInvalidStationName", "ConfigurationErrorInvalidStationName",
"ConfigurationErrorInvalidId",
"ConfigurationErrorInvalidPort", "ConfigurationErrorInvalidPort",
"ConfigurationErrorInvalidHostAddress", "ConfigurationErrorInvalidHostAddress",
"ConfigurationErrorBluetoothHardwareNotAvailable", "ConfigurationErrorBluetoothHardwareNotAvailable",
@ -1254,6 +1273,13 @@
"RuleErrorContainsEventBasesAction", "RuleErrorContainsEventBasesAction",
"RuleErrorNoExitActions" "RuleErrorNoExitActions"
], ],
"ServerConfiguration": {
"address": "String",
"authenticationEnabled": "Bool",
"id": "String",
"port": "Uint",
"sslEnabled": "Bool"
},
"SetupMethod": [ "SetupMethod": [
"SetupMethodJustAdd", "SetupMethodJustAdd",
"SetupMethodDisplayPin", "SetupMethodDisplayPin",

View File

@ -118,6 +118,9 @@ GuhTestBase::GuhTestBase(QObject *parent) :
m_mockDevice2Port = 7331 + (qrand() % 1000); m_mockDevice2Port = 7331 + (qrand() % 1000);
QCoreApplication::instance()->setOrganizationName("guh-test"); QCoreApplication::instance()->setOrganizationName("guh-test");
QSignalSpy spy(GuhCore::instance(), SIGNAL(initialized()));
spy.wait();
GuhCore::instance()->userManager()->removeUser("dummy@guh.io"); GuhCore::instance()->userManager()->removeUser("dummy@guh.io");
GuhCore::instance()->userManager()->createUser("dummy@guh.io", "DummyPW1!"); GuhCore::instance()->userManager()->createUser("dummy@guh.io", "DummyPW1!");
m_apiToken = GuhCore::instance()->userManager()->authenticate("dummy@guh.io", "DummyPW1!", "testcase"); m_apiToken = GuhCore::instance()->userManager()->authenticate("dummy@guh.io", "DummyPW1!", "testcase");
@ -476,6 +479,8 @@ void GuhTestBase::restartServer()
{ {
// Destroy and recreate the core instance... // Destroy and recreate the core instance...
GuhCore::instance()->destroy(); GuhCore::instance()->destroy();
QSignalSpy coreSpy(GuhCore::instance(), SIGNAL(initialized()));
coreSpy.wait();
QSignalSpy spy(GuhCore::instance()->deviceManager(), SIGNAL(loaded())); QSignalSpy spy(GuhCore::instance()->deviceManager(), SIGNAL(loaded()));
spy.wait(); spy.wait();
m_mockTcpServer = MockTcpServer::servers().first(); m_mockTcpServer = MockTcpServer::servers().first();

View File

@ -32,7 +32,7 @@ using namespace guhserver;
QList<MockTcpServer*> MockTcpServer::s_allServers; QList<MockTcpServer*> MockTcpServer::s_allServers;
MockTcpServer::MockTcpServer(QObject *parent): MockTcpServer::MockTcpServer(QObject *parent):
TransportInterface(parent) TransportInterface(ServerConfiguration(), parent)
{ {
s_allServers.append(this); s_allServers.append(this);
} }