Introduce monitor refresh method with params

cleanup-proxy-code
Simon Stürz 2023-02-16 22:27:56 +01:00
parent eb609da9a4
commit 5b39e12449
15 changed files with 163 additions and 42 deletions

View File

@ -243,6 +243,19 @@ 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);
if (m_proxyServer) {
monitorData.insert("proxyStatistic", m_proxyServer->currentStatistics());
}
monitorData.insert("tunnelProxyStatistic", tunnelProxyServer()->currentStatistics(printAll));
return monitorData;
}
Engine::Engine(QObject *parent) :
QObject(parent)
{
@ -262,19 +275,6 @@ Engine::~Engine()
stop();
}
QVariantMap Engine::createServerStatistic()
{
QVariantMap monitorData;
monitorData.insert("serverName", m_configuration->serverName());
monitorData.insert("serverVersion", SERVER_VERSION_STRING);
monitorData.insert("apiVersion", API_VERSION_STRING);
if (m_proxyServer) {
monitorData.insert("proxyStatistic", m_proxyServer->currentStatistics());
}
monitorData.insert("tunnelProxyStatistic", tunnelProxyServer()->currentStatistics());
return monitorData;
}
void Engine::onTimerTick()
{
qint64 timestamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
@ -284,21 +284,22 @@ void Engine::onTimerTick()
m_currentTimeCounter += deltaTime;
if (m_currentTimeCounter >= 1000) {
// One second passed, do second tick
if (m_proxyServer)
m_proxyServer->tick();
QVariantMap serverStatistics = createServerStatistic();
m_monitorServer->updateClients(serverStatistics);
m_logEngine->logStatistics(serverStatistics.value("proxyStatistic").toMap().value("tunnelCount").toInt(),
serverStatistics.value("proxyStatistic").toMap().value("clientCount").toInt(),
serverStatistics.value("proxyStatistic").toMap().value("troughput").toInt());
m_currentTimeCounter = 0;
if (m_proxyServer) {
m_proxyServer->tick();
}
if (m_tunnelProxyServer) {
m_tunnelProxyServer->tick();
}
// QVariantMap serverStatistics = buildMonitorData();
// m_monitorServer->updateClients(serverStatistics);
// m_logEngine->logStatistics(serverStatistics.value("proxyStatistic").toMap().value("tunnelCount").toInt(),
// serverStatistics.value("proxyStatistic").toMap().value("clientCount").toInt(),
// serverStatistics.value("proxyStatistic").toMap().value("troughput").toInt());
}
}

View File

@ -84,6 +84,8 @@ public:
MonitorServer *monitorServer() const;
LogEngine *logEngine() const;
QVariantMap buildMonitorData(bool printAll = false);
private:
explicit Engine(QObject *parent = nullptr);
~Engine();
@ -113,8 +115,6 @@ private:
MonitorServer *m_monitorServer = nullptr;
LogEngine *m_logEngine = nullptr;
QVariantMap createServerStatistic();
signals:
void runningChanged(bool running);

View File

@ -66,9 +66,8 @@ void MonitorServer::onMonitorConnected()
{
QLocalSocket *clientConnection = m_server->nextPendingConnection();
connect(clientConnection, &QLocalSocket::disconnected, this, &MonitorServer::onMonitorDisconnected);
connect(clientConnection, &QLocalSocket::readyRead, this, &MonitorServer::onMonitorDisconnected);
connect(clientConnection, &QLocalSocket::readyRead, this, &MonitorServer::onMonitorReadyRead);
m_clients.append(clientConnection);
qCDebug(dcMonitorServer()) << "New monitor connected.";
}
@ -80,6 +79,57 @@ void MonitorServer::onMonitorDisconnected()
clientConnection->deleteLater();
}
void MonitorServer::onMonitorReadyRead()
{
QLocalSocket *clientConnection = qobject_cast<QLocalSocket*>(sender());
QByteArray data = clientConnection->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if(error.error != QJsonParseError::NoError) {
qCWarning(dcMonitorServer()) << "Failed to parse JSON data from monitor:" << error.errorString();
clientConnection->close();
return;
}
processRequest(clientConnection, jsonDoc.toVariant().toMap());
}
void MonitorServer::processRequest(QLocalSocket *clientConnection, const QVariantMap &request)
{
/* Refresh method. If no params, it will return the active list of connections
TODO: filter for uuid's, ip's, names etc...
{
"method": "refresh",
"params": {
"printAll": bool
}
}
*/
// Note: as simple as possible...no error handling, either you know what you do, or you see nothing here.
if (request.contains("method")) {
if (request.value("method").toString() == "refresh") {
bool printAll = false;
if (request.contains("params")) {
QVariantMap params = request.value("params").toMap();
if (params.contains("printAll")) {
printAll = params.value("printAll").toBool();
}
}
sendMonitorData(clientConnection, Engine::instance()->buildMonitorData(printAll));
return;
}
}
// Not a valid request. Close the connection
qCWarning(dcMonitorServer()) << "Could not understand the request. Closing connection.";
clientConnection->close();
}
void MonitorServer::startServer()
{
qCDebug(dcMonitorServer()) << "Starting server on" << m_serverName;

View File

@ -54,6 +54,9 @@ private:
private slots:
void onMonitorConnected();
void onMonitorDisconnected();
void onMonitorReadyRead();
void processRequest(QLocalSocket *clientConnection, const QVariantMap &request);
public slots:
void startServer();

View File

@ -1,4 +1,4 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
@ -158,6 +158,7 @@ void TransportClient::sendData(const QByteArray &data)
if (!m_interface)
return;
addTxDataCount(data.count());
m_interface->sendData(m_clientId, data);
}

View File

@ -204,7 +204,7 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::disconnectClient(const QU
return TunnelProxyServer::TunnelProxyErrorNoError;
}
QVariantMap TunnelProxyServer::currentStatistics()
QVariantMap TunnelProxyServer::currentStatistics(bool printAll)
{
QVariantMap statisticsMap;
statisticsMap.insert("totalClientCount", m_proxyClients.count());
@ -221,7 +221,7 @@ QVariantMap TunnelProxyServer::currentStatistics()
foreach (TunnelProxyServerConnection *serverConnection, m_tunnelProxyServerConnections) {
// Show only active clients
if (serverConnection->clientConnections().isEmpty())
if (!printAll && serverConnection->clientConnections().isEmpty())
continue;
QVariantMap serverMap;
@ -365,7 +365,6 @@ void TunnelProxyServer::onClientDataAvailable(const QUuid &clientId, const QByte
qCDebug(dcTunnelProxyServerTraffic()) << "--> Tunnel data to server socket address" << clientConnection->socketAddress() << "to" << clientConnection->serverConnection() << "\n" << data;
QByteArray rawData = SlipDataProcessor::serializeData(SlipDataProcessor::buildFrame(frame));
clientConnection->serverConnection()->transportClient()->sendData(rawData);
clientConnection->serverConnection()->transportClient()->addTxDataCount(rawData.count());
m_troughputCounter += data.count();
} else if (tunnelProxyClient->type() == TunnelProxyClient::TypeServer) {
@ -401,7 +400,6 @@ void TunnelProxyServer::onClientDataAvailable(const QUuid &clientId, const QByte
qCDebug(dcTunnelProxyServerTraffic()) << "--> Tunnel data from server socket" << frame.socketAddress << "to" << clientConnection << "\n" << frame.data;
clientConnection->transportClient()->sendData(frame.data);
clientConnection->transportClient()->addTxDataCount(frame.data.count());
m_troughputCounter += frame.data.count();
}
}

View File

@ -67,7 +67,7 @@ public:
TunnelProxyServer::TunnelProxyError registerClient(const QUuid &clientId, const QUuid &clientUuid, const QString &clientName, const QUuid &serverUuid);
TunnelProxyServer::TunnelProxyError disconnectClient(const QUuid &clientId, quint16 socketAddress);
QVariantMap currentStatistics();
QVariantMap currentStatistics(bool printAll = false);
public slots:
void startServer();

View File

@ -61,9 +61,12 @@ int main(int argc, char *argv[])
socketOption.setDefaultValue("/tmp/nymea-remoteproxy-monitor.sock");
parser.addOption(socketOption);
QCommandLineOption noninteractiveOption(QStringList() << "n" << "non-interactive", "Connect to the server, list all data and close the connection. This works only for the tunnelproxy.");
QCommandLineOption noninteractiveOption(QStringList() << "n" << "non-interactive", "Connect to the server and list information and connections and exit.");
parser.addOption(noninteractiveOption);
QCommandLineOption allOption(QStringList() << "a" << "all", "Show all connections, not only the active tunnels. Currently only available with the non-interactive mode.");
parser.addOption(allOption);
QCommandLineOption jsonOption(QStringList() << "j" << "json", "Connect to the server and print the raw json data.");
parser.addOption(jsonOption);
@ -73,19 +76,24 @@ int main(int argc, char *argv[])
QFileInfo fileInfo(parser.value(socketOption));
if (!fileInfo.exists()) {
qWarning() << "Could not find socket descriptor" << parser.value(socketOption);
exit(1);
exit(EXIT_FAILURE);
}
if (!fileInfo.isReadable()) {
qWarning() << "Could not open socket descriptor" << parser.value(socketOption);
exit(1);
exit(EXIT_FAILURE);
}
if (parser.isSet(noninteractiveOption)) {
NonInteractiveMonitor *monitor = new NonInteractiveMonitor(parser.value(socketOption));
NonInteractiveMonitor *monitor = new NonInteractiveMonitor(parser.value(socketOption), parser.isSet(allOption), &application);
Q_UNUSED(monitor);
} else {
Monitor *monitor = new Monitor(parser.value(socketOption), parser.isSet(jsonOption));
if (parser.isSet(allOption)) {
qWarning() << "Error: The \"all\" option is only available with the non-interavtice mode.";
exit(EXIT_FAILURE);
}
Monitor *monitor = new Monitor(parser.value(socketOption), parser.isSet(jsonOption), &application);
Q_UNUSED(monitor);
}

View File

@ -36,6 +36,10 @@ Monitor::Monitor(const QString &serverName, bool jsonMode, QObject *parent) :
connect(m_monitorClient, &MonitorClient::connected, this, &Monitor::onConnected);
connect(m_monitorClient, &MonitorClient::disconnected, this, &Monitor::onDisconnected);
m_timer.setInterval(1000);
m_timer.setSingleShot(false);
connect(&m_timer, &QTimer::timeout, m_monitorClient, &MonitorClient::refresh);
m_monitorClient->connectMonitor();
}
@ -45,10 +49,15 @@ void Monitor::onConnected()
m_terminal = new TerminalWindow(this);
connect(m_monitorClient, &MonitorClient::dataReady, m_terminal, &TerminalWindow::refreshWindow);
}
refresh();
m_timer.start();
}
void Monitor::onDisconnected()
{
m_timer.stop();
if (!m_terminal)
return;

View File

@ -29,6 +29,7 @@
#define MONITOR_H
#include <QObject>
#include <QTimer>
#include "monitorclient.h"
#include "terminalwindow.h"
@ -43,6 +44,7 @@ private:
TerminalWindow *m_terminal = nullptr;
MonitorClient *m_monitorClient = nullptr;
bool m_jsonMode = false;
QTimer m_timer;
private slots:
void onConnected();

View File

@ -42,6 +42,16 @@ MonitorClient::MonitorClient(const QString &serverName, bool jsonMode, QObject *
connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onErrorOccurred(QLocalSocket::LocalSocketError)));
}
bool MonitorClient::printAll() const
{
return m_printAll;
}
void MonitorClient::setPrintAll(bool printAll)
{
m_printAll = printAll;
}
void MonitorClient::processBufferData()
{
QJsonParseError error;
@ -98,10 +108,28 @@ void MonitorClient::onErrorOccurred(QLocalSocket::LocalSocketError socketError)
void MonitorClient::connectMonitor()
{
m_socket->connectToServer(m_serverName, QLocalSocket::ReadOnly);
m_socket->connectToServer(m_serverName, QLocalSocket::ReadWrite);
}
void MonitorClient::disconnectMonitor()
{
m_socket->close();
}
void MonitorClient::refresh()
{
if (m_socket->state() != QLocalSocket::ConnectedState)
return;
QVariantMap request;
request.insert("method", "refresh");
QVariantMap params;
if (m_printAll) {
params.insert("printAll", m_printAll);
}
if (!params.isEmpty())
request.insert("params", params);
m_socket->write(QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + "\n");
}

View File

@ -39,10 +39,17 @@ class MonitorClient : public QObject
public:
explicit MonitorClient(const QString &serverName, bool jsonMode, QObject *parent = nullptr);
// Configuration before connection
bool printAll() const;
void setPrintAll(bool printAll);
private:
QString m_serverName;
QLocalSocket *m_socket = nullptr;
QString m_serverName;
bool m_jsonMode = false;
bool m_printAll = false;
QByteArray m_dataBuffer;
void processBufferData();
@ -62,6 +69,7 @@ public slots:
void connectMonitor();
void disconnectMonitor();
void refresh();
};
#endif // MONITORCLIENT_H

View File

@ -30,10 +30,12 @@
#include <QDebug>
NonInteractiveMonitor::NonInteractiveMonitor(const QString &serverName, QObject *parent)
NonInteractiveMonitor::NonInteractiveMonitor(const QString &serverName, bool printAll, QObject *parent)
: QObject{parent}
{
m_monitorClient = new MonitorClient(serverName, false, this);
m_monitorClient->setPrintAll(printAll);
connect(m_monitorClient, &MonitorClient::connected, this, &NonInteractiveMonitor::onConnected);
m_monitorClient->connectMonitor();
@ -105,4 +107,5 @@ void NonInteractiveMonitor::onConnected()
exit(0);
});
m_monitorClient->refresh();
}

View File

@ -35,7 +35,7 @@ class NonInteractiveMonitor : public QObject
{
Q_OBJECT
public:
explicit NonInteractiveMonitor(const QString &serverName, QObject *parent = nullptr);
explicit NonInteractiveMonitor(const QString &serverName, bool printAll = false, QObject *parent = nullptr);
private:
MonitorClient *m_monitorClient = nullptr;

View File

@ -58,6 +58,16 @@ createTunnelConnections 3
createTunnelConnections 2
createTunnelConnections 1
createTunnelConnections 8
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
createTunnelConnections 0
sleep 10