mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-22 02:01:08 +07:00
fix: Fix local proxy UI
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
#include "core/api/apiUtils.h"
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "core/defs.h"
|
||||
#include "portavailabilityhelper.h"
|
||||
#include "proxylogger.h"
|
||||
#include "settings.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <QSaveFile>
|
||||
#include <QSysInfo>
|
||||
#include <QStandardPaths>
|
||||
#include <QTcpServer>
|
||||
#include <QUuid>
|
||||
|
||||
ConfigManager::ConfigManager(const std::shared_ptr<Settings> &settings)
|
||||
@@ -84,18 +83,6 @@ QString ConfigManager::serializeConfig(const QJsonObject &config) const
|
||||
return QString::fromUtf8(QJsonDocument(config).toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
bool ConfigManager::isPortAvailable(int port) const
|
||||
{
|
||||
if (port < kProxyPortMin || port > kProxyPortMax) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QTcpServer server;
|
||||
const bool success = server.listen(QHostAddress::LocalHost, static_cast<quint16>(port));
|
||||
server.close();
|
||||
return success;
|
||||
}
|
||||
|
||||
std::optional<ConfigManager::ConfigData> ConfigManager::buildConfig(QString &errorDescription) const
|
||||
{
|
||||
errorDescription.clear();
|
||||
@@ -223,29 +210,30 @@ std::optional<ConfigManager::ConfigData> ConfigManager::buildConfigWithFetch(QSt
|
||||
data.parsedConfig = doc.object();
|
||||
|
||||
int selectedPort = resolveProxyPort(m_settings);
|
||||
const int startPort = selectedPort;
|
||||
const bool isUserDefinedPort = m_settings->isLocalProxyPortUserDefined();
|
||||
|
||||
bool found = false;
|
||||
for (int port = selectedPort; port <= kProxyPortMax; ++port) {
|
||||
if (isPortAvailable(port)) {
|
||||
selectedPort = port;
|
||||
found = true;
|
||||
break;
|
||||
if (!PortAvailabilityHelper::isPortAvailable(selectedPort)) {
|
||||
const bool canAutoSelect = !isUserDefinedPort && selectedPort == kDefaultProxyPort;
|
||||
if (canAutoSelect) {
|
||||
const auto freePort = PortAvailabilityHelper::findFirstAvailablePort(kDefaultProxyPort + 1, kProxyPortMax);
|
||||
if (!freePort) {
|
||||
errorDescription = QStringLiteral("No available local proxy port in range %1-%2")
|
||||
.arg(kDefaultProxyPort + 1)
|
||||
.arg(kProxyPortMax);
|
||||
ProxyLogger::getInstance().error(errorDescription);
|
||||
return std::nullopt;
|
||||
}
|
||||
selectedPort = *freePort;
|
||||
} else {
|
||||
errorDescription = QStringLiteral("Local proxy port %1 is already in use")
|
||||
.arg(selectedPort);
|
||||
ProxyLogger::getInstance().error(errorDescription);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
errorDescription = QStringLiteral("No available local proxy port in range %1-%2")
|
||||
.arg(startPort)
|
||||
.arg(kProxyPortMax);
|
||||
ProxyLogger::getInstance().error(errorDescription);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (applyProxyPortToConfig(data.parsedConfig, selectedPort)) {
|
||||
data.serializedConfig = serializeConfig(data.parsedConfig);
|
||||
if (m_settings && m_settings->localProxyPort() != static_cast<quint16>(selectedPort)) {
|
||||
m_settings->setLocalProxyPort(static_cast<quint16>(selectedPort));
|
||||
}
|
||||
} else {
|
||||
ProxyLogger::getInstance().warning(QStringLiteral("Failed to override local proxy inbound port; using original config"));
|
||||
data.serializedConfig = *serializedConfig;
|
||||
|
||||
@@ -32,7 +32,6 @@ private:
|
||||
QString tempDirectory() const;
|
||||
bool applyProxyPortToConfig(QJsonObject &config, int port) const;
|
||||
QString serializeConfig(const QJsonObject &config) const;
|
||||
bool isPortAvailable(int port) const;
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "portavailabilityhelper.h"
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QTcpServer>
|
||||
|
||||
namespace {
|
||||
constexpr int kProxyPortMin = 1024;
|
||||
constexpr int kProxyPortMax = 65535;
|
||||
}
|
||||
|
||||
bool PortAvailabilityHelper::isPortAvailable(int port)
|
||||
{
|
||||
if (port < kProxyPortMin || port > kProxyPortMax) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QTcpServer server;
|
||||
const bool success = server.listen(QHostAddress::LocalHost, static_cast<quint16>(port));
|
||||
server.close();
|
||||
return success;
|
||||
}
|
||||
|
||||
std::optional<int> PortAvailabilityHelper::findFirstAvailablePort(int startPort, int endPort)
|
||||
{
|
||||
if (startPort < kProxyPortMin) {
|
||||
startPort = kProxyPortMin;
|
||||
}
|
||||
if (endPort > kProxyPortMax) {
|
||||
endPort = kProxyPortMax;
|
||||
}
|
||||
if (startPort > endPort) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for (int port = startPort; port <= endPort; ++port) {
|
||||
if (isPortAvailable(port)) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
class PortAvailabilityHelper
|
||||
{
|
||||
public:
|
||||
static bool isPortAvailable(int port);
|
||||
static std::optional<int> findFirstAvailablePort(int startPort, int endPort);
|
||||
};
|
||||
|
||||
@@ -65,11 +65,11 @@ void ProxyServer::stopXrayProcess()
|
||||
m_service->stopXray();
|
||||
}
|
||||
|
||||
void ProxyServer::syncSettings()
|
||||
bool ProxyServer::syncSettings()
|
||||
{
|
||||
if (!m_isRunning) {
|
||||
qDebug() << "Local proxy: syncSettings called but server is not running";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const quint16 newProxyPort = m_settings ? m_settings->localProxyPort() : 0;
|
||||
@@ -77,14 +77,21 @@ void ProxyServer::syncSettings()
|
||||
|
||||
if (!xrayRunning) {
|
||||
qInfo() << "Local proxy: starting Xray on port" << newProxyPort;
|
||||
m_currentProxyPort = newProxyPort;
|
||||
startXrayProcess();
|
||||
return;
|
||||
const bool started = startXrayProcess();
|
||||
if (started) {
|
||||
m_currentProxyPort = newProxyPort;
|
||||
}
|
||||
return started;
|
||||
}
|
||||
|
||||
if (m_currentProxyPort != newProxyPort) {
|
||||
qInfo() << "Local proxy: proxy port changed from" << m_currentProxyPort << "to" << newProxyPort;
|
||||
m_currentProxyPort = newProxyPort;
|
||||
m_service->restartXray();
|
||||
const bool restarted = m_service->restartXray();
|
||||
if (restarted) {
|
||||
m_currentProxyPort = newProxyPort;
|
||||
}
|
||||
return restarted;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
|
||||
bool start(quint16 port = 49490);
|
||||
void stop();
|
||||
void syncSettings();
|
||||
bool syncSettings();
|
||||
|
||||
private:
|
||||
bool startXrayProcess();
|
||||
|
||||
Reference in New Issue
Block a user