diff --git a/libnymea-remoteproxy/engine.cpp b/libnymea-remoteproxy/engine.cpp index 7d6ca85..538ce4c 100644 --- a/libnymea-remoteproxy/engine.cpp +++ b/libnymea-remoteproxy/engine.cpp @@ -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()); } } diff --git a/libnymea-remoteproxy/engine.h b/libnymea-remoteproxy/engine.h index 1b73286..e3297dc 100644 --- a/libnymea-remoteproxy/engine.h +++ b/libnymea-remoteproxy/engine.h @@ -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); diff --git a/libnymea-remoteproxy/server/monitorserver.cpp b/libnymea-remoteproxy/server/monitorserver.cpp index 3cd94af..380e4ad 100644 --- a/libnymea-remoteproxy/server/monitorserver.cpp +++ b/libnymea-remoteproxy/server/monitorserver.cpp @@ -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(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; diff --git a/libnymea-remoteproxy/server/monitorserver.h b/libnymea-remoteproxy/server/monitorserver.h index 12f8597..951efc9 100644 --- a/libnymea-remoteproxy/server/monitorserver.h +++ b/libnymea-remoteproxy/server/monitorserver.h @@ -54,6 +54,9 @@ private: private slots: void onMonitorConnected(); void onMonitorDisconnected(); + void onMonitorReadyRead(); + + void processRequest(QLocalSocket *clientConnection, const QVariantMap &request); public slots: void startServer(); diff --git a/libnymea-remoteproxy/server/transportclient.cpp b/libnymea-remoteproxy/server/transportclient.cpp index 571456f..aa4bcb6 100644 --- a/libnymea-remoteproxy/server/transportclient.cpp +++ b/libnymea-remoteproxy/server/transportclient.cpp @@ -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); } diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp index 07b2a44..080f2a4 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp @@ -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(); } } diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.h b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.h index c03febc..d01f8fb 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.h +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.h @@ -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(); diff --git a/monitor/main.cpp b/monitor/main.cpp index 6d311b6..66d8a23 100644 --- a/monitor/main.cpp +++ b/monitor/main.cpp @@ -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); } diff --git a/monitor/monitor.cpp b/monitor/monitor.cpp index 58cf366..156de5b 100644 --- a/monitor/monitor.cpp +++ b/monitor/monitor.cpp @@ -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; diff --git a/monitor/monitor.h b/monitor/monitor.h index 6bd199c..aa31343 100644 --- a/monitor/monitor.h +++ b/monitor/monitor.h @@ -29,6 +29,7 @@ #define MONITOR_H #include +#include #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(); diff --git a/monitor/monitorclient.cpp b/monitor/monitorclient.cpp index a176fed..0174914 100644 --- a/monitor/monitorclient.cpp +++ b/monitor/monitorclient.cpp @@ -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"); +} diff --git a/monitor/monitorclient.h b/monitor/monitorclient.h index 65b19ed..816db69 100644 --- a/monitor/monitorclient.h +++ b/monitor/monitorclient.h @@ -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 diff --git a/monitor/noninteractivemonitor.cpp b/monitor/noninteractivemonitor.cpp index 6d56743..90c1f6e 100644 --- a/monitor/noninteractivemonitor.cpp +++ b/monitor/noninteractivemonitor.cpp @@ -30,10 +30,12 @@ #include -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(); } diff --git a/monitor/noninteractivemonitor.h b/monitor/noninteractivemonitor.h index 67191e2..716da82 100644 --- a/monitor/noninteractivemonitor.h +++ b/monitor/noninteractivemonitor.h @@ -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; diff --git a/tests/scripts/create-many-connections.sh b/tests/scripts/create-many-connections.sh index c0aff57..752cd93 100755 --- a/tests/scripts/create-many-connections.sh +++ b/tests/scripts/create-many-connections.sh @@ -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