refactor: STCP connections as ETCP links (is_tcp)
- Add is_tcp, tcp_link, tcp_reconnect_* fields to ETCP_LINK - Remove transport_link from ETCP_CONN, add tcp_link_count - stcp_link: replace embedded etcp_conn with pointer; add etcp_link backpointer - stcp_link: link_rx_cb routes ETCP data to etcp_conn_input - stcp_link: call on_close_cb in close - New TCP functions: etcp_link_enter_ready_tcp, etcp_tcp_link_start_connect, etcp_tcp_link_start_reconnect, tcp_link_close_cb, etcp_tcp_send - etcp_link_new: handle NULL conn for TCP links; skip enter_init for TCP - etcp_link_close: close stcp_link for TCP - etcp_encrypt_send: redirect TCP to etcp_tcp_send (skips AES-CCM) - tcp_server_on_link: create ETCP_LINK(is_tcp=1) + enter_ready_tcp - etcp_connect: TCP addrs -> etcp_tcp_link_start_connect - Remove ctx->tcp_link/tcp_ready - test_stcp_traffic: find stcp_link via links->is_tcp instead of transport_link - 66/68 tests pass; 2 STCP tests expected to fail (integration not complete)
This commit is contained in:
1 parent
937af4c26a
commit
d773f1724a
1705 files changed
+187
-1082154
No files matched your search
@@ -1,270 +0,0 @@
|
||||
// settingsdialog.cpp — Settings dialog with category list
|
||||
#include "settingsdialog.h"
|
||||
#include "networksettingspage.h"
|
||||
#include "databasesettingspage.h"
|
||||
#include "statuspage.h"
|
||||
#include "nodespage.h"
|
||||
#include "soundsettingspage.h"
|
||||
#include "audiodevicesettingspage.h"
|
||||
#include "storagesettingspage.h"
|
||||
#include "../transport/gui_bridge.h"
|
||||
#include "../../lib/mem.h"
|
||||
#include "../db/db_manager.h"
|
||||
#include "../transport/utun_node.h"
|
||||
extern "C" {
|
||||
#include "chat/chat_core.h"
|
||||
}
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
SettingsDialog::SettingsDialog(const QString& configPath, DbManager* db, UtunNode* node,
|
||||
AudioRecorder* recorder, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_configPath(configPath)
|
||||
{
|
||||
setWindowTitle("Settings");
|
||||
setMinimumSize(760, 460);
|
||||
setModal(true);
|
||||
|
||||
auto* mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// --- Left sidebar: category list ---
|
||||
m_categoryList = new QListWidget(this);
|
||||
m_categoryList->setFixedWidth(150);
|
||||
m_categoryList->setStyleSheet(
|
||||
"QListWidget { border: none; border-right: 1px solid palette(mid);"
|
||||
" background: palette(window); font-size: 13px; }"
|
||||
"QListWidget::item { padding: 10px 14px; }"
|
||||
"QListWidget::item:selected { background: #3390EC; color: white; }");
|
||||
m_categoryList->addItem("Profile");
|
||||
m_categoryList->addItem("Storage");
|
||||
m_categoryList->addItem("Network");
|
||||
m_categoryList->addItem("Database");
|
||||
m_categoryList->addItem("Status");
|
||||
m_categoryList->addItem("Nodes");
|
||||
m_categoryList->addItem("Sound");
|
||||
m_categoryList->addItem("Audio");
|
||||
mainLayout->addWidget(m_categoryList);
|
||||
|
||||
// --- Right panel: stacked pages ---
|
||||
auto* rightPanel = new QWidget(this);
|
||||
auto* rightLayout = new QVBoxLayout(rightPanel);
|
||||
rightLayout->setContentsMargins(20, 16, 20, 16);
|
||||
rightLayout->setSpacing(0);
|
||||
|
||||
m_pages = new QStackedWidget(rightPanel);
|
||||
|
||||
// Profile page
|
||||
auto* profilePage = new QWidget(m_pages);
|
||||
auto* profLayout = new QFormLayout(profilePage);
|
||||
profLayout->setContentsMargins(0, 12, 0, 0);
|
||||
auto* nameLabel = new QLabel("Display name:", profilePage);
|
||||
m_nicknameEdit = new QLineEdit(profilePage);
|
||||
m_nicknameEdit->setPlaceholderText("Your name (shown to others)");
|
||||
m_nicknameEdit->setMaxLength(32);
|
||||
m_nicknameEdit->setStyleSheet(
|
||||
"QLineEdit { border: 1px solid palette(mid); border-radius: 4px;"
|
||||
" padding: 6px 10px; font-size: 13px; background: palette(base); }");
|
||||
profLayout->addRow(nameLabel, m_nicknameEdit);
|
||||
|
||||
auto* sortLabel = new QLabel("Channel sorting:", profilePage);
|
||||
m_sortCombo = new QComboBox(profilePage);
|
||||
m_sortCombo->addItem("Alphabetical (A-Z)");
|
||||
m_sortCombo->addItem("Recent Activity");
|
||||
m_sortCombo->setStyleSheet(
|
||||
"QComboBox { border: 1px solid palette(mid); border-radius: 4px;"
|
||||
" padding: 6px 10px; font-size: 13px; background: palette(base); }");
|
||||
profLayout->addRow(sortLabel, m_sortCombo);
|
||||
|
||||
auto* joinLabel = new QLabel("Join requests:", profilePage);
|
||||
m_joinPolicyCombo = new QComboBox(profilePage);
|
||||
m_joinPolicyCombo->addItem("Auto-join");
|
||||
m_joinPolicyCombo->addItem("Ask before joining");
|
||||
m_joinPolicyCombo->addItem("Deny all");
|
||||
m_joinPolicyCombo->setStyleSheet(
|
||||
"QComboBox { border: 1px solid palette(mid); border-radius: 4px;"
|
||||
" padding: 6px 10px; font-size: 13px; background: palette(base); }");
|
||||
profLayout->addRow(joinLabel, m_joinPolicyCombo);
|
||||
m_pages->addWidget(profilePage);
|
||||
|
||||
// Storage page
|
||||
m_storagePage = new StorageSettingsPage(db, m_pages);
|
||||
m_storagePage->setConfigPath(m_configPath);
|
||||
m_pages->addWidget(m_storagePage);
|
||||
|
||||
// Network page
|
||||
m_networkPage = new NetworkSettingsPage(m_pages);
|
||||
m_pages->addWidget(m_networkPage);
|
||||
|
||||
// Database page
|
||||
m_databasePage = new DatabaseSettingsPage(db, m_pages);
|
||||
m_pages->addWidget(m_databasePage);
|
||||
|
||||
// Status page
|
||||
m_statusPage = new StatusPage(node, m_pages);
|
||||
m_pages->addWidget(m_statusPage);
|
||||
|
||||
// Nodes page
|
||||
m_nodesPage = new NodesPage(db, m_pages);
|
||||
m_pages->addWidget(m_nodesPage);
|
||||
|
||||
m_soundPage = new SoundSettingsPage(db, m_pages);
|
||||
m_pages->addWidget(m_soundPage);
|
||||
|
||||
m_audioDevicePage = new AudioDeviceSettingsPage(db, recorder, m_pages);
|
||||
m_audioDevicePage->setConfigPath(m_configPath);
|
||||
m_pages->addWidget(m_audioDevicePage);
|
||||
rightLayout->addWidget(m_pages, 1);
|
||||
|
||||
// --- Bottom buttons ---
|
||||
auto* btnLayout = new QHBoxLayout();
|
||||
btnLayout->setSpacing(8);
|
||||
btnLayout->addStretch();
|
||||
|
||||
auto* cancelBtn = new QPushButton("Cancel", rightPanel);
|
||||
cancelBtn->setFixedWidth(90);
|
||||
cancelBtn->setStyleSheet(
|
||||
"QPushButton { border: 1px solid palette(mid); border-radius: 4px;"
|
||||
" padding: 6px 16px; font-size: 13px; background: palette(button); }"
|
||||
"QPushButton:hover { background: palette(light); }");
|
||||
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
||||
btnLayout->addWidget(cancelBtn);
|
||||
|
||||
m_saveBtn = new QPushButton("Save", rightPanel);
|
||||
m_saveBtn->setFixedWidth(90);
|
||||
m_saveBtn->setDefault(true);
|
||||
m_saveBtn->setStyleSheet(
|
||||
"QPushButton { border: none; border-radius: 4px;"
|
||||
" padding: 6px 16px; font-size: 13px; font-weight: bold;"
|
||||
" background: #3390EC; color: white; }"
|
||||
"QPushButton:hover { background: #2B7ED4; }");
|
||||
connect(m_saveBtn, &QPushButton::clicked, this, &SettingsDialog::onSave);
|
||||
btnLayout->addWidget(m_saveBtn);
|
||||
|
||||
rightLayout->addLayout(btnLayout);
|
||||
mainLayout->addWidget(rightPanel, 1);
|
||||
|
||||
connect(m_categoryList, &QListWidget::currentRowChanged,
|
||||
this, &SettingsDialog::onCategoryChanged);
|
||||
|
||||
// Load current values
|
||||
loadProfileFromConfig(m_configPath);
|
||||
if (db) {
|
||||
int sortMode = db->getUiStateInt("channel_sort", 0);
|
||||
m_sortCombo->setCurrentIndex(sortMode == 1 ? 1 : 0);
|
||||
int joinPolicy = db->getUiStateInt("join_policy", 1);
|
||||
m_joinPolicyCombo->setCurrentIndex(joinPolicy >= 0 && joinPolicy <= 2 ? joinPolicy : 1);
|
||||
}
|
||||
m_networkPage->loadFromConfig(m_configPath);
|
||||
m_soundPage->loadFromDb();
|
||||
m_categoryList->setCurrentRow(0);
|
||||
}
|
||||
|
||||
void SettingsDialog::loadProfileFromConfig(const QString& path) {
|
||||
QFile f(path);
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) return;
|
||||
QTextStream in(&f);
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine().trimmed();
|
||||
if (line.startsWith("my_node_name=")) {
|
||||
QString nm = line.mid(QString("my_node_name=").size()).trimmed();
|
||||
m_nicknameEdit->setText(nm);
|
||||
m_oldNickname = nm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::onCategoryChanged(int row) {
|
||||
m_pages->setCurrentIndex(row);
|
||||
if (row == 1) m_storagePage->loadFromDb();
|
||||
if (row == 3) m_databasePage->refreshStatus();
|
||||
if (row == 4) m_statusPage->refreshStatus();
|
||||
if (row == 5) m_nodesPage->refreshNodes();
|
||||
if (row == 6) m_soundPage->loadFromDb();
|
||||
if (row == 7) m_audioDevicePage->loadFromDb();
|
||||
}
|
||||
|
||||
void SettingsDialog::onSave() {
|
||||
QString newName = m_nicknameEdit->text().trimmed();
|
||||
|
||||
/* update name in uTun if changed */
|
||||
if (newName != m_oldNickname) {
|
||||
char* name_copy = u_strdup(newName.toUtf8().constData());
|
||||
if (name_copy) gui_bridge_post_uasync_fn(chat_core_update_my_name_trampoline, name_copy);
|
||||
m_oldNickname = newName;
|
||||
}
|
||||
|
||||
// Save nickname to config
|
||||
QFile f(m_configPath);
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { accept(); return; }
|
||||
QString content = f.readAll();
|
||||
f.close();
|
||||
|
||||
QTextStream ts(&content);
|
||||
QStringList lines;
|
||||
while (!ts.atEnd()) lines << ts.readLine();
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (lines[i].trimmed().startsWith("my_node_name=")) {
|
||||
lines[i] = "my_node_name=" + newName;
|
||||
found = true;
|
||||
} else if (!found && lines[i].trimmed() == "[global]") {
|
||||
lines.insert(i + 1, "my_node_name=" + newName);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) lines << "my_node_name=" + newName;
|
||||
|
||||
f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
|
||||
f.write(lines.join('\n').toUtf8());
|
||||
f.close();
|
||||
|
||||
m_networkPage->saveToConfig(m_configPath);
|
||||
|
||||
/* save channel sort preference to ui_state */
|
||||
{
|
||||
const char* key = "channel_sort";
|
||||
QByteArray val = QByteArray::number(m_sortCombo->currentIndex());
|
||||
size_t klen = strlen(key), vlen = (size_t)val.size();
|
||||
size_t total = klen + 1 + vlen + 1;
|
||||
if (total <= 256) {
|
||||
void* arg = u_malloc(total);
|
||||
memcpy(arg, key, klen + 1);
|
||||
memcpy((char*)arg + klen + 1, val.constData(), vlen + 1);
|
||||
gui_bridge_post_uasync_fn(chat_core_save_ui_state_trampoline, arg);
|
||||
}
|
||||
}
|
||||
|
||||
m_soundPage->applyAndSave();
|
||||
m_audioDevicePage->applyAndSave();
|
||||
m_storagePage->applyAndSave();
|
||||
|
||||
/* save join_policy */
|
||||
{
|
||||
const char* key = "join_policy";
|
||||
int v = m_joinPolicyCombo->currentIndex();
|
||||
QByteArray val = QByteArray::number(v);
|
||||
size_t klen = strlen(key), vl = (size_t)val.size(), total = klen + 1 + vl + 1;
|
||||
if (total <= 256) {
|
||||
void* arg = u_malloc(total);
|
||||
memcpy(arg, key, klen + 1);
|
||||
memcpy((char*)arg + klen + 1, val.constData(), vl + 1);
|
||||
gui_bridge_post_uasync_fn(chat_core_save_ui_state_trampoline, arg);
|
||||
}
|
||||
if (!m_configPath.isEmpty()) {
|
||||
postChatSetting(m_configPath, "join_policy", v);
|
||||
}
|
||||
}
|
||||
accept();
|
||||
}
|
||||
Reference in new issue
Block a user