Add configuration for the tunnel proxy server

This commit is contained in:
Michael Zanetti 2022-01-20 16:59:56 +01:00
parent fea2ae0866
commit 47add31e63
18 changed files with 283 additions and 78 deletions

View File

@ -94,7 +94,7 @@ MqttChannel *MqttProviderImplementation::createChannel(const QString &clientId,
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) { foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
if (clientAddress.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) { if (clientAddress.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) {
foreach (const ServerConfiguration &config, m_broker->configurations()) { foreach (const ServerConfiguration &config, m_broker->configurations()) {
if (config.address == QHostAddress("0.0.0.0") || clientAddress.isInSubnet(config.address, addressEntry.prefixLength())) { if (QHostAddress(config.address) == QHostAddress("0.0.0.0") || clientAddress.isInSubnet(QHostAddress(config.address), addressEntry.prefixLength())) {
channel->m_serverAddress = addressEntry.ip(); channel->m_serverAddress = addressEntry.ip();
channel->m_serverPort = config.port; channel->m_serverPort = config.port;
break; break;
@ -145,9 +145,9 @@ MqttClient *MqttProviderImplementation::createInternalClient(const QString &clie
ServerConfiguration preferredConfig; ServerConfiguration preferredConfig;
foreach (const ServerConfiguration &config, m_broker->configurations()) { foreach (const ServerConfiguration &config, m_broker->configurations()) {
if (config.address == QHostAddress::Any if (QHostAddress(config.address) == QHostAddress::Any
|| config.address == QHostAddress::AnyIPv4 || QHostAddress(config.address) == QHostAddress::AnyIPv4
|| config.address == QHostAddress::LocalHost) { || QHostAddress(config.address) == QHostAddress::LocalHost) {
preferredConfig = config; preferredConfig = config;
break; break;
} }
@ -176,12 +176,12 @@ MqttClient *MqttProviderImplementation::createInternalClient(const QString &clie
m_broker->removePolicy(clientId); m_broker->removePolicy(clientId);
}); });
if (preferredConfig.address == QHostAddress::Any if (QHostAddress(preferredConfig.address) == QHostAddress::Any
|| preferredConfig.address == QHostAddress::AnyIPv4 || QHostAddress(preferredConfig.address) == QHostAddress::AnyIPv4
|| preferredConfig.address == QHostAddress::LocalHost) { || QHostAddress(preferredConfig.address) == QHostAddress::LocalHost) {
client->connectToHost("127.0.0.1", preferredConfig.port); client->connectToHost("127.0.0.1", preferredConfig.port);
} else { } else {
client->connectToHost(preferredConfig.address.toString(), preferredConfig.port); client->connectToHost(preferredConfig.address, preferredConfig.port);
} }
return client; return client;
} }

View File

@ -86,6 +86,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
// Objects // Objects
registerObject<ServerConfiguration>(); registerObject<ServerConfiguration>();
registerObject<WebServerConfiguration>(); registerObject<WebServerConfiguration>();
registerObject<TunnelProxyServerConfiguration>();
registerObject<MqttPolicy>(); registerObject<MqttPolicy>();
// Methods // Methods
@ -118,12 +119,15 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
QVariantList webSocketServerConfigurations; QVariantList webSocketServerConfigurations;
webSocketServerConfigurations.append(objectRef<ServerConfiguration>()); webSocketServerConfigurations.append(objectRef<ServerConfiguration>());
returns.insert("webSocketServerConfigurations", webSocketServerConfigurations); returns.insert("webSocketServerConfigurations", webSocketServerConfigurations);
QVariantList tunnelProxyServerConfigurations;
tunnelProxyServerConfigurations.append(objectRef<TunnelProxyServerConfiguration>());
returns.insert("tunnelProxyServerConfigurations", tunnelProxyServerConfigurations);
QVariantList mqttServerConfigurations; QVariantList mqttServerConfigurations;
mqttServerConfigurations.append(objectRef<ServerConfiguration>()); mqttServerConfigurations.append(objectRef<ServerConfiguration>());
QVariantMap cloudConfiguration; QVariantMap cloudConfiguration;
cloudConfiguration.insert("enabled", enumValueName(Bool)); cloudConfiguration.insert("enabled", enumValueName(Bool));
returns.insert("cloud", cloudConfiguration); returns.insert("cloud", cloudConfiguration);
registerMethod("GetConfigurations", description, params, returns); registerMethod("GetConfigurations", description, params, returns, Types::PermissionScopeNone);
params.clear(); returns.clear(); params.clear(); returns.clear();
description = "Set the name of the server. Default is nymea."; description = "Set the name of the server. Default is nymea.";
@ -173,6 +177,18 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>()); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
registerMethod("DeleteWebSocketServerConfiguration", description, params, returns); registerMethod("DeleteWebSocketServerConfiguration", description, params, returns);
params.clear(); returns.clear();
description = "Configure a Tunnel Proxy 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", objectRef<TunnelProxyServerConfiguration>());
returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
registerMethod("SetTunnelProxyServerConfiguration", description, params, returns);
params.clear(); returns.clear();
description = "Delete a Tunnel Proxy 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("id", enumValueName(String));
returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
registerMethod("DeleteTunnelProxyServerConfiguration", description, params, returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
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."; 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.insert("configuration", objectRef<WebServerConfiguration>()); params.insert("configuration", objectRef<WebServerConfiguration>());
@ -257,6 +273,16 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
params.insert("id", enumValueName(String)); params.insert("id", enumValueName(String));
registerNotification("WebSocketServerConfigurationRemoved", description, params); registerNotification("WebSocketServerConfigurationRemoved", description, params);
params.clear(); returns.clear();
description = "Emitted whenever the tunnel proxy server configuration changes.";
params.insert("tunnelProxyServerConfiguration", objectRef<TunnelProxyServerConfiguration>());
registerNotification("TunnelProxyServerConfigurationChanged", description, params);
params.clear(); returns.clear();
description = "Emitted whenever a tunnel proxy server configuration is removed.";
params.insert("id", enumValueName(String));
registerNotification("TunnelProxyServerConfigurationRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
description = "Emitted whenever the MQTT broker configuration is changed."; description = "Emitted whenever the MQTT broker configuration is changed.";
params.insert("mqttServerConfiguration", objectRef<ServerConfiguration>()); params.insert("mqttServerConfiguration", objectRef<ServerConfiguration>());
@ -303,6 +329,8 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webServerConfigurationRemoved, this, &ConfigurationHandler::onWebServerConfigurationRemoved); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webServerConfigurationRemoved, this, &ConfigurationHandler::onWebServerConfigurationRemoved);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webSocketServerConfigurationChanged, this, &ConfigurationHandler::onWebSocketServerConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webSocketServerConfigurationChanged, this, &ConfigurationHandler::onWebSocketServerConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webSocketServerConfigurationRemoved, this, &ConfigurationHandler::onWebSocketServerConfigurationRemoved); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::webSocketServerConfigurationRemoved, this, &ConfigurationHandler::onWebSocketServerConfigurationRemoved);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::tunnelProxyServerConfigurationChanged, this, &ConfigurationHandler::onTunnelProxyServerConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::tunnelProxyServerConfigurationRemoved, this, &ConfigurationHandler::onTunnelProxyServerConfigurationRemoved);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttServerConfigurationChanged, this, &ConfigurationHandler::onMqttServerConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttServerConfigurationChanged, this, &ConfigurationHandler::onMqttServerConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttServerConfigurationRemoved, this, &ConfigurationHandler::onMqttServerConfigurationRemoved); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttServerConfigurationRemoved, this, &ConfigurationHandler::onMqttServerConfigurationRemoved);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttPolicyChanged, this, &ConfigurationHandler::onMqttPolicyChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttPolicyChanged, this, &ConfigurationHandler::onMqttPolicyChanged);
@ -340,6 +368,12 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap &params) co
} }
returns.insert("webSocketServerConfigurations", webSocketServerConfigs); returns.insert("webSocketServerConfigurations", webSocketServerConfigs);
QVariantList tunnelProxyServerConfigs;
foreach (const TunnelProxyServerConfiguration &config, NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations()) {
tunnelProxyServerConfigs.append(pack(config));
}
returns.insert("tunnelProxyServerConfigurations", tunnelProxyServerConfigs);
QVariantMap cloudConfig; QVariantMap cloudConfig;
cloudConfig.insert("enabled", NymeaCore::instance()->configuration()->cloudEnabled()); cloudConfig.insert("enabled", NymeaCore::instance()->configuration()->cloudEnabled());
returns.insert("cloud", cloudConfig); returns.insert("cloud", cloudConfig);
@ -422,7 +456,7 @@ JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &pa
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort));
} }
qCDebug(dcJsonRpc()) << QString("Configure TCP server %1:%2").arg(config.address.toString()).arg(config.port); qCDebug(dcJsonRpc()) << QString("Configure TCP server %1:%2").arg(config.address).arg(config.port);
NymeaCore::instance()->configuration()->setTcpServerConfiguration(config); NymeaCore::instance()->configuration()->setTcpServerConfiguration(config);
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
@ -453,7 +487,7 @@ JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &pa
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort));
} }
qCDebug(dcJsonRpc()) << QString("Configure web server %1:%2").arg(config.address.toString()).arg(config.port); qCDebug(dcJsonRpc()) << QString("Configure web server %1:%2").arg(config.address).arg(config.port);
NymeaCore::instance()->configuration()->setWebServerConfiguration(config); NymeaCore::instance()->configuration()->setWebServerConfiguration(config);
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
@ -483,7 +517,7 @@ JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantM
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort));
} }
qCDebug(dcJsonRpc()) << QString("Configuring web socket server %1:%2").arg(config.address.toString()).arg(config.port); qCDebug(dcJsonRpc()) << QString("Configuring web socket server %1:%2").arg(config.address).arg(config.port);
NymeaCore::instance()->configuration()->setWebSocketServerConfiguration(config); NymeaCore::instance()->configuration()->setWebSocketServerConfiguration(config);
@ -500,6 +534,37 @@ JsonReply *ConfigurationHandler::DeleteWebSocketServerConfiguration(const QVaria
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
} }
JsonReply *ConfigurationHandler::SetTunnelProxyServerConfiguration(const QVariantMap &params) const
{
TunnelProxyServerConfiguration config = unpack<TunnelProxyServerConfiguration>(params.value("configuration").toMap());
if (config.id.isEmpty()) {
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId));
}
if (config.address.isNull())
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidHostAddress));
if (config.port <= 0 || config.port > 65535) {
qCWarning(dcJsonRpc()) << "Port out of range";
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort));
}
qCDebug(dcJsonRpc()) << QString("Configuring tunnel proxy server %1:%2").arg(config.address).arg(config.port);
NymeaCore::instance()->configuration()->setTunnelProxyServerConfiguration(config);
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
}
JsonReply *ConfigurationHandler::DeleteTunnelProxyServerConfiguration(const QVariantMap &params) const
{
QString id = params.value("id").toString();
if (id.isEmpty() || !NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations().contains(id)) {
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId));
}
NymeaCore::instance()->configuration()->removeTunnelProxyServerConfiguration(id);
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
}
JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap &params) const JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap &params) const
{ {
Q_UNUSED(params) Q_UNUSED(params)
@ -526,7 +591,7 @@ JsonReply *ConfigurationHandler::SetMqttServerConfiguration(const QVariantMap &p
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidPort));
} }
qCDebug(dcJsonRpc()) << QString("Configure MQTT server %1:%2").arg(config.address.toString()).arg(config.port); qCDebug(dcJsonRpc()) << QString("Configure MQTT server %1:%2").arg(config.address).arg(config.port);
NymeaCore::instance()->configuration()->setMqttServerConfiguration(config); NymeaCore::instance()->configuration()->setMqttServerConfiguration(config);
@ -639,6 +704,22 @@ void ConfigurationHandler::onWebSocketServerConfigurationRemoved(const QString &
emit WebSocketServerConfigurationRemoved(params); emit WebSocketServerConfigurationRemoved(params);
} }
void ConfigurationHandler::onTunnelProxyServerConfigurationChanged(const QString &id)
{
qCDebug(dcJsonRpc()) << "Notification: Tunnel proxy server configuration changed";
QVariantMap params;
params.insert("tunnelProxyServerConfiguration", pack(NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations().value(id)));
emit TunnelProxyServerConfigurationChanged(params);
}
void ConfigurationHandler::onTunnelProxyServerConfigurationRemoved(const QString &id)
{
qCDebug(dcJsonRpc()) << "Notification: Tunnel proxy server configuration removed";
QVariantMap params;
params.insert("id", id);
emit TunnelProxyServerConfigurationRemoved(params);
}
void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id) void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id)
{ {
qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed"; qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed";

View File

@ -60,6 +60,8 @@ public:
Q_INVOKABLE JsonReply *DeleteWebServerConfiguration(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; Q_INVOKABLE JsonReply *DeleteWebSocketServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetTunnelProxyServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *DeleteTunnelProxyServerConfiguration(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *GetMqttServerConfigurations(const QVariantMap &params) const; Q_INVOKABLE JsonReply *GetMqttServerConfigurations(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *SetMqttServerConfiguration(const QVariantMap &params) const; Q_INVOKABLE JsonReply *SetMqttServerConfiguration(const QVariantMap &params) const;
@ -79,6 +81,8 @@ signals:
void WebServerConfigurationRemoved(const QVariantMap &params); void WebServerConfigurationRemoved(const QVariantMap &params);
void WebSocketServerConfigurationChanged(const QVariantMap &params); void WebSocketServerConfigurationChanged(const QVariantMap &params);
void WebSocketServerConfigurationRemoved(const QVariantMap &params); void WebSocketServerConfigurationRemoved(const QVariantMap &params);
void TunnelProxyServerConfigurationChanged(const QVariantMap &params);
void TunnelProxyServerConfigurationRemoved(const QVariantMap &params);
void MqttServerConfigurationChanged(const QVariantMap &params); void MqttServerConfigurationChanged(const QVariantMap &params);
void MqttServerConfigurationRemoved(const QVariantMap &params); void MqttServerConfigurationRemoved(const QVariantMap &params);
@ -95,6 +99,8 @@ private slots:
void onWebServerConfigurationRemoved(const QString &id); void onWebServerConfigurationRemoved(const QString &id);
void onWebSocketServerConfigurationChanged(const QString &id); void onWebSocketServerConfigurationChanged(const QString &id);
void onWebSocketServerConfigurationRemoved(const QString &id); void onWebSocketServerConfigurationRemoved(const QString &id);
void onTunnelProxyServerConfigurationChanged(const QString &id);
void onTunnelProxyServerConfigurationRemoved(const QString &id);
void onMqttServerConfigurationChanged(const QString &id); void onMqttServerConfigurationChanged(const QString &id);
void onMqttServerConfigurationRemoved(const QString &id); void onMqttServerConfigurationRemoved(const QString &id);
void onMqttPolicyChanged(const QString &clientId); void onMqttPolicyChanged(const QString &clientId);

View File

@ -93,7 +93,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
qCWarning(dcConfiguration) << "No TCP server configuration found. Generating default of nymeas://0.0.0.0:2222"; qCWarning(dcConfiguration) << "No TCP server configuration found. Generating default of nymeas://0.0.0.0:2222";
ServerConfiguration config; ServerConfiguration config;
config.id = "default"; config.id = "default";
config.address = QHostAddress("0.0.0.0"); config.address = QHostAddress("0.0.0.0").toString();
config.port = 2222; config.port = 2222;
config.sslEnabled = true; config.sslEnabled = true;
config.authenticationEnabled = true; config.authenticationEnabled = true;
@ -121,7 +121,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
qCWarning(dcConfiguration) << "No Web server configuration found. Generating defaults of http://0.0.0.0:80 and https://0.0.0.0:443"; qCWarning(dcConfiguration) << "No Web server configuration found. Generating defaults of http://0.0.0.0:80 and https://0.0.0.0:443";
WebServerConfiguration insecureConfig; WebServerConfiguration insecureConfig;
insecureConfig.id = "insecure"; insecureConfig.id = "insecure";
insecureConfig.address = QHostAddress("0.0.0.0"); insecureConfig.address = QHostAddress("0.0.0.0").toString();
insecureConfig.port = 80; insecureConfig.port = 80;
insecureConfig.sslEnabled = false; insecureConfig.sslEnabled = false;
insecureConfig.authenticationEnabled = false; insecureConfig.authenticationEnabled = false;
@ -132,7 +132,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
WebServerConfiguration secureConfig; WebServerConfiguration secureConfig;
secureConfig.id = "secure"; secureConfig.id = "secure";
secureConfig.address = QHostAddress("0.0.0.0"); secureConfig.address = QHostAddress("0.0.0.0").toString();
secureConfig.port = 443; secureConfig.port = 443;
secureConfig.sslEnabled = true; secureConfig.sslEnabled = true;
secureConfig.authenticationEnabled = false; secureConfig.authenticationEnabled = false;
@ -162,7 +162,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
qCWarning(dcConfiguration) << "No WebSocket server configuration found. Generating default of wss://0.0.0.0:4444"; qCWarning(dcConfiguration) << "No WebSocket server configuration found. Generating default of wss://0.0.0.0:4444";
ServerConfiguration config; ServerConfiguration config;
config.id = "default"; config.id = "default";
config.address = QHostAddress("0.0.0.0"); config.address = QHostAddress("0.0.0.0").toString();
config.port = 4444; config.port = 4444;
config.sslEnabled = true; config.sslEnabled = true;
config.authenticationEnabled = true; config.authenticationEnabled = true;
@ -190,7 +190,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
qCWarning(dcConfiguration) << "No MQTT server configuration found. Generating default of 0.0.0.0:1883"; qCWarning(dcConfiguration) << "No MQTT server configuration found. Generating default of 0.0.0.0:1883";
ServerConfiguration config; ServerConfiguration config;
config.id = "default"; config.id = "default";
config.address = QHostAddress("0.0.0.0"); config.address = QHostAddress("0.0.0.0").toString();
config.port = 1883; config.port = 1883;
config.sslEnabled = false; config.sslEnabled = false;
config.authenticationEnabled = true; config.authenticationEnabled = true;
@ -212,19 +212,33 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
} }
// Tunnel Proxy Server // Tunnel Proxy Server
// FIXME: maybe configure default proxy createDefaults = !settings.childGroups().contains("TunnelProxyServer");
if (settings.childGroups().contains("TunnelProxyServer")) { if (settings.childGroups().contains("TunnelProxyServer")) {
settings.beginGroup("TunnelProxyServer"); settings.beginGroup("TunnelProxyServer");
if (settings.value("disabled").toBool()) { if (settings.value("disabled").toBool()) {
qCDebug(dcConfiguration) << "Tunnel proxy server disabled by configuration."; qCDebug(dcConfiguration) << "Tunnel proxy server disabled by configuration.";
} else if (!settings.childGroups().isEmpty()) { } else if (!settings.childGroups().isEmpty()) {
foreach (const QString &key, settings.childGroups()) { foreach (const QString &key, settings.childGroups()) {
ServerConfiguration config = readServerConfig("TunnelProxyServer", key); TunnelProxyServerConfiguration config = readTunnelProxyServerConfig(key);
m_tunnelProxyServerConfigs[config.id] = config; m_tunnelProxyServerConfigs[config.id] = config;
} }
} else {
createDefaults = true;
} }
settings.endGroup(); settings.endGroup();
} }
if (createDefaults) {
qCWarning(dcConfiguration) << "No Tunnel Proxy server configuration found. Generating default of remoteproxy.nymea.io:2213";
TunnelProxyServerConfiguration config;
config.id = "default";
config.address = "remoteproxy.nymea.io";
config.port = 2213;
config.sslEnabled = true;
config.authenticationEnabled = true;
config.ignoreSslErrors = false;
m_tunnelProxyServerConfigs[config.id] = config;
storeTunnelProxyServerConfig(config);
}
// Write defaults for log settings // Write defaults for log settings
settings.beginGroup("Logs"); settings.beginGroup("Logs");
@ -381,12 +395,12 @@ void NymeaConfiguration::removeWebSocketServerConfiguration(const QString &id)
emit webSocketServerConfigurationRemoved(id); emit webSocketServerConfigurationRemoved(id);
} }
QHash<QString, ServerConfiguration> NymeaConfiguration::tunnelProxyServerConfigurations() const QHash<QString, TunnelProxyServerConfiguration> NymeaConfiguration::tunnelProxyServerConfigurations() const
{ {
return m_tunnelProxyServerConfigs; return m_tunnelProxyServerConfigs;
} }
void NymeaConfiguration::setTunnelProxyServerConfiguration(const ServerConfiguration &config) void NymeaConfiguration::setTunnelProxyServerConfiguration(const TunnelProxyServerConfiguration &config)
{ {
m_tunnelProxyServerConfigs[config.id] = config; m_tunnelProxyServerConfigs[config.id] = config;
storeServerConfig("TunnelProxyServer", config); storeServerConfig("TunnelProxyServer", config);
@ -661,7 +675,7 @@ void NymeaConfiguration::storeServerConfig(const QString &group, const ServerCon
settings.beginGroup(group); settings.beginGroup(group);
settings.remove("disabled"); settings.remove("disabled");
settings.beginGroup(config.id); settings.beginGroup(config.id);
settings.setValue("address", config.address.toString()); settings.setValue("address", config.address);
settings.setValue("port", config.port); settings.setValue("port", config.port);
settings.setValue("sslEnabled", config.sslEnabled); settings.setValue("sslEnabled", config.sslEnabled);
settings.setValue("authenticationEnabled", config.authenticationEnabled); settings.setValue("authenticationEnabled", config.authenticationEnabled);
@ -676,7 +690,7 @@ ServerConfiguration NymeaConfiguration::readServerConfig(const QString &group, c
settings.beginGroup(group); settings.beginGroup(group);
settings.beginGroup(id); settings.beginGroup(id);
config.id = id; config.id = id;
config.address = QHostAddress(settings.value("address").toString()); config.address = settings.value("address").toString();
config.port = settings.value("port").toUInt(); config.port = settings.value("port").toUInt();
config.sslEnabled = settings.value("sslEnabled", true).toBool(); config.sslEnabled = settings.value("sslEnabled", true).toBool();
config.authenticationEnabled = settings.value("authenticationEnabled", true).toBool(); config.authenticationEnabled = settings.value("authenticationEnabled", true).toBool();
@ -715,7 +729,7 @@ WebServerConfiguration NymeaConfiguration::readWebServerConfig(const QString &id
settings.beginGroup("WebServer"); settings.beginGroup("WebServer");
settings.beginGroup(id); settings.beginGroup(id);
config.id = id; config.id = id;
config.address = QHostAddress(settings.value("address").toString()); config.address = settings.value("address").toString();
config.port = settings.value("port").toUInt(); config.port = settings.value("port").toUInt();
config.sslEnabled = settings.value("sslEnabled", true).toBool(); config.sslEnabled = settings.value("sslEnabled", true).toBool();
config.authenticationEnabled = settings.value("authenticationEnabled", true).toBool(); config.authenticationEnabled = settings.value("authenticationEnabled", true).toBool();
@ -726,6 +740,34 @@ WebServerConfiguration NymeaConfiguration::readWebServerConfig(const QString &id
return config; return config;
} }
void NymeaConfiguration::storeTunnelProxyServerConfig(const TunnelProxyServerConfiguration &config)
{
storeServerConfig("TunnelProxyServer", config);
NymeaSettings settings(NymeaSettings::SettingsRoleGlobal);
settings.beginGroup("TunnelProxyServer");
settings.beginGroup(config.id);
settings.setValue("ignoreSslErrors", config.ignoreSslErrors);
settings.endGroup();
settings.endGroup();
}
TunnelProxyServerConfiguration NymeaConfiguration::readTunnelProxyServerConfig(const QString &id)
{
TunnelProxyServerConfiguration config;
NymeaSettings settings(NymeaSettings::SettingsRoleGlobal);
settings.beginGroup("TunnelProxyServer");
settings.beginGroup(id);
config.id = id;
config.address = 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.ignoreSslErrors = settings.value("ignoreSslErrors").toBool();
settings.endGroup();
settings.endGroup();
return config;
}
void NymeaConfiguration::storeMqttPolicy(const MqttPolicy &policy) void NymeaConfiguration::storeMqttPolicy(const MqttPolicy &policy)
{ {
NymeaSettings settings(NymeaSettings::SettingsRoleMqttPolicies); NymeaSettings settings(NymeaSettings::SettingsRoleMqttPolicies);
@ -747,7 +789,7 @@ QDebug operator <<(QDebug debug, const ServerConfiguration &configuration)
{ {
debug.nospace() << "ServerConfiguration(" << configuration.address; debug.nospace() << "ServerConfiguration(" << configuration.address;
debug.nospace() << ", " << configuration.id; debug.nospace() << ", " << configuration.id;
debug.nospace() << ", " << QString("%1:%2").arg(configuration.address.toString()).arg(configuration.port); debug.nospace() << ", " << QString("%1:%2").arg(configuration.address).arg(configuration.port);
debug.nospace() << ") "; debug.nospace() << ") ";
return debug; return debug;
} }

View File

@ -42,15 +42,14 @@ namespace nymeaserver {
class ServerConfiguration { class ServerConfiguration {
Q_GADGET Q_GADGET
Q_PROPERTY(QString id MEMBER id) Q_PROPERTY(QString id MEMBER id)
Q_PROPERTY(QString address READ addressString WRITE setAddress) Q_PROPERTY(QString address MEMBER address)
Q_PROPERTY(uint port MEMBER port) Q_PROPERTY(uint port MEMBER port)
Q_PROPERTY(bool sslEnabled MEMBER sslEnabled) Q_PROPERTY(bool sslEnabled MEMBER sslEnabled)
Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled) Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled)
public: public:
QString id; QString id;
QHostAddress address; QString address;
QString addressString() { return address.toString(); } void setAddress(const QString &address) {this->address = address; }
void setAddress(const QString &addressString) {address = QHostAddress(addressString); }
uint port = 0; uint port = 0;
bool sslEnabled = true; bool sslEnabled = true;
bool authenticationEnabled = true; bool authenticationEnabled = true;
@ -75,6 +74,14 @@ public:
bool restServerEnabled = false; bool restServerEnabled = false;
}; };
class TunnelProxyServerConfiguration: public ServerConfiguration
{
Q_GADGET
Q_PROPERTY(bool ignoreSslErrors MEMBER ignoreSslErrors)
public:
bool ignoreSslErrors = false;
};
class MqttPolicy class MqttPolicy
{ {
Q_GADGET Q_GADGET
@ -148,8 +155,8 @@ public:
void removeWebSocketServerConfiguration(const QString &id); void removeWebSocketServerConfiguration(const QString &id);
// Tunnel proxy server // Tunnel proxy server
QHash<QString, ServerConfiguration> tunnelProxyServerConfigurations() const; QHash<QString, TunnelProxyServerConfiguration> tunnelProxyServerConfigurations() const;
void setTunnelProxyServerConfiguration(const ServerConfiguration &config); void setTunnelProxyServerConfiguration(const TunnelProxyServerConfiguration &config);
void removeTunnelProxyServerConfiguration(const QString &id); void removeTunnelProxyServerConfiguration(const QString &id);
// MQTT // MQTT
@ -192,7 +199,7 @@ private:
QHash<QString, ServerConfiguration> m_webSocketServerConfigs; QHash<QString, ServerConfiguration> m_webSocketServerConfigs;
QHash<QString, ServerConfiguration> m_mqttServerConfigs; QHash<QString, ServerConfiguration> m_mqttServerConfigs;
QHash<QString, MqttPolicy> m_mqttPolicies; QHash<QString, MqttPolicy> m_mqttPolicies;
QHash<QString, ServerConfiguration> m_tunnelProxyServerConfigs; QHash<QString, TunnelProxyServerConfiguration> m_tunnelProxyServerConfigs;
void setServerUuid(const QUuid &uuid); void setServerUuid(const QUuid &uuid);
void setWebServerPublicFolder(const QString & path); void setWebServerPublicFolder(const QString & path);
@ -204,6 +211,8 @@ private:
void deleteServerConfig(const QString &group, const QString &id); void deleteServerConfig(const QString &group, const QString &id);
void storeWebServerConfig(const WebServerConfiguration &config); void storeWebServerConfig(const WebServerConfiguration &config);
WebServerConfiguration readWebServerConfig(const QString &id); WebServerConfiguration readWebServerConfig(const QString &id);
void storeTunnelProxyServerConfig(const TunnelProxyServerConfiguration &config);
TunnelProxyServerConfiguration readTunnelProxyServerConfig(const QString &id);
void storeMqttPolicy(const MqttPolicy &policy); void storeMqttPolicy(const MqttPolicy &policy);
MqttPolicy readMqttPolicy(const QString &clientId); MqttPolicy readMqttPolicy(const QString &clientId);

View File

@ -70,6 +70,7 @@ namespace nymeaserver {
ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configuration, const QStringList &additionalInterfaces, QObject *parent) : ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configuration, const QStringList &additionalInterfaces, QObject *parent) :
QObject(parent), QObject(parent),
m_platform(platform), m_platform(platform),
m_nymeaConfiguration(configuration),
m_sslConfiguration(QSslConfiguration()) m_sslConfiguration(QSslConfiguration())
{ {
if (!QSslSocket::supportsSsl()) { if (!QSslSocket::supportsSsl()) {
@ -120,7 +121,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
QUrl additionalInterface(interfaceString); QUrl additionalInterface(interfaceString);
ServerConfiguration config; ServerConfiguration config;
config.id = "tmp-" + additionalInterface.host(); config.id = "tmp-" + additionalInterface.host();
config.address = QHostAddress(additionalInterface.host()); config.address = additionalInterface.host();
config.port = additionalInterface.port(); config.port = additionalInterface.port();
TransportInterface *server = nullptr; TransportInterface *server = nullptr;
QString serverType, serviceType; QString serverType, serviceType;
@ -166,7 +167,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
m_bluetoothServer->startServer(); m_bluetoothServer->startServer();
} }
foreach (const ServerConfiguration &config, configuration->tunnelProxyServerConfigurations()) { foreach (const TunnelProxyServerConfiguration &config, configuration->tunnelProxyServerConfigurations()) {
TunnelProxyServer *tunnelProxyServer = new TunnelProxyServer(configuration->serverName(), configuration->serverUuid(), config, this); TunnelProxyServer *tunnelProxyServer = new TunnelProxyServer(configuration->serverName(), configuration->serverUuid(), config, this);
qCDebug(dcServerManager()) << "Creating tunnel proxy server" << config; qCDebug(dcServerManager()) << "Creating tunnel proxy server" << config;
m_tunnelProxyServers.insert(config.id, tunnelProxyServer); m_tunnelProxyServers.insert(config.id, tunnelProxyServer);
@ -318,7 +319,7 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
server->stopServer(); server->stopServer();
server->setConfiguration(config); server->setConfiguration(config);
} else { } else {
qDebug(dcServerManager()) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address.toString() << config.port << "(SSL:" << config.sslEnabled << ")"; qDebug(dcServerManager()) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address << config.port << "(SSL:" << config.sslEnabled << ")";
server = new WebServer(config, m_sslConfiguration, this); server = new WebServer(config, m_sslConfiguration, this);
m_webServers.insert(config.id, server); m_webServers.insert(config.id, server);
} }
@ -369,14 +370,32 @@ void ServerManager::mqttPolicyRemoved(const QString &clientId)
void ServerManager::tunnelProxyServerConfigurationChanged(const QString &id) void ServerManager::tunnelProxyServerConfigurationChanged(const QString &id)
{ {
// FIXME: not dynamic configurable for now TunnelProxyServer *server = m_tunnelProxyServers.value(id);
Q_UNUSED(id) TunnelProxyServerConfiguration config = NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations().value(id);
if (server) {
qDebug(dcServerManager()) << "Restarting tunnel proxy connection for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
unregisterZeroConfService(id, "ws");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcServerManager()) << "Received a tunnel proxy config change event but don't have a WebSocket Server instance for it. Creating new instance.";
server = new TunnelProxyServer(m_nymeaConfiguration->serverName(), m_nymeaConfiguration->serverUuid(), config, this);
m_tunnelProxyServers.insert(server->configuration().id, server);
}
m_jsonServer->registerTransportInterface(server, config.authenticationEnabled);
server->startServer();
} }
void ServerManager::tunnelProxyServerConfigurationRemoved(const QString &id) void ServerManager::tunnelProxyServerConfigurationRemoved(const QString &id)
{ {
// FIXME: not dynamic configurable for now if (!m_tunnelProxyServers.contains(id)) {
Q_UNUSED(id) qWarning(dcServerManager()) << "Received a tunnel proxy config removed event but don't have a tunnel proxy connection for it.";
return;
}
TunnelProxyServer *server = m_tunnelProxyServers.take(id);
m_jsonServer->unregisterTransportInterface(server);
server->stopServer();
server->deleteLater();
} }
void ServerManager::cloudEnabledChanged(bool enabled) void ServerManager::cloudEnabledChanged(bool enabled)
@ -402,7 +421,7 @@ bool ServerManager::registerZeroConfService(const ServerConfiguration &configura
txt.insert("name", NymeaCore::instance()->configuration()->serverName()); txt.insert("name", NymeaCore::instance()->configuration()->serverName());
txt.insert("sslEnabled", configuration.sslEnabled ? "true" : "false"); txt.insert("sslEnabled", configuration.sslEnabled ? "true" : "false");
QString name = "nymea-" + serverType + "-" + configuration.id; QString name = "nymea-" + serverType + "-" + configuration.id;
if (!m_platform->zeroConfController()->servicePublisher()->registerService(name, configuration.address, static_cast<quint16>(configuration.port), serviceType, txt)) { if (!m_platform->zeroConfController()->servicePublisher()->registerService(name, QHostAddress(configuration.address), static_cast<quint16>(configuration.port), serviceType, txt)) {
qCWarning(dcServerManager()) << "Could not register ZeroConf service for" << configuration; qCWarning(dcServerManager()) << "Could not register ZeroConf service for" << configuration;
return false; return false;
} }

View File

@ -69,6 +69,10 @@ public:
MqttBroker *mqttBroker() const; MqttBroker *mqttBroker() const;
public slots:
void setServerName(const QString &serverName);
private slots: private slots:
void tcpServerConfigurationChanged(const QString &id); void tcpServerConfigurationChanged(const QString &id);
void tcpServerConfigurationRemoved(const QString &id); void tcpServerConfigurationRemoved(const QString &id);
@ -89,8 +93,11 @@ private:
bool registerZeroConfService(const ServerConfiguration &configuration, const QString &serverType, const QString &serviceType); bool registerZeroConfService(const ServerConfiguration &configuration, const QString &serverType, const QString &serviceType);
void unregisterZeroConfService(const QString &configId, const QString &serverType); void unregisterZeroConfService(const QString &configId, const QString &serverType);
bool loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName);
private: private:
Platform *m_platform = nullptr; Platform *m_platform = nullptr;
NymeaConfiguration *m_nymeaConfiguration = nullptr;
// Interfaces // Interfaces
JsonRPCServerImplementation *m_jsonServer; JsonRPCServerImplementation *m_jsonServer;
@ -108,12 +115,6 @@ private:
QSslConfiguration m_sslConfiguration; QSslConfiguration m_sslConfiguration;
QSslKey m_certificateKey; QSslKey m_certificateKey;
QSslCertificate m_certificate; QSslCertificate m_certificate;
bool loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName);
public slots:
void setServerName(const QString &serverName);
}; };
} }

View File

@ -140,7 +140,7 @@ MqttBroker::~MqttBroker()
bool MqttBroker::startServer(const ServerConfiguration &config, const QSslConfiguration &sslConfiguration) bool MqttBroker::startServer(const ServerConfiguration &config, const QSslConfiguration &sslConfiguration)
{ {
int serverAddressId = m_server->listen(config.address, config.port, config.sslEnabled ? sslConfiguration : QSslConfiguration()); int serverAddressId = m_server->listen(QHostAddress(config.address), config.port, config.sslEnabled ? sslConfiguration : QSslConfiguration());
if (serverAddressId == -1) { if (serverAddressId == -1) {
qCWarning(dcMqtt) << "Error starting MQTT server on port" << config.port; qCWarning(dcMqtt) << "Error starting MQTT server on port" << config.port;
return false; return false;

View File

@ -101,7 +101,7 @@ TcpServer::~TcpServer()
/*! Returns the URL of this server. */ /*! Returns the URL of this server. */
QUrl TcpServer::serverUrl() const QUrl TcpServer::serverUrl() const
{ {
return QUrl(QString("%1://%2:%3").arg((configuration().sslEnabled ? "nymeas" : "nymea")).arg(configuration().address.toString()).arg(configuration().port)); return QUrl(QString("%1://%2:%3").arg((configuration().sslEnabled ? "nymeas" : "nymea")).arg(configuration().address).arg(configuration().port));
} }
/*! Sending \a data to a list of \a clients.*/ /*! Sending \a data to a list of \a clients.*/
@ -177,8 +177,8 @@ void TcpServer::setServerName(const QString &serverName)
bool TcpServer::startServer() bool TcpServer::startServer()
{ {
m_server = new SslServer(configuration().sslEnabled, m_sslConfig); m_server = new SslServer(configuration().sslEnabled, m_sslConfig);
if(!m_server->listen(configuration().address, static_cast<quint16>(configuration().port))) { if(!m_server->listen(QHostAddress(configuration().address), static_cast<quint16>(configuration().port))) {
qCWarning(dcTcpServer()) << "Tcp server error: can not listen on" << configuration().address.toString() << configuration().port; qCWarning(dcTcpServer()) << "Tcp server error: can not listen on" << configuration().address << configuration().port;
delete m_server; delete m_server;
m_server = nullptr; m_server = nullptr;
return false; return false;

View File

@ -35,21 +35,20 @@ NYMEA_LOGGING_CATEGORY(dcTunnelProxyServer, "TunnelProxyServer")
namespace nymeaserver { namespace nymeaserver {
TunnelProxyServer::TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const ServerConfiguration &configuration, QObject *parent) : TunnelProxyServer::TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const TunnelProxyServerConfiguration &configuration, QObject *parent) :
TransportInterface(configuration, parent), TransportInterface(configuration, parent),
m_config(configuration),
m_serverName(serverName), m_serverName(serverName),
m_serverUuid(serverUuid) m_serverUuid(serverUuid)
{ {
// Note: the authentication must always be enabled on the tunnel proxy server
if (!configuration.authenticationEnabled) { if (!configuration.authenticationEnabled) {
qCWarning(dcTunnelProxyServer()) << "============================================================================================================================="; qCWarning(dcTunnelProxyServer()) << "=====================================================================================================================";
qCWarning(dcTunnelProxyServer()) << "WARNING! The tunnel proxy server has authentication disabled! This is very dangerous and exposes your system to the internet."; qCWarning(dcTunnelProxyServer()) << "WARNING! Tunnel proxy connection has authentication disabled! The system will be publicly accessible on the internet.";
qCWarning(dcTunnelProxyServer()) << "============================================================================================================================="; qCWarning(dcTunnelProxyServer()) << "=====================================================================================================================";
} }
// Default to ssl m_serverUrl.setScheme(configuration.sslEnabled ? "ssl" : "tcp");
m_serverUrl.setScheme("ssl"); m_serverUrl.setHost(configuration.address);
m_serverUrl.setHost(configuration.address.toString());
m_serverUrl.setPort(configuration.port); m_serverUrl.setPort(configuration.port);
m_tunnelProxySocketServer = new TunnelProxySocketServer(m_serverUuid, m_serverName, this); m_tunnelProxySocketServer = new TunnelProxySocketServer(m_serverUuid, m_serverName, this);
@ -102,7 +101,7 @@ void TunnelProxyServer::setServerName(const QString &serverName)
bool TunnelProxyServer::startServer() bool TunnelProxyServer::startServer()
{ {
qCDebug(dcTunnelProxyServer()) << "Connecting to tunnel proxy server at:" << m_serverUrl;
m_tunnelProxySocketServer->startServer(m_serverUrl); m_tunnelProxySocketServer->startServer(m_serverUrl);
return true; return true;
} }
@ -144,7 +143,12 @@ void TunnelProxyServer::onSslErrors(const QList<QSslError> &errors)
{ {
qCDebug(dcTunnelProxyServer()) << "Remote proxy connection SSL errors occurred" << errors; qCDebug(dcTunnelProxyServer()) << "Remote proxy connection SSL errors occurred" << errors;
// FIXME: make this configurable // FIXME: make this configurable
m_tunnelProxySocketServer->ignoreSslErrors(); if (m_config.ignoreSslErrors) {
qCWarning(dcTunnelProxyServer()) << "Ingoring SSL errors on tunnel proxy connection:" << errors;
m_tunnelProxySocketServer->ignoreSslErrors();
} else {
qCWarning(dcTunnelProxyServer()) << "The remote proxy connection failed due to SSL errors:" << errors;
}
} }
void TunnelProxyServer::onClientConnected(TunnelProxySocket *tunnelProxySocket) void TunnelProxyServer::onClientConnected(TunnelProxySocket *tunnelProxySocket)

View File

@ -47,7 +47,7 @@ class TunnelProxyServer : public TransportInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const ServerConfiguration &configuration, QObject *parent = nullptr); explicit TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const TunnelProxyServerConfiguration &configuration, QObject *parent = nullptr);
~TunnelProxyServer() override; ~TunnelProxyServer() override;
void sendData(const QUuid &clientId, const QByteArray &data) override; void sendData(const QUuid &clientId, const QByteArray &data) override;
@ -74,6 +74,7 @@ private slots:
void onClientDisconnected(TunnelProxySocket *tunnelProxySocket); void onClientDisconnected(TunnelProxySocket *tunnelProxySocket);
private: private:
TunnelProxyServerConfiguration m_config;
TunnelProxySocketServer *m_tunnelProxySocketServer = nullptr; TunnelProxySocketServer *m_tunnelProxySocketServer = nullptr;
QString m_serverName; QString m_serverName;
QUuid m_serverUuid; QUuid m_serverUuid;

View File

@ -129,7 +129,7 @@ WebServer::~WebServer()
/*! Returns the server URL of this WebServer. */ /*! Returns the server URL of this WebServer. */
QUrl WebServer::serverUrl() const QUrl WebServer::serverUrl() const
{ {
return QUrl(QString("%1://%2:%3").arg((m_configuration.sslEnabled ? "https" : "http")).arg(m_configuration.address.toString()).arg(m_configuration.port)); return QUrl(QString("%1://%2:%3").arg((m_configuration.sslEnabled ? "https" : "http")).arg(m_configuration.address).arg(m_configuration.port));
} }
/*! Send the given \a reply map to the corresponding client. /*! Send the given \a reply map to the corresponding client.
@ -561,7 +561,7 @@ void WebServer::setServerName(const QString &serverName)
/*! 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_configuration.address, static_cast<quint16>(m_configuration.port))) { if (!listen(QHostAddress(m_configuration.address), static_cast<quint16>(m_configuration.port))) {
qCWarning(dcWebServer()) << "Webserver could not listen on" << serverUrl().toString() << errorString(); qCWarning(dcWebServer()) << "Webserver could not listen on" << serverUrl().toString() << errorString();
m_enabled = false; m_enabled = false;
return false; return false;
@ -712,7 +712,7 @@ QByteArray WebServer::createServerXmlDocument(QHostAddress address)
int counter = 1; int counter = 1;
int sslCounter = 1; int sslCounter = 1;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) { foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) {
if (config.address == QHostAddress("0.0.0.0") || config.address == address) { if (QHostAddress(config.address) == QHostAddress("0.0.0.0") || QHostAddress(config.address) == address) {
writer.writeStartElement("service"); writer.writeStartElement("service");
writer.writeTextElement("serviceType", QString("urn:nymea.io:service:%1:%2").arg(config.sslEnabled ? "wss" : "ws").arg(config.sslEnabled ? sslCounter : counter)); writer.writeTextElement("serviceType", QString("urn:nymea.io:service:%1:%2").arg(config.sslEnabled ? "wss" : "ws").arg(config.sslEnabled ? sslCounter : counter));
writer.writeTextElement("serviceId", QString("urn:nymea.io:serviceId:%1:%2").arg(config.sslEnabled ? "wss" : "ws").arg(config.sslEnabled ? sslCounter++ : counter++)); writer.writeTextElement("serviceId", QString("urn:nymea.io:serviceId:%1:%2").arg(config.sslEnabled ? "wss" : "ws").arg(config.sslEnabled ? sslCounter++ : counter++));
@ -725,7 +725,7 @@ QByteArray WebServer::createServerXmlDocument(QHostAddress address)
counter = 1; counter = 1;
sslCounter = 1; sslCounter = 1;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) { foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) {
if (config.address == QHostAddress("0.0.0.0") || config.address == address) { if (QHostAddress(config.address) == QHostAddress("0.0.0.0") || QHostAddress(config.address) == address) {
writer.writeStartElement("service"); writer.writeStartElement("service");
writer.writeTextElement("serviceType", QString("urn:nymea.io:service:%1:%2").arg(config.sslEnabled ? "nymeas" : "nymea").arg(config.sslEnabled ? sslCounter : counter)); writer.writeTextElement("serviceType", QString("urn:nymea.io:service:%1:%2").arg(config.sslEnabled ? "nymeas" : "nymea").arg(config.sslEnabled ? sslCounter : counter));
writer.writeTextElement("serviceId", QString("urn:nymea.io:serviceId:%1:%2").arg(config.sslEnabled ? "nymeas" : "nymea").arg(config.sslEnabled ? sslCounter++ : counter++)); writer.writeTextElement("serviceId", QString("urn:nymea.io:serviceId:%1:%2").arg(config.sslEnabled ? "nymeas" : "nymea").arg(config.sslEnabled ? sslCounter++ : counter++));

View File

@ -87,7 +87,7 @@ WebSocketServer::~WebSocketServer()
/*! Returns the url of this server. */ /*! Returns the url of this server. */
QUrl WebSocketServer::serverUrl() const QUrl WebSocketServer::serverUrl() const
{ {
return QUrl(QString("%1://%2:%3").arg((configuration().sslEnabled ? "wss" : "ws")).arg(configuration().address.toString()).arg(configuration().port)); return QUrl(QString("%1://%2:%3").arg((configuration().sslEnabled ? "wss" : "ws")).arg(configuration().address).arg(configuration().port));
} }
/*! Send the given \a data map to the client with the given \a clientId. /*! Send the given \a data map to the client with the given \a clientId.
@ -219,7 +219,7 @@ 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(configuration().address, static_cast<quint16>(configuration().port))) { if (!m_server->listen(QHostAddress(configuration().address), static_cast<quint16>(configuration().port))) {
qCWarning(dcWebSocketServer()) << "Error listening on" << serverUrl().toString(); qCWarning(dcWebSocketServer()) << "Error listening on" << serverUrl().toString();
return false; return false;
} }

View File

@ -471,6 +471,16 @@
"configurationError": "$ref:ConfigurationError" "configurationError": "$ref:ConfigurationError"
} }
}, },
"Configuration.DeleteTunnelProxyServerConfiguration": {
"description": "Delete a Tunnel Proxy 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"
},
"permissionScope": "PermissionScopeAdmin",
"returns": {
"configurationError": "$ref:ConfigurationError"
}
},
"Configuration.DeleteWebServerConfiguration": { "Configuration.DeleteWebServerConfiguration": {
"description": "Delete a WebServer interface of the server.", "description": "Delete a WebServer interface of the server.",
"params": { "params": {
@ -507,7 +517,7 @@
"description": "Get all configuration parameters of the server.", "description": "Get all configuration parameters of the server.",
"params": { "params": {
}, },
"permissionScope": "PermissionScopeAdmin", "permissionScope": "PermissionScopeNone",
"returns": { "returns": {
"basicConfiguration": { "basicConfiguration": {
"d:language": "String", "d:language": "String",
@ -523,6 +533,9 @@
"tcpServerConfigurations": [ "tcpServerConfigurations": [
"$ref:ServerConfiguration" "$ref:ServerConfiguration"
], ],
"tunnelProxyServerConfigurations": [
"$ref:TunnelProxyServerConfiguration"
],
"webServerConfigurations": [ "webServerConfigurations": [
"$ref:WebServerConfiguration" "$ref:WebServerConfiguration"
], ],
@ -647,6 +660,16 @@
"configurationError": "$ref:ConfigurationError" "configurationError": "$ref:ConfigurationError"
} }
}, },
"Configuration.SetTunnelProxyServerConfiguration": {
"description": "Configure a Tunnel Proxy 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": {
"configuration": "$ref:TunnelProxyServerConfiguration"
},
"permissionScope": "PermissionScopeAdmin",
"returns": {
"configurationError": "$ref:ConfigurationError"
}
},
"Configuration.SetWebServerConfiguration": { "Configuration.SetWebServerConfiguration": {
"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.", "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": {
@ -2043,6 +2066,18 @@
"id": "String" "id": "String"
} }
}, },
"Configuration.TunnelProxyServerConfigurationChanged": {
"description": "Emitted whenever the tunnel proxy server configuration changes.",
"params": {
"tunnelProxyServerConfiguration": "$ref:TunnelProxyServerConfiguration"
}
},
"Configuration.TunnelProxyServerConfigurationRemoved": {
"description": "Emitted whenever a tunnel proxy server configuration is removed.",
"params": {
"id": "String"
}
},
"Configuration.WebServerConfigurationChanged": { "Configuration.WebServerConfigurationChanged": {
"description": "Emitted whenever the web server configuration changes.", "description": "Emitted whenever the web server configuration changes.",
"params": { "params": {
@ -2830,6 +2865,14 @@
"TokenInfoList": [ "TokenInfoList": [
"$ref:TokenInfo" "$ref:TokenInfo"
], ],
"TunnelProxyServerConfiguration": {
"address": "String",
"authenticationEnabled": "Bool",
"id": "String",
"ignoreSslErrors": "Bool",
"port": "Uint",
"sslEnabled": "Bool"
},
"UserInfo": { "UserInfo": {
"r:displayName": "String", "r:displayName": "String",
"r:email": "String", "r:email": "String",

View File

@ -278,7 +278,7 @@ void TestConfigurations::testDebugServerConfiguration()
qCDebug(dcTests()) << "TestWebserver starting"; qCDebug(dcTests()) << "TestWebserver starting";
foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) {
if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { if (config.port == 3333 && (QHostAddress(config.address) == QHostAddress("127.0.0.1") || QHostAddress(config.address) == QHostAddress("0.0.0.0"))) {
qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; qDebug() << "Already have a webserver listening on 127.0.0.1:3333";
return; return;
} }
@ -287,7 +287,7 @@ void TestConfigurations::testDebugServerConfiguration()
qCDebug(dcTests) << "Creating new webserver instance on 127.0.0.1:3333"; qCDebug(dcTests) << "Creating new webserver instance on 127.0.0.1:3333";
WebServerConfiguration config; WebServerConfiguration config;
config.id = "Testwebserver for debug server interface"; config.id = "Testwebserver for debug server interface";
config.address = QHostAddress("127.0.0.1"); config.address = "127.0.0.1";
config.port = 3333; config.port = 3333;
config.sslEnabled = true; config.sslEnabled = true;
NymeaCore::instance()->configuration()->setWebServerConfiguration(config); NymeaCore::instance()->configuration()->setWebServerConfiguration(config);

View File

@ -61,8 +61,7 @@ private slots:
void TestMqttBroker::initTestCase() void TestMqttBroker::initTestCase()
{ {
NymeaTestBase::initTestCase(); NymeaTestBase::initTestCase("*.debug=false\nnymea.mqtt*.debug=true\nMqtt.debug=true\nJsonRpc.debug=true");
QLoggingCategory::setFilterRules("*.debug=false\nnymea.mqtt*.debug=true\nMqtt.debug=true\nJsonRpc.debug=true");
} }
void TestMqttBroker::testServerConfigurationAPI() void TestMqttBroker::testServerConfigurationAPI()

View File

@ -79,7 +79,7 @@ void TestWebserver::initTestCase()
qDebug() << "TestWebserver starting"; qDebug() << "TestWebserver starting";
foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) {
if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { if (config.port == 3333 && (QHostAddress(config.address) == QHostAddress("127.0.0.1") || QHostAddress(config.address) == QHostAddress("0.0.0.0"))) {
qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; qDebug() << "Already have a webserver listening on 127.0.0.1:3333";
return; return;
} }
@ -87,7 +87,7 @@ void TestWebserver::initTestCase()
qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; qDebug() << "Creating new webserver instance on 127.0.0.1:3333";
WebServerConfiguration config; WebServerConfiguration config;
config.address = QHostAddress("127.0.0.1"); config.address = "127.0.0.1";
config.port = 3333; config.port = 3333;
config.sslEnabled = true; config.sslEnabled = true;
config.restServerEnabled = true; config.restServerEnabled = true;
@ -215,7 +215,7 @@ void TestWebserver::checkAllowedMethodCall()
QFETCH(int, expectedStatusCode); QFETCH(int, expectedStatusCode);
QNetworkAccessManager nam; QNetworkAccessManager nam;
connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply* reply, const QList<QSslError> &) { connect(&nam, &QNetworkAccessManager::sslErrors, [](QNetworkReply* reply, const QList<QSslError> &) {
reply->ignoreSslErrors(); reply->ignoreSslErrors();
}); });
QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*)));

View File

@ -72,7 +72,7 @@ void TestWebSocketServer::initTestCase()
ServerConfiguration config; ServerConfiguration config;
foreach (const ServerConfiguration &c, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) { foreach (const ServerConfiguration &c, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) {
if (c.port == 4444 && (c.address == QHostAddress("127.0.0.1") || c.address == QHostAddress("0.0.0.0"))) { if (c.port == 4444 && (QHostAddress(c.address) == QHostAddress("127.0.0.1") || QHostAddress(c.address) == QHostAddress("0.0.0.0"))) {
qDebug() << "Already have a websocketserver listening on 127.0.0.1:4444"; qDebug() << "Already have a websocketserver listening on 127.0.0.1:4444";
config = c; config = c;
break; break;
@ -80,7 +80,7 @@ void TestWebSocketServer::initTestCase()
} }
qDebug() << "Creating new websocketserver instance on 127.0.0.1:4444"; qDebug() << "Creating new websocketserver instance on 127.0.0.1:4444";
config.address = QHostAddress("127.0.0.1"); config.address = "127.0.0.1";
config.port = 4444; config.port = 4444;
config.sslEnabled = true; config.sslEnabled = true;
config.authenticationEnabled = true; config.authenticationEnabled = true;