- 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
68 lines
1.9 KiB
C++
68 lines
1.9 KiB
C++
// config_updater.cpp — Universal INI config file updater
|
|
#include "config_updater.h"
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
|
|
bool config_update_option(const QString& filePath, const QString& section,
|
|
const QString& param, const QString& value, int flags)
|
|
{
|
|
QStringList lines;
|
|
|
|
QFile f(filePath);
|
|
if (f.exists()) {
|
|
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
return false;
|
|
QTextStream in(&f);
|
|
while (!in.atEnd())
|
|
lines.append(in.readLine());
|
|
f.close();
|
|
}
|
|
|
|
const QString sectionHdr = "[" + section + "]";
|
|
const QString newLine = param + "=" + value;
|
|
|
|
int secIdx = -1;
|
|
for (int i = 0; i < lines.size(); i++) {
|
|
if (lines[i].trimmed() == sectionHdr) { secIdx = i; break; }
|
|
}
|
|
|
|
int secEnd = lines.size();
|
|
if (secIdx >= 0) {
|
|
for (int i = secIdx + 1; i < lines.size(); i++) {
|
|
if (lines[i].trimmed().startsWith('[')) { secEnd = i; break; }
|
|
}
|
|
}
|
|
|
|
if (secIdx >= 0) {
|
|
int ins = secEnd;
|
|
while (ins > secIdx + 1 && lines[ins - 1].trimmed().isEmpty())
|
|
ins--;
|
|
|
|
if (flags == CONFIG_UPDATE_REPLACE) {
|
|
int paramIdx = -1;
|
|
for (int i = secIdx + 1; i < secEnd; i++) {
|
|
if (lines[i].trimmed().startsWith(param + "=")) { paramIdx = i; break; }
|
|
}
|
|
if (paramIdx >= 0)
|
|
lines[paramIdx] = newLine;
|
|
else
|
|
lines.insert(ins, newLine);
|
|
} else {
|
|
lines.insert(ins, newLine);
|
|
}
|
|
} else {
|
|
if (!lines.isEmpty() && !lines.last().trimmed().isEmpty())
|
|
lines.append("");
|
|
lines.append(sectionHdr);
|
|
lines.append(newLine);
|
|
}
|
|
|
|
if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
|
|
return false;
|
|
QTextStream out(&f);
|
|
for (const QString& line : lines)
|
|
out << line << "\n";
|
|
f.close();
|
|
return true;
|
|
}
|