metrics: RTT/loss histograms + Ed25519 signing + peer exchange via INIT handshake + file logging to stats/<peer>.dat

- etcp_metrics struct: 12-bucket RTT histogram, 11-bucket loss histogram, 10-min snapshots (>=200 pkts)
- Total counters: packets/bytes sent/rcvd, losses (retrans + probe gap detection)
- CSV append to <stats_dir>/<peer_id>.dat every 10 min
- Ed25519 pubkey exchange in INIT handshake (V3), always present
- Signed metrics exchange via ETCP_SECTION_METRICS (0x0A)
- Received metrics saved as from_<peer_id>.dat with signature hex
- on_metrics_rcvd callback in ETCP_BINDINGS
- stats_dir derived from config file path, mkdir'd at instance init
- Simplified versioning: ETCP_INIT_REQ_SIZE / ETCP_INIT_RESP_SIZE via sizeof
This commit is contained in:
Evgeny committed 2026-07-07 17:16:45 +03:00
1 parent f5c93266dc
commit 1889d23240
29 files changed
+1247 -53

No files matched your search

+23 -22
View File
@@ -4,20 +4,19 @@
#include "accountlist.h"
#include "invitedialog.h"
#include "joindialog.h"
#include "settingsdialog.h"
#include "invite_link.h"
#include "../db/db_manager.h"
#include "../transport/utun_node.h"
#include "../transport/node_config.h"
#include "../transport/gui_bridge.h"
#include <QSplitter>
#include <QCloseEvent>
#include <QApplication>
#include <QStyle>
#include <QMessageBox>
#include <QStandardPaths>
#include <QDir>
MainWindow::MainWindow(QWidget *parent, DbManager* db)
MainWindow::MainWindow(QWidget *parent, DbManager* db, const QString& cfgPath,
const QString& debugFile)
: QMainWindow(parent)
, m_channelList(nullptr)
, m_messageList(nullptr)
@@ -25,6 +24,8 @@ MainWindow::MainWindow(QWidget *parent, DbManager* db)
, m_trayIcon(nullptr)
, m_trayMenu(nullptr)
, m_db(db)
, m_cfgPath(cfgPath)
, m_cfgDebugFile(debugFile)
{
setWindowTitle("Chat");
resize(900, 600);
@@ -45,6 +46,8 @@ MainWindow::MainWindow(QWidget *parent, DbManager* db)
this, &MainWindow::showInviteDialog);
connect(m_channelList, &ChannelList::joinRequested,
this, &MainWindow::showJoinDialog);
connect(m_channelList, &ChannelList::settingsRequested,
this, &MainWindow::showSettings);
m_channelList->loadChannels();
m_accountList->loadAccounts();
@@ -57,7 +60,6 @@ MainWindow::MainWindow(QWidget *parent, DbManager* db)
MainWindow::~MainWindow() {
if (m_node) { m_node->stop(); delete m_node; m_node = nullptr; }
delete m_config;
}
void MainWindow::setupUi() {
@@ -81,20 +83,6 @@ void MainWindow::setupUi() {
}
void MainWindow::setupNode() {
QString configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
QDir().mkpath(configDir);
QString configPath = configDir + "/node.conf";
m_config = new NodeConfig(configPath);
if (!m_config->exists()) {
if (!m_config->create("chatgui", 1333)) {
qWarning("Failed to create node config");
return;
}
} else {
m_config->load();
}
m_node = new UtunNode(this);
connect(m_node, &UtunNode::error, this, [](const QString& msg) {
qWarning("UtunNode error: %s", qPrintable(msg));
@@ -106,7 +94,10 @@ void MainWindow::setupNode() {
qDebug("UtunNode stopped");
});
if (!m_node->start(configPath))
if (!m_cfgDebugFile.isEmpty())
m_node->setDebugFile(m_cfgDebugFile);
if (!m_node->start(m_cfgPath))
qWarning("Failed to start UtunNode");
}
@@ -125,6 +116,11 @@ void MainWindow::setupTray() {
m_trayIcon->setToolTip("Chat");
m_trayMenu = new QMenu(this);
QAction *settingsAction = m_trayMenu->addAction("Settings");
connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings);
m_trayMenu->addSeparator();
QAction *showAction = m_trayMenu->addAction("Show");
connect(showAction, &QAction::triggered, this, [this]() {
show();
@@ -163,8 +159,8 @@ void MainWindow::showInviteDialog(const QString& channelId) {
if (!m_db || !m_db->isOpen()) return;
QByteArray pubkey;
if (m_config && !m_config->pubKey().isEmpty())
pubkey = QByteArray::fromHex(m_config->pubKey().toLatin1());
if (m_node && m_node->isRunning())
pubkey = QByteArray::fromHex(m_node->pubKeyHex().toLatin1());
if (pubkey.size() != 32) {
QMessageBox::warning(this, "Error", "Failed to get node public key.");
@@ -193,3 +189,8 @@ void MainWindow::showJoinDialog() {
m_channelList->loadChannels();
}
}
void MainWindow::showSettings() {
SettingsDialog dlg(m_cfgPath, this);
dlg.exec();
}