Improve monitor and implement server statistics
This commit is contained in:
parent
6869b18ad9
commit
2173d8e61f
@ -56,6 +56,8 @@ void AwsAuthenticator::onAuthenticationProcessFinished(Authenticator::Authentica
|
||||
qCDebug(dcAuthentication()) << name() << reply->proxyClient() << "finished with error" << error;
|
||||
}
|
||||
|
||||
reply->proxyClient()->setUserName(userInformation.email());
|
||||
|
||||
setReplyError(reply, error);
|
||||
setReplyFinished(reply);
|
||||
}
|
||||
|
||||
@ -43,6 +43,8 @@ AuthenticationReply *DummyAuthenticator::authenticate(ProxyClient *proxyClient)
|
||||
qCWarning(dcAuthentication()) << "Attention: This authenticator will always succeed! This is a security risk and was explicitly enabled!";
|
||||
AuthenticationReply *reply = createAuthenticationReply(proxyClient, this);
|
||||
|
||||
proxyClient->setUserName("dummy@example.com");
|
||||
|
||||
setReplyError(reply, AuthenticationErrorNoError);
|
||||
setReplyFinished(reply);
|
||||
return reply;
|
||||
|
||||
@ -157,7 +157,13 @@ MonitorServer *Engine::monitorServer() const
|
||||
Engine::Engine(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_lastTimeStamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setSingleShot(false);
|
||||
m_timer->setInterval(50);
|
||||
|
||||
connect(m_timer, &QTimer::timeout, this, &Engine::onTimerTick);
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
@ -165,6 +171,31 @@ 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);
|
||||
monitorData.insert("proxyStatistic", proxyServer()->currentStatistics());
|
||||
return monitorData;
|
||||
}
|
||||
|
||||
void Engine::onTimerTick()
|
||||
{
|
||||
qint64 timestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||
qint64 deltaTime = timestamp - m_lastTimeStamp;
|
||||
m_lastTimeStamp = timestamp;
|
||||
|
||||
m_currentTimeCounter += deltaTime;
|
||||
if (m_currentTimeCounter >= 1000) {
|
||||
// One second passed, do second tick
|
||||
m_proxyServer->tick();
|
||||
m_monitorServer->updateClients(createServerStatistic());
|
||||
m_currentTimeCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::clean()
|
||||
{
|
||||
if (m_monitorServer) {
|
||||
@ -195,9 +226,14 @@ void Engine::setRunning(bool running)
|
||||
if (m_running == running)
|
||||
return;
|
||||
|
||||
//qCDebug(dcEngine()) << "----------------------------------------------------------";
|
||||
qCDebug(dcEngine()) << "Engine is" << (running ? "now running." : "not running any more.");
|
||||
//qCDebug(dcEngine()) << "----------------------------------------------------------";
|
||||
|
||||
if (running) {
|
||||
m_timer->start();
|
||||
} else {
|
||||
m_timer->stop();
|
||||
}
|
||||
|
||||
m_running = running;
|
||||
emit runningChanged(m_running);
|
||||
}
|
||||
|
||||
@ -23,7 +23,9 @@
|
||||
#define ENGINE_H
|
||||
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QHostAddress>
|
||||
#include <QSslConfiguration>
|
||||
|
||||
@ -66,6 +68,11 @@ private:
|
||||
~Engine();
|
||||
static Engine *s_instance;
|
||||
|
||||
QTimer *m_timer = nullptr;
|
||||
qint64 m_lastTimeStamp = 0;
|
||||
int m_currentTimeCounter = 0;
|
||||
qint64 m_runTime = 0;
|
||||
|
||||
bool m_running = false;
|
||||
bool m_developerMode = false;
|
||||
|
||||
@ -75,10 +82,13 @@ private:
|
||||
WebSocketServer *m_webSocketServer = nullptr;
|
||||
MonitorServer *m_monitorServer = nullptr;
|
||||
|
||||
QVariantMap createServerStatistic();
|
||||
|
||||
signals:
|
||||
void runningChanged(bool running);
|
||||
|
||||
private slots:
|
||||
void onTimerTick();
|
||||
void clean();
|
||||
void setRunning(bool running);
|
||||
|
||||
|
||||
@ -32,10 +32,7 @@ MonitorServer::MonitorServer(const QString &serverName, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_serverName(serverName)
|
||||
{
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setInterval(1000);
|
||||
m_timer->setSingleShot(false);
|
||||
connect(m_timer, &QTimer::timeout, this, &MonitorServer::onTimeout);
|
||||
|
||||
}
|
||||
|
||||
MonitorServer::~MonitorServer()
|
||||
@ -51,36 +48,12 @@ bool MonitorServer::running() const
|
||||
return m_server->isListening();
|
||||
}
|
||||
|
||||
QVariantMap MonitorServer::createMonitorData()
|
||||
{
|
||||
QVariantMap monitorData;
|
||||
monitorData.insert("serverName", Engine::instance()->configuration()->serverName());
|
||||
monitorData.insert("serverVersion", SERVER_VERSION_STRING);
|
||||
monitorData.insert("apiVersion", API_VERSION_STRING);
|
||||
monitorData.insert("proxyStatistic", Engine::instance()->proxyServer()->currentStatistics());
|
||||
return monitorData;
|
||||
}
|
||||
|
||||
void MonitorServer::sendMonitorData(QLocalSocket *clientConnection, const QVariantMap &dataMap)
|
||||
{
|
||||
clientConnection->write(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Compact) + '\n');
|
||||
clientConnection->flush();
|
||||
}
|
||||
|
||||
void MonitorServer::onTimeout()
|
||||
{
|
||||
// If no client left or no server running, stop the timer
|
||||
if (m_clients.isEmpty() || !m_server)
|
||||
m_timer->stop();
|
||||
|
||||
QVariantMap dataMap = createMonitorData();
|
||||
|
||||
// Send each monitor the current data
|
||||
foreach (QLocalSocket *clientConnection, m_clients) {
|
||||
sendMonitorData(clientConnection, dataMap);
|
||||
}
|
||||
}
|
||||
|
||||
void MonitorServer::onMonitorConnected()
|
||||
{
|
||||
QLocalSocket *clientConnection = m_server->nextPendingConnection();
|
||||
@ -89,12 +62,6 @@ void MonitorServer::onMonitorConnected()
|
||||
m_clients.append(clientConnection);
|
||||
|
||||
qCDebug(dcMonitorServer()) << "New monitor connected.";
|
||||
|
||||
if (!m_timer->isActive()) {
|
||||
// Send the data right the way
|
||||
onTimeout();
|
||||
m_timer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void MonitorServer::onMonitorDisconnected()
|
||||
@ -131,7 +98,6 @@ void MonitorServer::startServer()
|
||||
|
||||
void MonitorServer::stopServer()
|
||||
{
|
||||
m_timer->stop();
|
||||
if (!m_server)
|
||||
return;
|
||||
|
||||
@ -145,4 +111,12 @@ void MonitorServer::stopServer()
|
||||
m_server = nullptr;
|
||||
}
|
||||
|
||||
void MonitorServer::updateClients(const QVariantMap &dataMap)
|
||||
{
|
||||
// Send each monitor the current data
|
||||
foreach (QLocalSocket *clientConnection, m_clients) {
|
||||
sendMonitorData(clientConnection, dataMap);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -41,20 +41,19 @@ public:
|
||||
private:
|
||||
QString m_serverName;
|
||||
QLocalServer *m_server = nullptr;
|
||||
QTimer *m_timer = nullptr;
|
||||
QList<QLocalSocket *> m_clients;
|
||||
|
||||
QVariantMap createMonitorData();
|
||||
void sendMonitorData(QLocalSocket *clientConnection, const QVariantMap &dataMap);
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
void onMonitorConnected();
|
||||
void onMonitorDisconnected();
|
||||
|
||||
public slots:
|
||||
void startServer();
|
||||
void stopServer();
|
||||
|
||||
void updateClients(const QVariantMap &dataMap);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -88,6 +88,16 @@ void ProxyClient::setTunnelConnected(bool isTunnelConnected)
|
||||
}
|
||||
}
|
||||
|
||||
QString ProxyClient::userName() const
|
||||
{
|
||||
return m_userName;
|
||||
}
|
||||
|
||||
void ProxyClient::setUserName(const QString &userName)
|
||||
{
|
||||
m_userName = userName;
|
||||
}
|
||||
|
||||
TransportInterface *ProxyClient::interface() const
|
||||
{
|
||||
return m_interface;
|
||||
@ -133,6 +143,26 @@ void ProxyClient::setNonce(const QString &nonce)
|
||||
m_nonce = nonce;
|
||||
}
|
||||
|
||||
quint64 ProxyClient::rxDataCount() const
|
||||
{
|
||||
return m_rxDataCount;
|
||||
}
|
||||
|
||||
void ProxyClient::addRxDataCount(int dataCount)
|
||||
{
|
||||
m_rxDataCount += static_cast<quint64>(dataCount);
|
||||
}
|
||||
|
||||
quint64 ProxyClient::txDataCount() const
|
||||
{
|
||||
return m_txDataCount;
|
||||
}
|
||||
|
||||
void ProxyClient::addTxDataCount(int dataCount)
|
||||
{
|
||||
m_txDataCount += static_cast<quint64>(dataCount);
|
||||
}
|
||||
|
||||
void ProxyClient::sendData(const QByteArray &data)
|
||||
{
|
||||
if (!m_interface)
|
||||
@ -157,6 +187,7 @@ QDebug operator<<(QDebug debug, ProxyClient *proxyClient)
|
||||
}
|
||||
debug.nospace() << proxyClient->interface()->serverName();
|
||||
debug.nospace() << ", " << proxyClient->clientId().toString();
|
||||
debug.nospace() << ", " << proxyClient->userName();
|
||||
debug.nospace() << ", " << proxyClient->peerAddress().toString();
|
||||
debug.nospace() << ", " << proxyClient->creationTimeString() << ") ";
|
||||
return debug;
|
||||
|
||||
@ -51,6 +51,9 @@ public:
|
||||
bool isTunnelConnected() const;
|
||||
void setTunnelConnected(bool isTunnelConnected);
|
||||
|
||||
QString userName() const;
|
||||
void setUserName(const QString &userName);
|
||||
|
||||
TransportInterface *interface() const;
|
||||
|
||||
// Properties from auth request
|
||||
@ -66,6 +69,12 @@ public:
|
||||
QString nonce() const;
|
||||
void setNonce(const QString &nonce);
|
||||
|
||||
quint64 rxDataCount() const;
|
||||
void addRxDataCount(int dataCount);
|
||||
|
||||
quint64 txDataCount() const;
|
||||
void addTxDataCount(int dataCount);
|
||||
|
||||
// Actions for this client
|
||||
void sendData(const QByteArray &data);
|
||||
void killConnection(const QString &reason);
|
||||
@ -86,6 +95,11 @@ private:
|
||||
QString m_token;
|
||||
QString m_nonce;
|
||||
|
||||
QString m_userName;
|
||||
|
||||
quint64 m_rxDataCount = 0;
|
||||
quint64 m_txDataCount = 0;
|
||||
|
||||
signals:
|
||||
void authenticated();
|
||||
void tunnelConnected();
|
||||
|
||||
@ -65,6 +65,7 @@ QVariantMap ProxyServer::currentStatistics()
|
||||
QVariantMap statisticsMap;
|
||||
statisticsMap.insert("clientCount", m_proxyClients.count());
|
||||
statisticsMap.insert("tunnelCount", m_tunnels.count());
|
||||
statisticsMap.insert("troughput", m_troughput);
|
||||
|
||||
// Create client list
|
||||
QVariantList clientList;
|
||||
@ -76,7 +77,10 @@ QVariantMap ProxyServer::currentStatistics()
|
||||
clientMap.insert("authenticated", client->isAuthenticated());
|
||||
clientMap.insert("tunnelConnected", client->isTunnelConnected());
|
||||
clientMap.insert("name", client->name());
|
||||
clientMap.insert("userName", client->userName());
|
||||
clientMap.insert("uuid", client->uuid());
|
||||
clientMap.insert("rxDataCount", client->rxDataCount());
|
||||
clientMap.insert("txDataCount", client->txDataCount());
|
||||
clientList.append(clientMap);
|
||||
}
|
||||
statisticsMap.insert("clients", clientList);
|
||||
@ -242,6 +246,11 @@ void ProxyServer::onClientDataAvailable(const QUuid &clientId, const QByteArray
|
||||
Q_ASSERT_X(remoteClient, "ProxyServer", "Tunnel existing but not tunnel client available");
|
||||
Q_ASSERT_X(m_tunnels.contains(proxyClient->token()), "ProxyServer", "Tunnel connect but not existing");
|
||||
|
||||
// Calculate server statisitcs
|
||||
m_troughputCounter += data.count();
|
||||
proxyClient->addRxDataCount(data.count());
|
||||
remoteClient->addTxDataCount(data.count());
|
||||
|
||||
qCDebug(dcProxyServerTraffic()) << "Pipe tunnel data:";
|
||||
qCDebug(dcProxyServerTraffic()) << " --> from" << proxyClient;
|
||||
qCDebug(dcProxyServerTraffic()) << " --> to" << remoteClient;
|
||||
@ -338,4 +347,10 @@ void ProxyServer::stopServer()
|
||||
setRunning(false);
|
||||
}
|
||||
|
||||
void ProxyServer::tick()
|
||||
{
|
||||
m_troughput = m_troughputCounter;
|
||||
m_troughputCounter = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -63,6 +63,10 @@ private:
|
||||
// Token, Tunnel
|
||||
QHash<QString, TunnelConnection> m_tunnels;
|
||||
|
||||
// Statistic measurments
|
||||
int m_troughput = 0;
|
||||
int m_troughputCounter = 0;
|
||||
|
||||
void setRunning(bool running);
|
||||
|
||||
ProxyClient *getRemoteClient(ProxyClient *proxyClient);
|
||||
@ -84,6 +88,8 @@ public slots:
|
||||
void startServer();
|
||||
void stopServer();
|
||||
|
||||
void tick();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -105,6 +105,22 @@ QString TerminalWindow::getDurationString(uint timestamp)
|
||||
return res.sprintf("%02d:%02d:%02d", hours, minutes, seconds);
|
||||
}
|
||||
|
||||
QString TerminalWindow::humanReadableTraffic(int bytes)
|
||||
{
|
||||
double dataCount = bytes;
|
||||
QStringList list;
|
||||
list << "KB" << "MB" << "GB" << "TB";
|
||||
|
||||
QStringListIterator i(list);
|
||||
QString unit("B");
|
||||
|
||||
while(dataCount >= 1024.0 && i.hasNext()) {
|
||||
unit = i.next();
|
||||
dataCount /= 1024.0;
|
||||
}
|
||||
return QString().setNum(dataCount,'f',2) + " " + unit;
|
||||
}
|
||||
|
||||
void TerminalWindow::resizeWindow()
|
||||
{
|
||||
int terminalSizeX;
|
||||
@ -146,12 +162,13 @@ void TerminalWindow::drawWindowBorder(WINDOW *window)
|
||||
|
||||
void TerminalWindow::paintHeader()
|
||||
{
|
||||
QString headerString = QString(" Server: %1 %2 | API version %3 | Clients: %4 | Tunnels %5 | %6 ")
|
||||
QString headerString = QString(" Server: %1 %2 | API version %3 | Clients: %4 | Tunnels %5 | %6 | %7 ")
|
||||
.arg(m_dataMap.value("serverName", "-").toString())
|
||||
.arg(m_dataMap.value("serverVersion", "-").toString())
|
||||
.arg(m_dataMap.value("apiVersion", "-").toString())
|
||||
.arg(m_dataMap.value("proxyStatistic").toMap().value("clientCount", 0).toInt())
|
||||
.arg(m_dataMap.value("proxyStatistic").toMap().value("tunnelCount", 0).toInt())
|
||||
.arg(humanReadableTraffic(m_dataMap.value("proxyStatistic").toMap().value("troughput", 0).toInt()) + " / s", - 13)
|
||||
.arg((m_view == ViewClients ? "-- Clients --" : "-- Tunnels --"));
|
||||
|
||||
int delta = m_terminalSizeX - headerString.count();
|
||||
@ -164,7 +181,6 @@ void TerminalWindow::paintHeader()
|
||||
wattron(m_headerWindow, A_BOLD | COLOR_PAIR(1));
|
||||
mvwprintw(m_headerWindow, 1, 2, convertString(headerString));
|
||||
wattroff(m_headerWindow, A_BOLD | COLOR_PAIR(1));
|
||||
drawWindowBorder(m_headerWindow);
|
||||
}
|
||||
|
||||
void TerminalWindow::paintContentClients()
|
||||
@ -179,11 +195,15 @@ void TerminalWindow::paintContentClients()
|
||||
uint timeStamp = clientMap.value("timestamp").toUInt();
|
||||
QString clientConnectionTime = QDateTime::fromTime_t(timeStamp).toString("dd.MM.yyyy hh:mm:ss");
|
||||
|
||||
QString clientPrint = QString("%1 | %2 | %3 | %4 | %5 | %6 | %7")
|
||||
int rxDataCountBytes = clientMap.value("rxDataCount").toInt();
|
||||
int txDataCountBytes = clientMap.value("txDataCount").toInt();
|
||||
|
||||
QString clientPrint = QString("%1 | %2 | %3 | RX: %4 | TX: %5 | %6 | %7 | %8")
|
||||
.arg(clientConnectionTime)
|
||||
.arg(clientMap.value("duration").toString())
|
||||
.arg(clientMap.value("address").toString(), - 16)
|
||||
.arg(clientMap.value("uuid").toString())
|
||||
.arg(humanReadableTraffic(rxDataCountBytes), - 10)
|
||||
.arg(humanReadableTraffic(txDataCountBytes), - 10)
|
||||
.arg((clientMap.value("authenticated").toBool() ? "A" : "-"))
|
||||
.arg((clientMap.value("tunnelConnected").toBool() ? "T" : "-"))
|
||||
.arg(clientMap.value("name").toString(), -30);
|
||||
@ -192,8 +212,6 @@ void TerminalWindow::paintContentClients()
|
||||
i++;
|
||||
}
|
||||
|
||||
// Draw borders
|
||||
drawWindowBorder(m_contentWindow);
|
||||
}
|
||||
|
||||
void TerminalWindow::paintContentTunnels()
|
||||
@ -209,21 +227,21 @@ void TerminalWindow::paintContentTunnels()
|
||||
uint timeStamp = tunnelMap.value("timestamp").toUInt();
|
||||
QString tunnelConnectionTime = QDateTime::fromTime_t(timeStamp).toString("dd.MM.yyyy hh:mm:ss");
|
||||
|
||||
QString tunnelPrint = QString("%1 | %2 %3 %4 %5 %6")
|
||||
|
||||
QString tunnelPrint = QString("%1 | %2 | %3 | %4 | %5 (%6) <---> %7 (%8)")
|
||||
.arg(tunnelConnectionTime)
|
||||
.arg(clientOne.value("address").toString(), - 16)
|
||||
.arg(getDurationString(timeStamp))
|
||||
.arg(humanReadableTraffic(clientOne.value("rxDataCount").toInt() + clientOne.value("txDataCount").toInt()), - 10)
|
||||
.arg(clientOne.value("userName").toString())
|
||||
.arg(clientOne.value("name").toString())
|
||||
.arg(" <---> ")
|
||||
.arg(clientTwo.value("address").toString(), - 16)
|
||||
.arg(clientOne.value("address").toString())
|
||||
.arg(clientTwo.value("name").toString())
|
||||
.arg(clientTwo.value("address").toString())
|
||||
;
|
||||
|
||||
mvwprintw(m_contentWindow, i, 2, convertString(tunnelPrint));
|
||||
i++;
|
||||
}
|
||||
|
||||
// Draw borders
|
||||
drawWindowBorder(m_contentWindow);
|
||||
}
|
||||
|
||||
void TerminalWindow::eventLoop()
|
||||
@ -232,7 +250,7 @@ void TerminalWindow::eventLoop()
|
||||
werase(m_headerWindow);
|
||||
werase(m_contentWindow);
|
||||
|
||||
resizeWindow();
|
||||
resizeWindow();
|
||||
|
||||
int keyInteger = getch();
|
||||
switch (keyInteger) {
|
||||
@ -268,9 +286,13 @@ void TerminalWindow::eventLoop()
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw borders
|
||||
drawWindowBorder(m_headerWindow);
|
||||
drawWindowBorder(m_contentWindow);
|
||||
|
||||
wrefresh(m_headerWindow);
|
||||
wrefresh(m_contentWindow);
|
||||
//refresh();
|
||||
refresh();
|
||||
|
||||
// Reinvoke the method for the next event loop run
|
||||
//QMetaObject::invokeMethod(this, "eventLoop", Qt::QueuedConnection);
|
||||
|
||||
@ -59,6 +59,8 @@ private:
|
||||
const char *convertString(const QString &string);
|
||||
QString getDurationString(uint timestamp);
|
||||
|
||||
QString humanReadableTraffic(int bytes);
|
||||
|
||||
// content paint methods
|
||||
void resizeWindow();
|
||||
void drawWindowBorder(WINDOW *window);
|
||||
|
||||
Reference in New Issue
Block a user