Merge PR #455: Add tunnel proxy server for new remote connection mechanism
This commit is contained in:
commit
37738bb022
@ -40,7 +40,7 @@ namespace nymeaserver {
|
||||
CloudTransport::CloudTransport(const ServerConfiguration &config, QObject *parent):
|
||||
TransportInterface(config, parent)
|
||||
{
|
||||
m_defaultProxyUrl = "wss://remoteproxy.nymea.io";
|
||||
m_defaultProxyUrl = "ssl://remoteproxy.nymea.io:4433";
|
||||
}
|
||||
|
||||
void CloudTransport::sendData(const QUuid &clientId, const QByteArray &data)
|
||||
@ -48,7 +48,7 @@ void CloudTransport::sendData(const QUuid &clientId, const QByteArray &data)
|
||||
qCDebug(dcCloudTraffic()) << "Sending data" << clientId << data;
|
||||
foreach (const ConnectionContext &ctx, m_connections) {
|
||||
if (ctx.clientId == clientId) {
|
||||
ctx.proxyConnection->sendData(data);
|
||||
ctx.proxyConnection->sendData(data + '\n');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -89,12 +89,18 @@ void CloudTransport::connectToCloud(const QString &token, const QString &nonce,
|
||||
QString proxyUrl = serverUrl.isEmpty() ? m_defaultProxyUrl : serverUrl;
|
||||
qCDebug(dcCloud()) << "Connecting to remote proxy server" << proxyUrl;
|
||||
|
||||
RemoteProxyConnection::ConnectionType connectionType = RemoteProxyConnection::ConnectionTypeTcpSocket;
|
||||
QUrl url(proxyUrl);
|
||||
if (url.scheme() == "wss" || url.scheme() == "ws") {
|
||||
connectionType = RemoteProxyConnection::ConnectionTypeWebSocket;
|
||||
}
|
||||
|
||||
ConnectionContext context;
|
||||
context.clientId = QUuid::createUuid();
|
||||
context.token = token;
|
||||
context.nonce = nonce;
|
||||
QString identifier = QString("nymea:core (%1)").arg(NymeaCore::instance()->configuration()->serverName());
|
||||
context.proxyConnection = new RemoteProxyConnection(NymeaCore::instance()->configuration()->serverUuid().toString(), identifier, this);
|
||||
context.proxyConnection = new RemoteProxyConnection(NymeaCore::instance()->configuration()->serverUuid().toString(), identifier, connectionType, this);
|
||||
m_connections.insert(context.proxyConnection, context);
|
||||
|
||||
connect(context.proxyConnection, &RemoteProxyConnection::ready, this, &CloudTransport::transportReady);
|
||||
@ -103,7 +109,7 @@ void CloudTransport::connectToCloud(const QString &token, const QString &nonce,
|
||||
connect(context.proxyConnection, &RemoteProxyConnection::remoteConnectionEstablished, this, &CloudTransport::transportConnected);
|
||||
connect(context.proxyConnection, &RemoteProxyConnection::disconnected, this, &CloudTransport::transportDisconnected);
|
||||
|
||||
context.proxyConnection->connectServer(QUrl(proxyUrl));
|
||||
context.proxyConnection->connectServer(url);
|
||||
}
|
||||
|
||||
void CloudTransport::remoteConnectionStateChanged(RemoteProxyConnection::State state)
|
||||
|
||||
@ -79,7 +79,7 @@ ModbusRtuMasterImpl::ModbusRtuMasterImpl(const QUuid &modbusUuid, const QString
|
||||
});
|
||||
|
||||
connect(m_modbus, &QModbusRtuSerialMaster::errorOccurred, this, [=](QModbusDevice::Error error){
|
||||
qCWarning(dcModbusRtu()) << "Error occured for modbus RTU master" << m_modbusUuid.toString() << m_serialPort << error << m_modbus->errorString();
|
||||
qCWarning(dcModbusRtu()) << "Error occurred for modbus RTU master" << m_modbusUuid.toString() << m_serialPort << error << m_modbus->errorString();
|
||||
if (error != QModbusDevice::NoError) {
|
||||
disconnectDevice();
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ MqttChannel *MqttProviderImplementation::createChannel(const QString &clientId,
|
||||
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
||||
if (clientAddress.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) {
|
||||
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_serverPort = config.port;
|
||||
break;
|
||||
@ -145,9 +145,9 @@ MqttClient *MqttProviderImplementation::createInternalClient(const QString &clie
|
||||
|
||||
ServerConfiguration preferredConfig;
|
||||
foreach (const ServerConfiguration &config, m_broker->configurations()) {
|
||||
if (config.address == QHostAddress::Any
|
||||
|| config.address == QHostAddress::AnyIPv4
|
||||
|| config.address == QHostAddress::LocalHost) {
|
||||
if (QHostAddress(config.address) == QHostAddress::Any
|
||||
|| QHostAddress(config.address) == QHostAddress::AnyIPv4
|
||||
|| QHostAddress(config.address) == QHostAddress::LocalHost) {
|
||||
preferredConfig = config;
|
||||
break;
|
||||
}
|
||||
@ -176,12 +176,12 @@ MqttClient *MqttProviderImplementation::createInternalClient(const QString &clie
|
||||
m_broker->removePolicy(clientId);
|
||||
});
|
||||
|
||||
if (preferredConfig.address == QHostAddress::Any
|
||||
|| preferredConfig.address == QHostAddress::AnyIPv4
|
||||
|| preferredConfig.address == QHostAddress::LocalHost) {
|
||||
if (QHostAddress(preferredConfig.address) == QHostAddress::Any
|
||||
|| QHostAddress(preferredConfig.address) == QHostAddress::AnyIPv4
|
||||
|| QHostAddress(preferredConfig.address) == QHostAddress::LocalHost) {
|
||||
client->connectToHost("127.0.0.1", preferredConfig.port);
|
||||
} else {
|
||||
client->connectToHost(preferredConfig.address.toString(), preferredConfig.port);
|
||||
client->connectToHost(preferredConfig.address, preferredConfig.port);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
@ -86,6 +86,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
// Objects
|
||||
registerObject<ServerConfiguration>();
|
||||
registerObject<WebServerConfiguration>();
|
||||
registerObject<TunnelProxyServerConfiguration>();
|
||||
registerObject<MqttPolicy>();
|
||||
|
||||
// Methods
|
||||
@ -118,12 +119,15 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
QVariantList webSocketServerConfigurations;
|
||||
webSocketServerConfigurations.append(objectRef<ServerConfiguration>());
|
||||
returns.insert("webSocketServerConfigurations", webSocketServerConfigurations);
|
||||
QVariantList tunnelProxyServerConfigurations;
|
||||
tunnelProxyServerConfigurations.append(objectRef<TunnelProxyServerConfiguration>());
|
||||
returns.insert("tunnelProxyServerConfigurations", tunnelProxyServerConfigurations);
|
||||
QVariantList mqttServerConfigurations;
|
||||
mqttServerConfigurations.append(objectRef<ServerConfiguration>());
|
||||
QVariantMap cloudConfiguration;
|
||||
cloudConfiguration.insert("enabled", enumValueName(Bool));
|
||||
returns.insert("cloud", cloudConfiguration);
|
||||
registerMethod("GetConfigurations", description, params, returns);
|
||||
registerMethod("GetConfigurations", description, params, returns, Types::PermissionScopeNone);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Set the name of the server. Default is nymea.";
|
||||
@ -173,6 +177,18 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
|
||||
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();
|
||||
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>());
|
||||
@ -257,6 +273,16 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
params.insert("id", enumValueName(String));
|
||||
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();
|
||||
description = "Emitted whenever the MQTT broker configuration is changed.";
|
||||
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::webSocketServerConfigurationChanged, this, &ConfigurationHandler::onWebSocketServerConfigurationChanged);
|
||||
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::mqttServerConfigurationRemoved, this, &ConfigurationHandler::onMqttServerConfigurationRemoved);
|
||||
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::mqttPolicyChanged, this, &ConfigurationHandler::onMqttPolicyChanged);
|
||||
@ -340,6 +368,12 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap ¶ms) co
|
||||
}
|
||||
returns.insert("webSocketServerConfigurations", webSocketServerConfigs);
|
||||
|
||||
QVariantList tunnelProxyServerConfigs;
|
||||
foreach (const TunnelProxyServerConfiguration &config, NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations()) {
|
||||
tunnelProxyServerConfigs.append(pack(config));
|
||||
}
|
||||
returns.insert("tunnelProxyServerConfigurations", tunnelProxyServerConfigs);
|
||||
|
||||
QVariantMap cloudConfig;
|
||||
cloudConfig.insert("enabled", NymeaCore::instance()->configuration()->cloudEnabled());
|
||||
returns.insert("cloud", cloudConfig);
|
||||
@ -422,7 +456,7 @@ JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &pa
|
||||
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);
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
|
||||
@ -453,7 +487,7 @@ JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &pa
|
||||
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);
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
|
||||
@ -483,7 +517,7 @@ JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantM
|
||||
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);
|
||||
|
||||
@ -500,6 +534,37 @@ JsonReply *ConfigurationHandler::DeleteWebSocketServerConfiguration(const QVaria
|
||||
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
|
||||
}
|
||||
|
||||
JsonReply *ConfigurationHandler::SetTunnelProxyServerConfiguration(const QVariantMap ¶ms) 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 ¶ms) 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 ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
@ -526,7 +591,7 @@ JsonReply *ConfigurationHandler::SetMqttServerConfiguration(const QVariantMap &p
|
||||
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);
|
||||
|
||||
@ -639,6 +704,22 @@ void ConfigurationHandler::onWebSocketServerConfigurationRemoved(const QString &
|
||||
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)
|
||||
{
|
||||
qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed";
|
||||
|
||||
@ -60,6 +60,8 @@ public:
|
||||
Q_INVOKABLE JsonReply *DeleteWebServerConfiguration(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *SetWebSocketServerConfiguration(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *DeleteWebSocketServerConfiguration(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *SetTunnelProxyServerConfiguration(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *DeleteTunnelProxyServerConfiguration(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE JsonReply *GetMqttServerConfigurations(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *SetMqttServerConfiguration(const QVariantMap ¶ms) const;
|
||||
@ -79,6 +81,8 @@ signals:
|
||||
void WebServerConfigurationRemoved(const QVariantMap ¶ms);
|
||||
void WebSocketServerConfigurationChanged(const QVariantMap ¶ms);
|
||||
void WebSocketServerConfigurationRemoved(const QVariantMap ¶ms);
|
||||
void TunnelProxyServerConfigurationChanged(const QVariantMap ¶ms);
|
||||
void TunnelProxyServerConfigurationRemoved(const QVariantMap ¶ms);
|
||||
|
||||
void MqttServerConfigurationChanged(const QVariantMap ¶ms);
|
||||
void MqttServerConfigurationRemoved(const QVariantMap ¶ms);
|
||||
@ -95,6 +99,8 @@ private slots:
|
||||
void onWebServerConfigurationRemoved(const QString &id);
|
||||
void onWebSocketServerConfigurationChanged(const QString &id);
|
||||
void onWebSocketServerConfigurationRemoved(const QString &id);
|
||||
void onTunnelProxyServerConfigurationChanged(const QString &id);
|
||||
void onTunnelProxyServerConfigurationRemoved(const QString &id);
|
||||
void onMqttServerConfigurationChanged(const QString &id);
|
||||
void onMqttServerConfigurationRemoved(const QString &id);
|
||||
void onMqttPolicyChanged(const QString &clientId);
|
||||
|
||||
@ -100,6 +100,7 @@ HEADERS += nymeacore.h \
|
||||
servers/bluetoothserver.h \
|
||||
servers/websocketserver.h \
|
||||
servers/mqttbroker.h \
|
||||
servers/tunnelproxyserver.h \
|
||||
jsonrpc/jsonrpcserverimplementation.h \
|
||||
jsonrpc/jsonvalidator.h \
|
||||
jsonrpc/integrationshandler.h \
|
||||
@ -191,6 +192,7 @@ SOURCES += nymeacore.cpp \
|
||||
servers/websocketserver.cpp \
|
||||
servers/bluetoothserver.cpp \
|
||||
servers/mqttbroker.cpp \
|
||||
servers/tunnelproxyserver.cpp \
|
||||
jsonrpc/jsonrpcserverimplementation.cpp \
|
||||
jsonrpc/jsonvalidator.cpp \
|
||||
jsonrpc/integrationshandler.cpp \
|
||||
|
||||
@ -93,7 +93,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
|
||||
qCWarning(dcConfiguration) << "No TCP server configuration found. Generating default of nymeas://0.0.0.0:2222";
|
||||
ServerConfiguration config;
|
||||
config.id = "default";
|
||||
config.address = QHostAddress("0.0.0.0");
|
||||
config.address = QHostAddress("0.0.0.0").toString();
|
||||
config.port = 2222;
|
||||
config.sslEnabled = 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";
|
||||
WebServerConfiguration insecureConfig;
|
||||
insecureConfig.id = "insecure";
|
||||
insecureConfig.address = QHostAddress("0.0.0.0");
|
||||
insecureConfig.address = QHostAddress("0.0.0.0").toString();
|
||||
insecureConfig.port = 80;
|
||||
insecureConfig.sslEnabled = false;
|
||||
insecureConfig.authenticationEnabled = false;
|
||||
@ -132,7 +132,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
|
||||
|
||||
WebServerConfiguration secureConfig;
|
||||
secureConfig.id = "secure";
|
||||
secureConfig.address = QHostAddress("0.0.0.0");
|
||||
secureConfig.address = QHostAddress("0.0.0.0").toString();
|
||||
secureConfig.port = 443;
|
||||
secureConfig.sslEnabled = true;
|
||||
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";
|
||||
ServerConfiguration config;
|
||||
config.id = "default";
|
||||
config.address = QHostAddress("0.0.0.0");
|
||||
config.address = QHostAddress("0.0.0.0").toString();
|
||||
config.port = 4444;
|
||||
config.sslEnabled = 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";
|
||||
ServerConfiguration config;
|
||||
config.id = "default";
|
||||
config.address = QHostAddress("0.0.0.0");
|
||||
config.address = QHostAddress("0.0.0.0").toString();
|
||||
config.port = 1883;
|
||||
config.sslEnabled = false;
|
||||
config.authenticationEnabled = true;
|
||||
@ -211,6 +211,16 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
|
||||
mqttPolicies.endGroup();
|
||||
}
|
||||
|
||||
// Tunnel Proxy Server
|
||||
if (settings.childGroups().contains("TunnelProxyServer")) {
|
||||
settings.beginGroup("TunnelProxyServer");
|
||||
foreach (const QString &key, settings.childGroups()) {
|
||||
TunnelProxyServerConfiguration config = readTunnelProxyServerConfig(key);
|
||||
m_tunnelProxyServerConfigs[config.id] = config;
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
// Write defaults for log settings
|
||||
settings.beginGroup("Logs");
|
||||
settings.setValue("logDBDriver", logDBDriver());
|
||||
@ -366,6 +376,25 @@ void NymeaConfiguration::removeWebSocketServerConfiguration(const QString &id)
|
||||
emit webSocketServerConfigurationRemoved(id);
|
||||
}
|
||||
|
||||
QHash<QString, TunnelProxyServerConfiguration> NymeaConfiguration::tunnelProxyServerConfigurations() const
|
||||
{
|
||||
return m_tunnelProxyServerConfigs;
|
||||
}
|
||||
|
||||
void NymeaConfiguration::setTunnelProxyServerConfiguration(const TunnelProxyServerConfiguration &config)
|
||||
{
|
||||
m_tunnelProxyServerConfigs[config.id] = config;
|
||||
storeTunnelProxyServerConfig(config);
|
||||
emit tunnelProxyServerConfigurationChanged(config.id);
|
||||
}
|
||||
|
||||
void NymeaConfiguration::removeTunnelProxyServerConfiguration(const QString &id)
|
||||
{
|
||||
m_tunnelProxyServerConfigs.take(id);
|
||||
deleteServerConfig("TunnelProxyServer", id);
|
||||
emit tunnelProxyServerConfigurationRemoved(id);
|
||||
}
|
||||
|
||||
QHash<QString, ServerConfiguration> NymeaConfiguration::mqttServerConfigurations() const
|
||||
{
|
||||
return m_mqttServerConfigs;
|
||||
@ -627,7 +656,7 @@ void NymeaConfiguration::storeServerConfig(const QString &group, const ServerCon
|
||||
settings.beginGroup(group);
|
||||
settings.remove("disabled");
|
||||
settings.beginGroup(config.id);
|
||||
settings.setValue("address", config.address.toString());
|
||||
settings.setValue("address", config.address);
|
||||
settings.setValue("port", config.port);
|
||||
settings.setValue("sslEnabled", config.sslEnabled);
|
||||
settings.setValue("authenticationEnabled", config.authenticationEnabled);
|
||||
@ -642,7 +671,7 @@ ServerConfiguration NymeaConfiguration::readServerConfig(const QString &group, c
|
||||
settings.beginGroup(group);
|
||||
settings.beginGroup(id);
|
||||
config.id = id;
|
||||
config.address = QHostAddress(settings.value("address").toString());
|
||||
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();
|
||||
@ -681,7 +710,7 @@ WebServerConfiguration NymeaConfiguration::readWebServerConfig(const QString &id
|
||||
settings.beginGroup("WebServer");
|
||||
settings.beginGroup(id);
|
||||
config.id = id;
|
||||
config.address = QHostAddress(settings.value("address").toString());
|
||||
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();
|
||||
@ -692,6 +721,34 @@ WebServerConfiguration NymeaConfiguration::readWebServerConfig(const QString &id
|
||||
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)
|
||||
{
|
||||
NymeaSettings settings(NymeaSettings::SettingsRoleMqttPolicies);
|
||||
@ -713,9 +770,32 @@ QDebug operator <<(QDebug debug, const ServerConfiguration &configuration)
|
||||
{
|
||||
debug.nospace() << "ServerConfiguration(" << configuration.address;
|
||||
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() << ") ";
|
||||
return debug;
|
||||
return debug.maybeSpace();
|
||||
}
|
||||
|
||||
QDebug operator <<(QDebug debug, const TunnelProxyServerConfiguration &configuration)
|
||||
{
|
||||
debug.nospace() << "TunnelProxyServerConfiguration(" << configuration.id;
|
||||
debug.nospace() << ", " << QString("%1:%2").arg(configuration.address).arg(configuration.port);
|
||||
if (configuration.sslEnabled) {
|
||||
debug.nospace() << ", SSL enabled";
|
||||
} else {
|
||||
debug.nospace() << ", SSL disabled";
|
||||
}
|
||||
if (configuration.authenticationEnabled) {
|
||||
debug.nospace() << ", Authentication enabled";
|
||||
} else {
|
||||
debug.nospace() << ", Authentication disabled";
|
||||
}
|
||||
|
||||
if (configuration.ignoreSslErrors) {
|
||||
debug.nospace() << ", Ignoring SSL errors";
|
||||
}
|
||||
|
||||
debug.nospace() << ") ";
|
||||
return debug.maybeSpace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -42,15 +42,15 @@ namespace nymeaserver {
|
||||
class ServerConfiguration {
|
||||
Q_GADGET
|
||||
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(bool sslEnabled MEMBER sslEnabled)
|
||||
Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled)
|
||||
|
||||
public:
|
||||
QString id;
|
||||
QHostAddress address;
|
||||
QString addressString() { return address.toString(); }
|
||||
void setAddress(const QString &addressString) {address = QHostAddress(addressString); }
|
||||
QString address;
|
||||
void setAddress(const QString &address) {this->address = address; }
|
||||
uint port = 0;
|
||||
bool sslEnabled = true;
|
||||
bool authenticationEnabled = true;
|
||||
@ -70,11 +70,34 @@ class WebServerConfiguration: public ServerConfiguration
|
||||
{
|
||||
Q_GADGET
|
||||
Q_PROPERTY(QString publicFolder MEMBER publicFolder)
|
||||
|
||||
public:
|
||||
QString publicFolder;
|
||||
bool restServerEnabled = false;
|
||||
|
||||
bool operator==(const WebServerConfiguration &other) const {
|
||||
return ServerConfiguration::operator==(other)
|
||||
&& publicFolder == other.publicFolder
|
||||
&& restServerEnabled == other.restServerEnabled;
|
||||
}
|
||||
};
|
||||
|
||||
class TunnelProxyServerConfiguration: public ServerConfiguration
|
||||
{
|
||||
Q_GADGET
|
||||
Q_PROPERTY(bool ignoreSslErrors MEMBER ignoreSslErrors)
|
||||
|
||||
public:
|
||||
bool ignoreSslErrors = false;
|
||||
|
||||
bool operator==(const TunnelProxyServerConfiguration &other) const {
|
||||
return ServerConfiguration::operator==(other)
|
||||
&& ignoreSslErrors == other.ignoreSslErrors;
|
||||
}
|
||||
};
|
||||
|
||||
QDebug operator <<(QDebug debug, const TunnelProxyServerConfiguration &configuration);
|
||||
|
||||
class MqttPolicy
|
||||
{
|
||||
Q_GADGET
|
||||
@ -147,6 +170,11 @@ public:
|
||||
void setWebSocketServerConfiguration(const ServerConfiguration &config);
|
||||
void removeWebSocketServerConfiguration(const QString &id);
|
||||
|
||||
// Tunnel proxy server
|
||||
QHash<QString, TunnelProxyServerConfiguration> tunnelProxyServerConfigurations() const;
|
||||
void setTunnelProxyServerConfiguration(const TunnelProxyServerConfiguration &config);
|
||||
void removeTunnelProxyServerConfiguration(const QString &id);
|
||||
|
||||
// MQTT
|
||||
QHash<QString, ServerConfiguration> mqttServerConfigurations() const;
|
||||
void setMqttServerConfiguration(const ServerConfiguration &config);
|
||||
@ -187,6 +215,7 @@ private:
|
||||
QHash<QString, ServerConfiguration> m_webSocketServerConfigs;
|
||||
QHash<QString, ServerConfiguration> m_mqttServerConfigs;
|
||||
QHash<QString, MqttPolicy> m_mqttPolicies;
|
||||
QHash<QString, TunnelProxyServerConfiguration> m_tunnelProxyServerConfigs;
|
||||
|
||||
void setServerUuid(const QUuid &uuid);
|
||||
void setWebServerPublicFolder(const QString & path);
|
||||
@ -198,6 +227,8 @@ private:
|
||||
void deleteServerConfig(const QString &group, const QString &id);
|
||||
void storeWebServerConfig(const WebServerConfiguration &config);
|
||||
WebServerConfiguration readWebServerConfig(const QString &id);
|
||||
void storeTunnelProxyServerConfig(const TunnelProxyServerConfiguration &config);
|
||||
TunnelProxyServerConfiguration readTunnelProxyServerConfig(const QString &id);
|
||||
|
||||
void storeMqttPolicy(const MqttPolicy &policy);
|
||||
MqttPolicy readMqttPolicy(const QString &clientId);
|
||||
@ -216,6 +247,8 @@ signals:
|
||||
void webSocketServerConfigurationRemoved(const QString &configId);
|
||||
void mqttServerConfigurationChanged(const QString &configId);
|
||||
void mqttServerConfigurationRemoved(const QString &configId);
|
||||
void tunnelProxyServerConfigurationChanged(const QString &configId);
|
||||
void tunnelProxyServerConfigurationRemoved(const QString &configId);
|
||||
|
||||
void mqttPolicyChanged(const QString &clientId);
|
||||
void mqttPolicyRemoved(const QString &clientId);
|
||||
|
||||
@ -57,6 +57,7 @@
|
||||
#include "servers/webserver.h"
|
||||
#include "servers/bluetoothserver.h"
|
||||
#include "servers/mqttbroker.h"
|
||||
#include "servers/tunnelproxyserver.h"
|
||||
|
||||
#include "network/zeroconf/zeroconfservicepublisher.h"
|
||||
|
||||
@ -69,6 +70,7 @@ namespace nymeaserver {
|
||||
ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configuration, const QStringList &additionalInterfaces, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_platform(platform),
|
||||
m_nymeaConfiguration(configuration),
|
||||
m_sslConfiguration(QSslConfiguration())
|
||||
{
|
||||
if (!QSslSocket::supportsSsl()) {
|
||||
@ -119,7 +121,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
|
||||
QUrl additionalInterface(interfaceString);
|
||||
ServerConfiguration config;
|
||||
config.id = "tmp-" + additionalInterface.host();
|
||||
config.address = QHostAddress(additionalInterface.host());
|
||||
config.address = additionalInterface.host();
|
||||
config.port = additionalInterface.port();
|
||||
TransportInterface *server = nullptr;
|
||||
QString serverType, serviceType;
|
||||
@ -165,6 +167,25 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
|
||||
m_bluetoothServer->startServer();
|
||||
}
|
||||
|
||||
foreach (const TunnelProxyServerConfiguration &config, configuration->tunnelProxyServerConfigurations()) {
|
||||
TunnelProxyServer *tunnelProxyServer = new TunnelProxyServer(configuration->serverName(), configuration->serverUuid(), config, this);
|
||||
qCDebug(dcServerManager()) << "Creating tunnel proxy server using" << config;
|
||||
m_tunnelProxyServers.insert(config.id, tunnelProxyServer);
|
||||
connect(tunnelProxyServer, &TunnelProxyServer::runningChanged, this, [this, tunnelProxyServer](bool running){
|
||||
if (running) {
|
||||
// Note: enable authentication in any case, we don't want to expose unprotected access trough the internet
|
||||
m_jsonServer->registerTransportInterface(tunnelProxyServer, true);
|
||||
} else {
|
||||
m_jsonServer->unregisterTransportInterface(tunnelProxyServer);
|
||||
}
|
||||
});
|
||||
|
||||
// FIXME: make use of SSL over tunnel proxy connections
|
||||
// FIXME: make sure the authentication is enabled for the tunnel proxy
|
||||
|
||||
tunnelProxyServer->startServer();
|
||||
}
|
||||
|
||||
foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) {
|
||||
WebServer *webServer = new WebServer(config, m_sslConfiguration, this);
|
||||
m_webServers.insert(config.id, webServer);
|
||||
@ -191,6 +212,9 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
|
||||
connect(configuration, &NymeaConfiguration::mqttServerConfigurationRemoved, this, &ServerManager::mqttServerConfigurationRemoved);
|
||||
connect(configuration, &NymeaConfiguration::mqttPolicyChanged, this, &ServerManager::mqttPolicyChanged);
|
||||
connect(configuration, &NymeaConfiguration::mqttPolicyRemoved, this, &ServerManager::mqttPolicyRemoved);
|
||||
connect(configuration, &NymeaConfiguration::tunnelProxyServerConfigurationChanged, this, &ServerManager::tunnelProxyServerConfigurationChanged);
|
||||
connect(configuration, &NymeaConfiguration::tunnelProxyServerConfigurationRemoved, this, &ServerManager::tunnelProxyServerConfigurationRemoved);
|
||||
connect(configuration, &NymeaConfiguration::cloudEnabledChanged, this, &ServerManager::cloudEnabledChanged);
|
||||
}
|
||||
|
||||
/*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */
|
||||
@ -221,12 +245,12 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
|
||||
ServerConfiguration config = NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id);
|
||||
TcpServer *server = m_tcpServers.value(id);
|
||||
if (server) {
|
||||
qDebug(dcServerManager()) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
qCDebug(dcServerManager()) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
unregisterZeroConfService(config.id, "tcp");
|
||||
server->stopServer();
|
||||
server->setConfiguration(config);
|
||||
} else {
|
||||
qDebug(dcServerManager()) << "Received a TCP Server config change event but don't have a TCP Server instance for it. Creating new Server instance.";
|
||||
qCDebug(dcServerManager()) << "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);
|
||||
}
|
||||
@ -239,7 +263,7 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
|
||||
void ServerManager::tcpServerConfigurationRemoved(const QString &id)
|
||||
{
|
||||
if (!m_tcpServers.contains(id)) {
|
||||
qWarning(dcServerManager()) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
|
||||
qCWarning(dcServerManager()) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
|
||||
return;
|
||||
}
|
||||
TcpServer *server = m_tcpServers.take(id);
|
||||
@ -254,12 +278,12 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
|
||||
WebSocketServer *server = m_webSocketServers.value(id);
|
||||
ServerConfiguration config = NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id);
|
||||
if (server) {
|
||||
qDebug(dcServerManager()) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
qCDebug(dcServerManager()) << "Restarting WebSocket server 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 WebSocket Server config change event but don't have a WebSocket Server instance for it. Creating new instance.";
|
||||
qCDebug(dcServerManager()) << "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);
|
||||
}
|
||||
@ -272,7 +296,7 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
|
||||
void ServerManager::webSocketServerConfigurationRemoved(const QString &id)
|
||||
{
|
||||
if (!m_webSocketServers.contains(id)) {
|
||||
qWarning(dcServerManager()) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
|
||||
qCWarning(dcServerManager()) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
|
||||
return;
|
||||
}
|
||||
WebSocketServer *server = m_webSocketServers.take(id);
|
||||
@ -287,12 +311,12 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
|
||||
WebServerConfiguration config = NymeaCore::instance()->configuration()->webServerConfigurations().value(id);
|
||||
WebServer *server = m_webServers.value(id);
|
||||
if (server) {
|
||||
qDebug(dcServerManager()) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
qCDebug(dcServerManager()) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
unregisterZeroConfService(id, "http");
|
||||
server->stopServer();
|
||||
server->setConfiguration(config);
|
||||
} 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 << ")";
|
||||
qCDebug(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);
|
||||
m_webServers.insert(config.id, server);
|
||||
}
|
||||
@ -304,7 +328,7 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
|
||||
void ServerManager::webServerConfigurationRemoved(const QString &id)
|
||||
{
|
||||
if (!m_webServers.contains(id)) {
|
||||
qWarning(dcServerManager()) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
|
||||
qCWarning(dcServerManager()) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
|
||||
return;
|
||||
}
|
||||
WebServer *server = m_webServers.take(id);
|
||||
@ -341,6 +365,56 @@ void ServerManager::mqttPolicyRemoved(const QString &clientId)
|
||||
m_mqttBroker->removePolicy(clientId);
|
||||
}
|
||||
|
||||
void ServerManager::tunnelProxyServerConfigurationChanged(const QString &id)
|
||||
{
|
||||
TunnelProxyServer *server = m_tunnelProxyServers.value(id);
|
||||
TunnelProxyServerConfiguration config = NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations().value(id);
|
||||
if (server) {
|
||||
qCDebug(dcServerManager()) << "Restarting tunnel proxy connection using" << config;
|
||||
server->stopServer();
|
||||
server->setTunnelProxyConfig(config);
|
||||
} else {
|
||||
qCDebug(dcServerManager()) << "Received a tunnel proxy config change event but don't have a tunnel proxy server instance for it.";
|
||||
qCDebug(dcServerManager()) << "Creating tunnel proxy server using" << config;
|
||||
server = new TunnelProxyServer(m_nymeaConfiguration->serverName(), m_nymeaConfiguration->serverUuid(), config, this);
|
||||
m_tunnelProxyServers.insert(server->configuration().id, server);
|
||||
connect(server, &TunnelProxyServer::runningChanged, this, [this, server](bool running){
|
||||
if (running) {
|
||||
// Note: enable authentication in any case, we don't want to expose unprotected access trough the internet
|
||||
m_jsonServer->registerTransportInterface(server, true);
|
||||
} else {
|
||||
m_jsonServer->unregisterTransportInterface(server);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
server->startServer();
|
||||
}
|
||||
|
||||
void ServerManager::tunnelProxyServerConfigurationRemoved(const QString &id)
|
||||
{
|
||||
if (!m_tunnelProxyServers.contains(id)) {
|
||||
qCWarning(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)
|
||||
{
|
||||
qCDebug(dcServerManager()) << "Cloud connection" << (enabled ? "enabled. Starting tunnel proxy servers" : "disabled. Stopping tunnel proxy servers.");
|
||||
foreach (TunnelProxyServer *server, m_tunnelProxyServers) {
|
||||
if (enabled) {
|
||||
server->startServer();
|
||||
} else {
|
||||
server->stopServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerManager::registerZeroConfService(const ServerConfiguration &configuration, const QString &serverType, const QString &serviceType)
|
||||
{
|
||||
// Note: reversed order
|
||||
@ -352,7 +426,7 @@ bool ServerManager::registerZeroConfService(const ServerConfiguration &configura
|
||||
txt.insert("name", NymeaCore::instance()->configuration()->serverName());
|
||||
txt.insert("sslEnabled", configuration.sslEnabled ? "true" : "false");
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ class WebSocketServer;
|
||||
class WebServer;
|
||||
class BluetoothServer;
|
||||
class MqttBroker;
|
||||
class TunnelProxyServer;
|
||||
|
||||
class MockTcpServer;
|
||||
|
||||
@ -68,6 +69,10 @@ public:
|
||||
|
||||
MqttBroker *mqttBroker() const;
|
||||
|
||||
public slots:
|
||||
void setServerName(const QString &serverName);
|
||||
|
||||
|
||||
private slots:
|
||||
void tcpServerConfigurationChanged(const QString &id);
|
||||
void tcpServerConfigurationRemoved(const QString &id);
|
||||
@ -79,13 +84,20 @@ private slots:
|
||||
void mqttServerConfigurationRemoved(const QString &id);
|
||||
void mqttPolicyChanged(const QString &clientId);
|
||||
void mqttPolicyRemoved(const QString &clientId);
|
||||
void tunnelProxyServerConfigurationChanged(const QString &id);
|
||||
void tunnelProxyServerConfigurationRemoved(const QString &id);
|
||||
|
||||
void cloudEnabledChanged(bool enabled);
|
||||
|
||||
private:
|
||||
bool registerZeroConfService(const ServerConfiguration &configuration, const QString &serverType, const QString &serviceType);
|
||||
void unregisterZeroConfService(const QString &configId, const QString &serverType);
|
||||
|
||||
bool loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName);
|
||||
|
||||
private:
|
||||
Platform *m_platform = nullptr;
|
||||
NymeaConfiguration *m_nymeaConfiguration = nullptr;
|
||||
|
||||
// Interfaces
|
||||
JsonRPCServerImplementation *m_jsonServer;
|
||||
@ -94,6 +106,7 @@ private:
|
||||
QHash<QString, TcpServer*> m_tcpServers;
|
||||
QHash<QString, WebSocketServer*> m_webSocketServers;
|
||||
QHash<QString, WebServer*> m_webServers;
|
||||
QHash<QString, TunnelProxyServer *> m_tunnelProxyServers;
|
||||
MockTcpServer *m_mockTcpServer;
|
||||
|
||||
MqttBroker *m_mqttBroker;
|
||||
@ -102,12 +115,6 @@ private:
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
QSslKey m_certificateKey;
|
||||
QSslCertificate m_certificate;
|
||||
|
||||
bool loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName);
|
||||
|
||||
public slots:
|
||||
void setServerName(const QString &serverName);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ MqttBroker::~MqttBroker()
|
||||
|
||||
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) {
|
||||
qCWarning(dcMqtt) << "Error starting MQTT server on port" << config.port;
|
||||
return false;
|
||||
|
||||
@ -101,7 +101,7 @@ TcpServer::~TcpServer()
|
||||
/*! Returns the URL of this server. */
|
||||
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.*/
|
||||
@ -177,8 +177,8 @@ void TcpServer::setServerName(const QString &serverName)
|
||||
bool TcpServer::startServer()
|
||||
{
|
||||
m_server = new SslServer(configuration().sslEnabled, m_sslConfig);
|
||||
if(!m_server->listen(configuration().address, static_cast<quint16>(configuration().port))) {
|
||||
qCWarning(dcTcpServer()) << "Tcp server error: can not listen on" << configuration().address.toString() << 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 << configuration().port;
|
||||
delete m_server;
|
||||
m_server = nullptr;
|
||||
return false;
|
||||
|
||||
188
libnymea-core/servers/tunnelproxyserver.cpp
Normal file
188
libnymea-core/servers/tunnelproxyserver.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tunnelproxyserver.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
NYMEA_LOGGING_CATEGORY(dcTunnelProxyServer, "TunnelProxyServer")
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
TunnelProxyServer::TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const TunnelProxyServerConfiguration &configuration, QObject *parent) :
|
||||
TransportInterface(configuration, parent),
|
||||
m_tunnelProxyConfig(configuration),
|
||||
m_serverName(serverName),
|
||||
m_serverUuid(serverUuid)
|
||||
{
|
||||
if (!configuration.authenticationEnabled) {
|
||||
qCWarning(dcTunnelProxyServer()) << "=====================================================================================================================";
|
||||
qCWarning(dcTunnelProxyServer()) << "WARNING! Tunnel proxy connection has authentication disabled! The system will be publicly accessible on the internet.";
|
||||
qCWarning(dcTunnelProxyServer()) << "=====================================================================================================================";
|
||||
}
|
||||
|
||||
initConfiguration();
|
||||
|
||||
m_tunnelProxySocketServer = new TunnelProxySocketServer(m_serverUuid, m_serverName, this);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::stateChanged, this, &TunnelProxyServer::onStateChanged);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::runningChanged, this, &TunnelProxyServer::onServerRunningChanged);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::errorOccurred, this, &TunnelProxyServer::onErrorOccurred);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::serverErrorOccurred, this, &TunnelProxyServer::onServerErrorOccurred);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::sslErrors, this, &TunnelProxyServer::onSslErrors);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::clientConnected, this, &TunnelProxyServer::onClientConnected);
|
||||
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::clientDisconnected, this, &TunnelProxyServer::onClientDisconnected);
|
||||
|
||||
}
|
||||
|
||||
TunnelProxyServer::~TunnelProxyServer()
|
||||
{
|
||||
stopServer();
|
||||
}
|
||||
|
||||
void TunnelProxyServer::sendData(const QUuid &clientId, const QByteArray &data)
|
||||
{
|
||||
TunnelProxySocket *tunnelProxySocket = m_clients.value(clientId);
|
||||
if (!tunnelProxySocket) {
|
||||
qCWarning(dcTunnelProxyServer()) << "Failed to send data to client" << clientId.toString() << "because there is no tunnel socket for this client UUID.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: we add a \n at the end of the data for easier json parsing on the other end
|
||||
tunnelProxySocket->writeData(data + '\n');
|
||||
}
|
||||
|
||||
void TunnelProxyServer::sendData(const QList<QUuid> &clients, const QByteArray &data)
|
||||
{
|
||||
foreach (const QUuid &client, clients) {
|
||||
sendData(client, data);
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelProxyServer::terminateClientConnection(const QUuid &clientId)
|
||||
{
|
||||
TunnelProxySocket *tunnelProxySocket = m_clients.value(clientId);
|
||||
if (tunnelProxySocket) {
|
||||
tunnelProxySocket->disconnectSocket();
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelProxyServer::setServerName(const QString &serverName)
|
||||
{
|
||||
m_serverName = serverName;
|
||||
}
|
||||
|
||||
void TunnelProxyServer::setTunnelProxyConfig(const TunnelProxyServerConfiguration &tunnelProxyConfig)
|
||||
{
|
||||
m_tunnelProxyConfig = tunnelProxyConfig;
|
||||
}
|
||||
|
||||
bool TunnelProxyServer::startServer()
|
||||
{
|
||||
initConfiguration();
|
||||
|
||||
qCDebug(dcTunnelProxyServer()) << "Connecting to tunnel proxy server at:" << m_serverUrl;
|
||||
m_tunnelProxySocketServer->startServer(m_serverUrl);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TunnelProxyServer::stopServer()
|
||||
{
|
||||
qCDebug(dcTunnelProxyServer()) << "Stopping server";
|
||||
m_tunnelProxySocketServer->stopServer();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TunnelProxyServer::onStateChanged(TunnelProxySocketServer::State state)
|
||||
{
|
||||
if (state == TunnelProxySocketServer::StateRegister) {
|
||||
qCDebug(dcTunnelProxyServer()) << "Connected with" << m_tunnelProxySocketServer->remoteProxyServer()
|
||||
<< m_tunnelProxySocketServer->remoteProxyServerName()
|
||||
<< m_tunnelProxySocketServer->remoteProxyServerVersion()
|
||||
<< "API:" << m_tunnelProxySocketServer->remoteProxyApiVersion();
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelProxyServer::onServerRunningChanged(bool running)
|
||||
{
|
||||
qCDebug(dcTunnelProxyServer()).noquote() << "The server is" << (running ? "now listening for incoming connections on " + m_serverUuid.toString() : "not running any more.");
|
||||
emit runningChanged(running);
|
||||
}
|
||||
|
||||
void TunnelProxyServer::onErrorOccurred(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qCDebug(dcTunnelProxyServer()) << "Remote proxy connection error occurred" << error;
|
||||
}
|
||||
|
||||
void TunnelProxyServer::onServerErrorOccurred(TunnelProxySocketServer::Error error)
|
||||
{
|
||||
qCWarning(dcTunnelProxyServer()) << "Error occurred on server" << m_serverUrl.toString() << error;
|
||||
}
|
||||
|
||||
void TunnelProxyServer::onSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
qCDebug(dcTunnelProxyServer()) << "Remote proxy connection SSL errors occurred" << errors;
|
||||
if (m_tunnelProxyConfig.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)
|
||||
{
|
||||
QUuid clientId = QUuid::createUuid();
|
||||
qCDebug(dcTunnelProxyServer()) << "Client connected:" << clientId.toString() << tunnelProxySocket->clientName() << "(Remote address:" << tunnelProxySocket->clientPeerAddress().toString() << ")";
|
||||
m_clients.insert(clientId, tunnelProxySocket);
|
||||
|
||||
connect(tunnelProxySocket, &TunnelProxySocket::dataReceived, this, [this, clientId](const QByteArray &data){
|
||||
emit dataAvailable(clientId, data);
|
||||
});
|
||||
|
||||
emit clientConnected(clientId);
|
||||
}
|
||||
|
||||
void TunnelProxyServer::onClientDisconnected(TunnelProxySocket *tunnelProxySocket)
|
||||
{
|
||||
QUuid clientId = m_clients.key(tunnelProxySocket);
|
||||
qCDebug(dcTunnelProxyServer()) << "Client disconnected:" << clientId.toString() << tunnelProxySocket->clientName() << "(Remote address:" << tunnelProxySocket->clientPeerAddress().toString() << ")";
|
||||
m_clients.remove(clientId);
|
||||
emit clientDisconnected(clientId);
|
||||
}
|
||||
|
||||
void TunnelProxyServer::initConfiguration()
|
||||
{
|
||||
qCDebug(dcTunnelProxyServer()) << "Init configuration" << m_tunnelProxyConfig;
|
||||
m_serverUrl.setScheme(m_tunnelProxyConfig.sslEnabled ? "ssl" : "tcp");
|
||||
m_serverUrl.setHost(m_tunnelProxyConfig.address);
|
||||
m_serverUrl.setPort(m_tunnelProxyConfig.port);
|
||||
qCDebug(dcTunnelProxyServer()) << "Using server URL" << m_serverUrl.toString();
|
||||
}
|
||||
|
||||
}
|
||||
93
libnymea-core/servers/tunnelproxyserver.h
Normal file
93
libnymea-core/servers/tunnelproxyserver.h
Normal file
@ -0,0 +1,93 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TUNNELPROXYSERVER_H
|
||||
#define TUNNELPROXYSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "transportinterface.h"
|
||||
|
||||
#include <tunnelproxy/tunnelproxysocket.h>
|
||||
#include <tunnelproxy/tunnelproxysocketserver.h>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
using namespace remoteproxyclient;
|
||||
|
||||
class TunnelProxyServer : public TransportInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const TunnelProxyServerConfiguration &configuration, QObject *parent = nullptr);
|
||||
~TunnelProxyServer() override;
|
||||
|
||||
void sendData(const QUuid &clientId, const QByteArray &data) override;
|
||||
void sendData(const QList<QUuid> &clients, const QByteArray &data) override;
|
||||
|
||||
void terminateClientConnection(const QUuid &clientId) override;
|
||||
|
||||
public slots:
|
||||
void setServerName(const QString &serverName) override;
|
||||
void setTunnelProxyConfig(const TunnelProxyServerConfiguration &tunnelProxyConfig);
|
||||
|
||||
bool startServer() override;
|
||||
bool stopServer() override;
|
||||
|
||||
signals:
|
||||
void runningChanged(bool running);
|
||||
|
||||
private slots:
|
||||
void onStateChanged(TunnelProxySocketServer::State state);
|
||||
void onServerRunningChanged(bool running);
|
||||
void onErrorOccurred(QAbstractSocket::SocketError error);
|
||||
void onServerErrorOccurred(TunnelProxySocketServer::Error error);
|
||||
void onSslErrors(const QList<QSslError> &errors);
|
||||
|
||||
void onClientConnected(TunnelProxySocket *tunnelProxySocket);
|
||||
void onClientDisconnected(TunnelProxySocket *tunnelProxySocket);
|
||||
|
||||
private:
|
||||
TunnelProxyServerConfiguration m_tunnelProxyConfig;
|
||||
TunnelProxySocketServer *m_tunnelProxySocketServer = nullptr;
|
||||
QString m_serverName;
|
||||
QUuid m_serverUuid;
|
||||
QUrl m_serverUrl;
|
||||
|
||||
QHash<QUuid, TunnelProxySocket *> m_clients;
|
||||
|
||||
void initConfiguration();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TUNNELPROXYSERVER_H
|
||||
@ -129,7 +129,7 @@ WebServer::~WebServer()
|
||||
/*! Returns the server URL of this WebServer. */
|
||||
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.
|
||||
@ -561,7 +561,7 @@ void WebServer::setServerName(const QString &serverName)
|
||||
/*! Returns true if this \l{WebServer} started successfully. */
|
||||
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();
|
||||
m_enabled = false;
|
||||
return false;
|
||||
@ -712,7 +712,7 @@ QByteArray WebServer::createServerXmlDocument(QHostAddress address)
|
||||
int counter = 1;
|
||||
int sslCounter = 1;
|
||||
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.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++));
|
||||
@ -725,7 +725,7 @@ QByteArray WebServer::createServerXmlDocument(QHostAddress address)
|
||||
counter = 1;
|
||||
sslCounter = 1;
|
||||
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.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++));
|
||||
|
||||
@ -87,7 +87,7 @@ WebSocketServer::~WebSocketServer()
|
||||
/*! Returns the url of this server. */
|
||||
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.
|
||||
@ -219,7 +219,7 @@ bool WebSocketServer::startServer()
|
||||
connect (m_server, &QWebSocketServer::newConnection, this, &WebSocketServer::onClientConnected);
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -98,6 +98,7 @@ TransportInterface::TransportInterface(const ServerConfiguration &config, QObjec
|
||||
QObject(parent),
|
||||
m_config(config)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*! Set the ServerConfiguration of this TransportInterface to the given \a config. */
|
||||
|
||||
@ -457,7 +457,7 @@ void ZigbeeManager::addNetwork(ZigbeeNetwork *network)
|
||||
});
|
||||
|
||||
connect(network, &ZigbeeNetwork::errorOccured, this, [this, network](ZigbeeNetwork::Error error){
|
||||
qCWarning(dcZigbee()) << "Network error occured for" << network << error;
|
||||
qCWarning(dcZigbee()) << "Network error occurred for" << network << error;
|
||||
evaluateZigbeeAvailable();
|
||||
// TODO: handle error
|
||||
});
|
||||
|
||||
@ -471,6 +471,16 @@
|
||||
"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": {
|
||||
"description": "Delete a WebServer interface of the server.",
|
||||
"params": {
|
||||
@ -507,7 +517,7 @@
|
||||
"description": "Get all configuration parameters of the server.",
|
||||
"params": {
|
||||
},
|
||||
"permissionScope": "PermissionScopeAdmin",
|
||||
"permissionScope": "PermissionScopeNone",
|
||||
"returns": {
|
||||
"basicConfiguration": {
|
||||
"d:language": "String",
|
||||
@ -523,6 +533,9 @@
|
||||
"tcpServerConfigurations": [
|
||||
"$ref:ServerConfiguration"
|
||||
],
|
||||
"tunnelProxyServerConfigurations": [
|
||||
"$ref:TunnelProxyServerConfiguration"
|
||||
],
|
||||
"webServerConfigurations": [
|
||||
"$ref:WebServerConfiguration"
|
||||
],
|
||||
@ -647,6 +660,16 @@
|
||||
"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": {
|
||||
"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": {
|
||||
@ -2043,6 +2066,18 @@
|
||||
"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": {
|
||||
"description": "Emitted whenever the web server configuration changes.",
|
||||
"params": {
|
||||
@ -2830,6 +2865,14 @@
|
||||
"TokenInfoList": [
|
||||
"$ref:TokenInfo"
|
||||
],
|
||||
"TunnelProxyServerConfiguration": {
|
||||
"address": "String",
|
||||
"authenticationEnabled": "Bool",
|
||||
"id": "String",
|
||||
"ignoreSslErrors": "Bool",
|
||||
"port": "Uint",
|
||||
"sslEnabled": "Bool"
|
||||
},
|
||||
"UserInfo": {
|
||||
"r:displayName": "String",
|
||||
"r:email": "String",
|
||||
|
||||
@ -278,7 +278,7 @@ void TestConfigurations::testDebugServerConfiguration()
|
||||
|
||||
qCDebug(dcTests()) << "TestWebserver starting";
|
||||
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";
|
||||
return;
|
||||
}
|
||||
@ -287,7 +287,7 @@ void TestConfigurations::testDebugServerConfiguration()
|
||||
qCDebug(dcTests) << "Creating new webserver instance on 127.0.0.1:3333";
|
||||
WebServerConfiguration config;
|
||||
config.id = "Testwebserver for debug server interface";
|
||||
config.address = QHostAddress("127.0.0.1");
|
||||
config.address = "127.0.0.1";
|
||||
config.port = 3333;
|
||||
config.sslEnabled = true;
|
||||
NymeaCore::instance()->configuration()->setWebServerConfiguration(config);
|
||||
|
||||
@ -61,8 +61,7 @@ private slots:
|
||||
|
||||
void TestMqttBroker::initTestCase()
|
||||
{
|
||||
NymeaTestBase::initTestCase();
|
||||
QLoggingCategory::setFilterRules("*.debug=false\nnymea.mqtt*.debug=true\nMqtt.debug=true\nJsonRpc.debug=true");
|
||||
NymeaTestBase::initTestCase("*.debug=false\nnymea.mqtt*.debug=true\nMqtt.debug=true\nJsonRpc.debug=true");
|
||||
}
|
||||
|
||||
void TestMqttBroker::testServerConfigurationAPI()
|
||||
|
||||
@ -79,7 +79,7 @@ void TestWebserver::initTestCase()
|
||||
qDebug() << "TestWebserver starting";
|
||||
|
||||
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";
|
||||
return;
|
||||
}
|
||||
@ -87,7 +87,7 @@ void TestWebserver::initTestCase()
|
||||
|
||||
qDebug() << "Creating new webserver instance on 127.0.0.1:3333";
|
||||
WebServerConfiguration config;
|
||||
config.address = QHostAddress("127.0.0.1");
|
||||
config.address = "127.0.0.1";
|
||||
config.port = 3333;
|
||||
config.sslEnabled = true;
|
||||
config.restServerEnabled = true;
|
||||
@ -215,7 +215,7 @@ void TestWebserver::checkAllowedMethodCall()
|
||||
QFETCH(int, expectedStatusCode);
|
||||
|
||||
QNetworkAccessManager nam;
|
||||
connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply* reply, const QList<QSslError> &) {
|
||||
connect(&nam, &QNetworkAccessManager::sslErrors, [](QNetworkReply* reply, const QList<QSslError> &) {
|
||||
reply->ignoreSslErrors();
|
||||
});
|
||||
QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
@ -72,7 +72,7 @@ void TestWebSocketServer::initTestCase()
|
||||
|
||||
ServerConfiguration config;
|
||||
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";
|
||||
config = c;
|
||||
break;
|
||||
@ -80,7 +80,7 @@ void TestWebSocketServer::initTestCase()
|
||||
}
|
||||
|
||||
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.sslEnabled = true;
|
||||
config.authenticationEnabled = true;
|
||||
|
||||
Reference in New Issue
Block a user