270 lines
7.4 KiB
C++
270 lines
7.4 KiB
C++
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* nymea-remoteproxy
|
|
* Tunnel proxy server for the nymea remote access
|
|
*
|
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
|
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
|
*
|
|
* This file is part of nymea-remoteproxy.
|
|
*
|
|
* nymea-remoteproxy is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation, either version 3
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* nymea-remoteproxy 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with nymea-remoteproxy. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "engine.h"
|
|
#include "loggingcategories.h"
|
|
#include "../version.h"
|
|
|
|
namespace remoteproxy {
|
|
|
|
Engine *Engine::s_instance = nullptr;
|
|
|
|
Engine *Engine::instance()
|
|
{
|
|
if (!s_instance) {
|
|
qCDebug(dcEngine()) << "Create server engine";
|
|
s_instance = new Engine();
|
|
}
|
|
|
|
return s_instance;
|
|
}
|
|
|
|
void Engine::destroy()
|
|
{
|
|
qCDebug(dcEngine()) << "Destroy server engine";
|
|
if (s_instance) {
|
|
delete s_instance;
|
|
}
|
|
|
|
s_instance = nullptr;
|
|
}
|
|
|
|
bool Engine::exists()
|
|
{
|
|
return s_instance != nullptr;
|
|
}
|
|
|
|
void Engine::start(ProxyConfiguration *configuration)
|
|
{
|
|
if (!m_running)
|
|
qCDebug(dcEngine()) << "Start server engine";
|
|
|
|
// Clean up
|
|
clean();
|
|
|
|
m_configuration = configuration;
|
|
qCDebug(dcEngine()) << "Using configuration" << m_configuration;
|
|
|
|
|
|
// Tunnel proxy
|
|
// -------------------------------------
|
|
m_tunnelProxyServer = new TunnelProxyServer(this);
|
|
m_webSocketServerTunnelProxy = new WebSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
|
|
m_tcpSocketServerTunnelProxy = new TcpSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
|
|
m_unixSocketServerTunnelProxy = new UnixSocketServer(m_configuration->unixSocketFileName(), this);
|
|
|
|
// Configure websocket server
|
|
QUrl websocketServerTunnelProxyUrl;
|
|
websocketServerTunnelProxyUrl.setScheme(m_configuration->sslEnabled() ? "wss" : "ws");
|
|
websocketServerTunnelProxyUrl.setHost(m_configuration->webSocketServerTunnelProxyHost().toString());
|
|
websocketServerTunnelProxyUrl.setPort(m_configuration->webSocketServerTunnelProxyPort());
|
|
m_webSocketServerTunnelProxy->setServerUrl(websocketServerTunnelProxyUrl);
|
|
|
|
// Configure tcp socket server
|
|
QUrl tcpSocketServerTunnelProxyUrl;
|
|
tcpSocketServerTunnelProxyUrl.setScheme(m_configuration->sslEnabled() ? "ssl" : "tcp");
|
|
tcpSocketServerTunnelProxyUrl.setHost(m_configuration->tcpServerTunnelProxyHost().toString());
|
|
tcpSocketServerTunnelProxyUrl.setPort(m_configuration->tcpServerTunnelProxyPort());
|
|
m_tcpSocketServerTunnelProxy->setServerUrl(tcpSocketServerTunnelProxyUrl);
|
|
|
|
// Register the transport interfaces in the proxy server
|
|
m_tunnelProxyServer->registerTransportInterface(m_webSocketServerTunnelProxy);
|
|
m_tunnelProxyServer->registerTransportInterface(m_tcpSocketServerTunnelProxy);
|
|
m_tunnelProxyServer->registerTransportInterface(m_unixSocketServerTunnelProxy);
|
|
|
|
// Start the server
|
|
qCDebug(dcEngine()) << "Starting the tunnel proxy manager...";
|
|
m_tunnelProxyServer->startServer();
|
|
|
|
// Monitor server
|
|
// -------------------------------------
|
|
m_monitorServer = new MonitorServer(configuration->monitorSocketFileName(), this);
|
|
m_monitorServer->startServer();
|
|
|
|
if (configuration->logEngineEnabled())
|
|
m_logEngine->enable();
|
|
|
|
// Set running true in the next event loop
|
|
QMetaObject::invokeMethod(this, QString("setRunning").toLatin1().data(), Qt::QueuedConnection, Q_ARG(bool, true));
|
|
}
|
|
|
|
void Engine::stop()
|
|
{
|
|
if (m_running)
|
|
qCDebug(dcEngine()) << "Stop server engine";
|
|
|
|
clean();
|
|
setRunning(false);
|
|
}
|
|
|
|
bool Engine::running() const
|
|
{
|
|
return m_running;
|
|
}
|
|
|
|
QString Engine::serverName() const
|
|
{
|
|
return m_configuration->serverName();
|
|
}
|
|
|
|
ProxyConfiguration *Engine::configuration() const
|
|
{
|
|
return m_configuration;
|
|
}
|
|
|
|
TunnelProxyServer *Engine::tunnelProxyServer() const
|
|
{
|
|
return m_tunnelProxyServer;
|
|
}
|
|
|
|
UnixSocketServer *Engine::unixSocketServerTunnelProxy() const
|
|
{
|
|
return m_unixSocketServerTunnelProxy;
|
|
}
|
|
|
|
TcpSocketServer *Engine::tcpSocketServerTunnelProxy() const
|
|
{
|
|
return m_tcpSocketServerTunnelProxy;
|
|
}
|
|
|
|
WebSocketServer *Engine::webSocketServerTunnelProxy() const
|
|
{
|
|
return m_webSocketServerTunnelProxy;
|
|
}
|
|
|
|
MonitorServer *Engine::monitorServer() const
|
|
{
|
|
return m_monitorServer;
|
|
}
|
|
|
|
LogEngine *Engine::logEngine() const
|
|
{
|
|
return m_logEngine;
|
|
}
|
|
|
|
QVariantMap Engine::buildMonitorData(bool printAll)
|
|
{
|
|
QVariantMap monitorData;
|
|
monitorData.insert("serverName", m_configuration->serverName());
|
|
monitorData.insert("serverVersion", SERVER_VERSION_STRING);
|
|
monitorData.insert("apiVersion", API_VERSION_STRING);
|
|
monitorData.insert("tunnelProxyStatistic", tunnelProxyServer()->currentStatistics(printAll));
|
|
return monitorData;
|
|
}
|
|
|
|
Engine::Engine(QObject *parent) :
|
|
QObject(parent)
|
|
{
|
|
m_lastTimeStamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
|
|
|
|
m_timer = new QTimer(this);
|
|
m_timer->setSingleShot(false);
|
|
m_timer->setInterval(50);
|
|
|
|
connect(m_timer, &QTimer::timeout, this, &Engine::onTimerTick);
|
|
m_logEngine = new LogEngine(this);
|
|
}
|
|
|
|
Engine::~Engine()
|
|
{
|
|
stop();
|
|
}
|
|
|
|
void Engine::onTimerTick()
|
|
{
|
|
qint64 timestamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
|
|
qint64 deltaTime = timestamp - m_lastTimeStamp;
|
|
m_lastTimeStamp = timestamp;
|
|
|
|
m_currentTimeCounter += deltaTime;
|
|
if (m_currentTimeCounter >= 1000) {
|
|
// One second passed, do second tick
|
|
m_currentTimeCounter = 0;
|
|
if (m_tunnelProxyServer) {
|
|
m_tunnelProxyServer->tick();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Engine::clean()
|
|
{
|
|
if (m_monitorServer) {
|
|
m_monitorServer->stopServer();
|
|
delete m_monitorServer;
|
|
m_monitorServer = nullptr;
|
|
}
|
|
|
|
if (m_tunnelProxyServer) {
|
|
m_tunnelProxyServer->stopServer();
|
|
delete m_tunnelProxyServer;
|
|
m_tunnelProxyServer = nullptr;
|
|
}
|
|
|
|
if (m_tcpSocketServerTunnelProxy) {
|
|
delete m_tcpSocketServerTunnelProxy;
|
|
m_tcpSocketServerTunnelProxy = nullptr;
|
|
}
|
|
|
|
if (m_webSocketServerTunnelProxy) {
|
|
delete m_webSocketServerTunnelProxy;
|
|
m_webSocketServerTunnelProxy = nullptr;
|
|
}
|
|
|
|
if (m_unixSocketServerTunnelProxy) {
|
|
delete m_unixSocketServerTunnelProxy;
|
|
m_unixSocketServerTunnelProxy = nullptr;
|
|
}
|
|
|
|
if (m_configuration) {
|
|
delete m_configuration;
|
|
m_configuration = nullptr;
|
|
}
|
|
}
|
|
|
|
void Engine::setRunning(bool running)
|
|
{
|
|
if (m_running == running)
|
|
return;
|
|
|
|
if (m_tunnelProxyServer)
|
|
m_tunnelProxyServer->setRunning(running);
|
|
|
|
qCDebug(dcEngine()) << "Engine is" << (running ? "now running." : "not running any more.");
|
|
|
|
if (running) {
|
|
m_timer->start();
|
|
} else {
|
|
m_timer->stop();
|
|
}
|
|
|
|
m_running = running;
|
|
emit runningChanged(m_running);
|
|
}
|
|
|
|
|
|
}
|