diff --git a/include/global/DataStore.hpp b/include/global/DataStore.hpp
index f87c2ff..79aba24 100644
--- a/include/global/DataStore.hpp
+++ b/include/global/DataStore.hpp
@@ -115,6 +115,7 @@ namespace Configs {
// Socks & HTTP Inbound
QString inbound_address = "127.0.0.1";
int inbound_socks_port = 2080; // Mixed, actually
+ bool random_inbound_port = false;
QString custom_inbound = "{\"inbounds\": []}";
// Routing
diff --git a/include/ui/setting/dialog_basic_settings.ui b/include/ui/setting/dialog_basic_settings.ui
index 0ab9daf..58de77e 100644
--- a/include/ui/setting/dialog_basic_settings.ui
+++ b/include/ui/setting/dialog_basic_settings.ui
@@ -89,6 +89,16 @@
+ -
+
+
+ <html><head/><body><p>Selects a random available port on every run</p></body></html>
+
+
+ Random port
+
+
+
diff --git a/src/global/Configs.cpp b/src/global/Configs.cpp
index ec76bd1..c482575 100644
--- a/src/global/Configs.cpp
+++ b/src/global/Configs.cpp
@@ -245,6 +245,7 @@ namespace Configs {
_add(new configItem("current_group", ¤t_group, itemType::integer));
_add(new configItem("inbound_address", &inbound_address, itemType::string));
_add(new configItem("inbound_socks_port", &inbound_socks_port, itemType::integer));
+ _add(new configItem("random_inbound_port", &random_inbound_port, itemType::boolean));
_add(new configItem("log_level", &log_level, itemType::string));
_add(new configItem("mux_protocol", &mux_protocol, itemType::string));
_add(new configItem("mux_concurrency", &mux_concurrency, itemType::integer));
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index c06d422..b9ab73b 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -52,6 +52,7 @@
#include
#include
#include <3rdparty/QHotkey/qhotkey.h>
+#include <3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp>
#include
#include
@@ -125,6 +126,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
runOnUiThread([=] { show_log_impl(log); });
};
+ // Listen port if random
+ if (Configs::dataStore->random_inbound_port)
+ {
+ Configs::dataStore->inbound_socks_port = MkPort();
+ }
+
// Prepare core
Configs::dataStore->core_port = MkPort();
if (Configs::dataStore->core_port <= 0) Configs::dataStore->core_port = 19810;
@@ -688,6 +695,15 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
if (info.contains("UpdateDisableTray")) {
tray->setVisible(!Configs::dataStore->disable_tray);
}
+ if (info.contains("NeedChoosePort"))
+ {
+ Configs::dataStore->inbound_socks_port = MkPort();
+ if (Configs::dataStore->spmode_system_proxy)
+ {
+ set_spmode_system_proxy(false);
+ set_spmode_system_proxy(true);
+ }
+ }
auto suggestRestartProxy = Configs::dataStore->Save();
if (info.contains("RouteChanged")) {
Configs::dataStore->routing->Save();
@@ -700,7 +716,7 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
if (info.contains("VPNChanged") && Configs::dataStore->spmode_vpn) {
MessageBoxWarning(tr("Tun Settings changed"), tr("Restart Tun to take effect."));
}
- if (suggestRestartProxy && Configs::dataStore->started_id >= 0 &&
+ if ((info.contains("NeedChoosePort") || suggestRestartProxy) && Configs::dataStore->started_id >= 0 &&
QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) {
profile_start(Configs::dataStore->started_id);
}
diff --git a/src/ui/setting/dialog_basic_settings.cpp b/src/ui/setting/dialog_basic_settings.cpp
index d4f05bd..bf14a05 100644
--- a/src/ui/setting/dialog_basic_settings.cpp
+++ b/src/ui/setting/dialog_basic_settings.cpp
@@ -31,6 +31,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
D_LOAD_COMBO_STRING(log_level)
CACHE.custom_inbound = Configs::dataStore->custom_inbound;
D_LOAD_INT(inbound_socks_port)
+ ui->random_listen_port->setChecked(Configs::dataStore->random_inbound_port);
D_LOAD_INT(test_concurrent)
D_LOAD_STRING(test_latency_url)
D_LOAD_BOOL(disable_tray)
@@ -43,6 +44,16 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
connect(ui->disable_tray, &QCheckBox::stateChanged, this, [=](const bool &) {
CACHE.updateDisableTray = true;
});
+ connect(ui->random_listen_port, &QCheckBox::checkStateChanged, this, [=](const bool &state)
+ {
+ if (state)
+ {
+ ui->inbound_socks_port->setDisabled(true);
+ } else
+ {
+ ui->inbound_socks_port->setDisabled(false);
+ }
+ });
#ifndef Q_OS_WIN
ui->proxy_scheme_box->hide();
@@ -172,11 +183,17 @@ DialogBasicSettings::~DialogBasicSettings() {
void DialogBasicSettings::accept() {
// Common
+ bool needChoosePort = false;
D_SAVE_STRING(inbound_address)
D_SAVE_COMBO_STRING(log_level)
Configs::dataStore->custom_inbound = CACHE.custom_inbound;
D_SAVE_INT(inbound_socks_port)
+ if (!Configs::dataStore->random_inbound_port && ui->random_listen_port->isChecked())
+ {
+ needChoosePort = true;
+ }
+ Configs::dataStore->random_inbound_port = ui->random_listen_port->isChecked();
D_SAVE_INT(test_concurrent)
D_SAVE_STRING(test_latency_url)
D_SAVE_BOOL(disable_tray)
@@ -239,6 +256,7 @@ void DialogBasicSettings::accept() {
QStringList str{"UpdateDataStore"};
if (CACHE.needRestart) str << "NeedRestart";
if (CACHE.updateDisableTray) str << "UpdateDisableTray";
+ if (needChoosePort) str << "NeedChoosePort";
MW_dialog_message(Dialog_DialogBasicSettings, str.join(","));
QDialog::accept();
}