stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
This commit is contained in:
1 parent
a3783b5f55
commit
38c9f229bc
1272 files changed
+968388
-1
No files matched your search
@@ -0,0 +1,191 @@
|
||||
// networksettingspage.cpp — Network configuration form
|
||||
#include "networksettingspage.h"
|
||||
#include "../transport/config_updater.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QNetworkInterface>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
static const char* SECTION = "server:lan";
|
||||
|
||||
NetworkSettingsPage::NetworkSettingsPage(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(12);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto* title = new QLabel("Listen Address", this);
|
||||
title->setStyleSheet("font-weight: bold; font-size: 13px;");
|
||||
layout->addWidget(title);
|
||||
|
||||
// Interface
|
||||
auto* ifRow = new QHBoxLayout();
|
||||
ifRow->addWidget(new QLabel("Interface:", this));
|
||||
m_interfaceCombo = new QComboBox(this);
|
||||
m_interfaceCombo->setMinimumWidth(180);
|
||||
ifRow->addWidget(m_interfaceCombo, 1);
|
||||
layout->addLayout(ifRow);
|
||||
|
||||
// IP
|
||||
auto* ipRow = new QHBoxLayout();
|
||||
ipRow->addWidget(new QLabel("IP Address:", this));
|
||||
m_ipCombo = new QComboBox(this);
|
||||
m_ipCombo->setEditable(true);
|
||||
m_ipCombo->setMinimumWidth(180);
|
||||
ipRow->addWidget(m_ipCombo, 1);
|
||||
layout->addLayout(ipRow);
|
||||
|
||||
// Port
|
||||
auto* portRow = new QHBoxLayout();
|
||||
portRow->addWidget(new QLabel("Port:", this));
|
||||
m_portSpin = new QSpinBox(this);
|
||||
m_portSpin->setRange(1, 65535);
|
||||
m_portSpin->setValue(1333);
|
||||
m_portSpin->setMinimumWidth(100);
|
||||
portRow->addWidget(m_portSpin);
|
||||
portRow->addStretch();
|
||||
layout->addLayout(portRow);
|
||||
|
||||
// Protocol
|
||||
auto* protoRow = new QHBoxLayout();
|
||||
protoRow->addWidget(new QLabel("Protocol:", this));
|
||||
m_protoCombo = new QComboBox(this);
|
||||
m_protoCombo->addItems({"UDP", "TCP"});
|
||||
m_protoCombo->setMinimumWidth(100);
|
||||
protoRow->addWidget(m_protoCombo);
|
||||
protoRow->addStretch();
|
||||
layout->addLayout(protoRow);
|
||||
|
||||
auto* note = new QLabel("Changes take effect after restart.", this);
|
||||
note->setStyleSheet("color: gray; font-size: 11px;");
|
||||
layout->addWidget(note);
|
||||
|
||||
layout->addStretch();
|
||||
|
||||
populateInterfaces();
|
||||
connect(m_interfaceCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &NetworkSettingsPage::onInterfaceChanged);
|
||||
}
|
||||
|
||||
void NetworkSettingsPage::loadFromConfig(const QString& configPath) {
|
||||
// Read [server:lan] section from INI file
|
||||
QString addr, netif, transport;
|
||||
QFile f(configPath);
|
||||
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
bool inSection = false;
|
||||
QTextStream in(&f);
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine();
|
||||
if (line.startsWith('[') && line.endsWith(']')) {
|
||||
inSection = (line.mid(1, line.length() - 2) == SECTION);
|
||||
continue;
|
||||
}
|
||||
if (!inSection || !line.contains('=')) continue;
|
||||
QString key = line.section('=', 0, 0).trimmed();
|
||||
QString val = line.section('=', 1).trimmed();
|
||||
if (key == "addr") addr = val;
|
||||
else if (key == "netif") netif = val;
|
||||
else if (key == "transport") transport = val;
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
|
||||
// Parse addr: IP:port
|
||||
QString ip;
|
||||
if (!addr.isEmpty()) {
|
||||
int lastColon = addr.lastIndexOf(':');
|
||||
if (lastColon > 0) {
|
||||
ip = addr.left(lastColon);
|
||||
int port = addr.mid(lastColon + 1).toInt();
|
||||
if (port > 0 && port <= 65535) m_portSpin->setValue(port);
|
||||
}
|
||||
}
|
||||
|
||||
// Set protocol
|
||||
int protoIdx = (transport == "tcp") ? 1 : 0;
|
||||
m_protoCombo->setCurrentIndex(protoIdx);
|
||||
|
||||
// Set interface
|
||||
int ifIdx = m_interfaceCombo->findText(netif);
|
||||
if (ifIdx >= 0) m_interfaceCombo->setCurrentIndex(ifIdx);
|
||||
|
||||
// Set IP — populate addresses first, then select
|
||||
populateAddresses(netif.isEmpty() ? QString() : netif);
|
||||
if (ip.isEmpty() || ip == "0.0.0.0") ip = "Auto (0.0.0.0)";
|
||||
int ipIdx = m_ipCombo->findText(ip);
|
||||
if (ipIdx >= 0)
|
||||
m_ipCombo->setCurrentIndex(ipIdx);
|
||||
else
|
||||
m_ipCombo->setCurrentText(ip);
|
||||
}
|
||||
|
||||
void NetworkSettingsPage::saveToConfig(const QString& configPath) const {
|
||||
// addr
|
||||
QString ip = m_ipCombo->currentText().trimmed();
|
||||
if (ip.isEmpty() || ip == "Auto (0.0.0.0)") ip = "0.0.0.0";
|
||||
config_update_option(configPath, SECTION, "addr",
|
||||
QString("%1:%2").arg(ip).arg(m_portSpin->value()),
|
||||
CONFIG_UPDATE_REPLACE);
|
||||
|
||||
// netif: set or remove (empty value means no netif binding)
|
||||
QString iface = m_interfaceCombo->currentText();
|
||||
if (iface.startsWith("Auto"))
|
||||
iface.clear();
|
||||
config_update_option(configPath, SECTION, "netif", iface, CONFIG_UPDATE_REPLACE);
|
||||
|
||||
// transport
|
||||
config_update_option(configPath, SECTION, "transport",
|
||||
m_protoCombo->currentText().toLower(),
|
||||
CONFIG_UPDATE_REPLACE);
|
||||
|
||||
// IPv6 dual-stack: always add [server:lan6] with same port
|
||||
config_update_option(configPath, "server:lan6", "addr",
|
||||
QString("[::]:%1").arg(m_portSpin->value()),
|
||||
CONFIG_UPDATE_REPLACE);
|
||||
}
|
||||
|
||||
void NetworkSettingsPage::onInterfaceChanged(int index) {
|
||||
Q_UNUSED(index);
|
||||
QString iface = m_interfaceCombo->currentText();
|
||||
populateAddresses(iface.startsWith("Auto") ? QString() : iface);
|
||||
}
|
||||
|
||||
void NetworkSettingsPage::populateInterfaces() {
|
||||
m_interfaceCombo->addItem("Auto (any)");
|
||||
for (const QNetworkInterface& iface : QNetworkInterface::allInterfaces()) {
|
||||
if (iface.flags() & QNetworkInterface::IsLoopBack) continue;
|
||||
if (!(iface.flags() & QNetworkInterface::IsUp)) continue;
|
||||
m_interfaceCombo->addItem(iface.name());
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSettingsPage::populateAddresses(const QString& ifaceName) {
|
||||
QString current = m_ipCombo->currentText();
|
||||
m_ipCombo->clear();
|
||||
m_ipCombo->addItem("Auto (0.0.0.0)");
|
||||
|
||||
if (ifaceName.isEmpty()) {
|
||||
for (const QNetworkInterface& iface : QNetworkInterface::allInterfaces()) {
|
||||
if (iface.flags() & QNetworkInterface::IsLoopBack) continue;
|
||||
if (!(iface.flags() & QNetworkInterface::IsUp)) continue;
|
||||
for (const QNetworkAddressEntry& entry : iface.addressEntries()) {
|
||||
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol)
|
||||
m_ipCombo->addItem(entry.ip().toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName);
|
||||
if (iface.isValid()) {
|
||||
for (const QNetworkAddressEntry& entry : iface.addressEntries()) {
|
||||
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol)
|
||||
m_ipCombo->addItem(entry.ip().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int idx = m_ipCombo->findText(current);
|
||||
if (idx >= 0) m_ipCombo->setCurrentIndex(idx);
|
||||
}
|
||||
Reference in new issue
Block a user