Compare commits

...
3 Commits
Author SHA1 Message Date
vkamn 7f9b7db482 chore: bump version (#3350) 2026-10-29 23:20:34 +09:00
NickVs2015 6c0e62753d chore: update amnezia-xray-bindings to 1.5.0 (#3349) 2026-10-29 22:33:38 +09:00
NickVs2015 da8ce1809b fix: revert local proxy port rotation and logic with port processing (#3347)
* Revert "fix: rotate local proxy port on restart (#3320)"

This reverts commit a55ef420e8.

* fix: check local proxy port availability via service

* chore: update amnezia-xray-bindings
2026-10-29 22:16:26 +09:00
10 changed files with 77 additions and 39 deletions

No files matched your search

+2 -2
View File
@@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PROJECT AmneziaVPN)
if(NOT AMNEZIAVPN_VERSION)
set(AMNEZIAVPN_VERSION 5.1.0.4 CACHE STRING "Client app version")
set(AMNEZIAVPN_VERSION 5.1.0.5 CACHE STRING "Client app version")
endif()
set(QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP ON CACHE BOOL "" FORCE)
@@ -34,7 +34,7 @@ set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
# bump by 2 on every release, because we're releasing two versions on the play store
set(APP_ANDROID_VERSION_CODE 2186)
set(APP_ANDROID_VERSION_CODE 2188)
if(DEFINED APP_ANDROID_VERSION_CODE_OFFSET)
math(EXPR APP_ANDROID_VERSION_CODE "${APP_ANDROID_VERSION_CODE} + ${APP_ANDROID_VERSION_CODE_OFFSET}")
endif()
@@ -76,7 +76,6 @@ bool LocalProxyController::setPort(int port)
const bool isPortChanged = m_appSettingsRepository->localProxyPort() != static_cast<quint16>(port);
if (isPortChanged) {
m_appSettingsRepository->setLocalProxyPort(static_cast<quint16>(port));
m_lastProxyPort = 0;
}
m_appSettingsRepository->setLocalProxyPortUserDefined(true);
emit stateChanged();
@@ -89,7 +88,7 @@ bool LocalProxyController::setPort(int port)
bool LocalProxyController::isPortBusy(int port) const
{
return !portUtils::isPortAvailable(port);
return !isPortAvailable(port);
}
bool LocalProxyController::enable(const QString &ownerId, int port)
@@ -102,7 +101,7 @@ bool LocalProxyController::enable(const QString &ownerId, int port)
return false;
}
if (!portUtils::isPortAvailable(port) && m_appSettingsRepository->isLocalProxyPortUserDefined()) {
if (!isPortAvailable(port) && m_appSettingsRepository->isLocalProxyPortUserDefined()) {
return false;
}
@@ -226,7 +225,6 @@ bool LocalProxyController::startXray()
}
qDebug() << "Xray started on port" << config->proxyPort;
m_lastProxyPort = config->proxyPort;
setActivePort(config->proxyPort);
return true;
}
@@ -327,35 +325,35 @@ std::optional<LocalProxyController::XrayConfig> LocalProxyController::buildXrayC
std::optional<int> LocalProxyController::selectProxyPort() const
{
int basePort = m_appSettingsRepository->localProxyPort();
if (basePort < localProxy::proxyPortMin || basePort > localProxy::proxyPortMax) {
basePort = localProxy::defaultProxyPort;
int port = m_appSettingsRepository->localProxyPort();
if (port < localProxy::proxyPortMin || port > localProxy::proxyPortMax) {
port = localProxy::defaultProxyPort;
}
if (m_lastProxyPort == 0) {
if (portUtils::waitForPort(basePort, localProxy::portReleaseWaitMs)) {
return basePort;
}
if (m_appSettingsRepository->isLocalProxyPortUserDefined()) {
qWarning() << "Local proxy port" << basePort << "is already in use";
return std::nullopt;
}
const auto isAvailable = [this](int p) { return isPortAvailable(p); };
if (portUtils::waitForPort(port, localProxy::portReleaseWaitMs, isAvailable)) {
return port;
}
// Every restart moves to a new port so that clients notice the change and reconnect.
const int from = (m_lastProxyPort > 0 ? m_lastProxyPort : basePort) + 1;
auto freePort = portUtils::findFirstAvailablePort(from, localProxy::proxyPortMax);
if (!freePort && from > basePort + 1) {
freePort = portUtils::findFirstAvailablePort(basePort, from - 2);
}
if (!freePort) {
qWarning() << "No available local proxy port in range" << basePort << "-" << localProxy::proxyPortMax;
if (m_appSettingsRepository->isLocalProxyPortUserDefined()) {
qWarning() << "Local proxy port" << port << "is already in use";
return std::nullopt;
}
qDebug() << "Local proxy port selected:" << *freePort << "(previous" << m_lastProxyPort << ")";
std::optional<int> freePort;
if (port != localProxy::defaultProxyPort && isPortAvailable(localProxy::defaultProxyPort)) {
freePort = localProxy::defaultProxyPort;
} else {
freePort = portUtils::findFirstAvailablePort(localProxy::defaultProxyPort + 1, localProxy::proxyPortMax, isAvailable);
}
if (!freePort) {
qWarning() << "No available local proxy port in range" << localProxy::defaultProxyPort + 1 << "-"
<< localProxy::proxyPortMax;
return std::nullopt;
}
qDebug() << "Local proxy port" << port << "is busy, using" << *freePort;
return freePort;
}
@@ -494,6 +492,20 @@ bool LocalProxyController::isXrayEngineRunning() const
[]() { return false; });
}
bool LocalProxyController::isPortAvailable(int port) const
{
if (port < localProxy::proxyPortMin || port > localProxy::proxyPortMax) {
return false;
}
return IpcClient::withInterface(
[port](QSharedPointer<IpcInterfaceReplica> iface) {
auto reply = iface->isTcpPortAvailable(port);
return reply.waitForFinished() && reply.returnValue();
},
[port]() { return portUtils::isPortAvailable(port); });
}
#else
bool LocalProxyController::isSupported() const
@@ -525,4 +537,9 @@ bool LocalProxyController::isXrayEngineRunning() const
return false;
}
bool LocalProxyController::isPortAvailable(int port) const
{
return portUtils::isPortAvailable(port);
}
#endif
@@ -68,6 +68,7 @@ private:
bool startXrayEngine(const QString &config);
bool stopXrayEngine();
bool isXrayEngineRunning() const;
bool isPortAvailable(int port) const;
SecureServersRepository *m_serversRepository;
SecureAppSettingsRepository *m_appSettingsRepository;
@@ -79,7 +80,6 @@ private:
qint64 m_xrayToken = 0;
quint16 m_appliedProxyPort = 0;
int m_activePort = 0;
int m_lastProxyPort = 0;
};
#endif // LOCALPROXYCONTROLLER_H
+4 -4
View File
@@ -21,12 +21,12 @@ bool portUtils::isPortAvailable(int port)
return success;
}
bool portUtils::waitForPort(int port, int timeoutMs)
bool portUtils::waitForPort(int port, int timeoutMs, const PortCheck &isAvailable)
{
QElapsedTimer timer;
timer.start();
while (!isPortAvailable(port)) {
while (!isAvailable(port)) {
if (timer.elapsed() >= timeoutMs) {
return false;
}
@@ -36,13 +36,13 @@ bool portUtils::waitForPort(int port, int timeoutMs)
return true;
}
std::optional<int> portUtils::findFirstAvailablePort(int startPort, int endPort)
std::optional<int> portUtils::findFirstAvailablePort(int startPort, int endPort, const PortCheck &isAvailable)
{
startPort = qMax(startPort, localProxy::proxyPortMin);
endPort = qMin(endPort, localProxy::proxyPortMax);
for (int port = startPort; port <= endPort; ++port) {
if (isPortAvailable(port)) {
if (isAvailable(port)) {
return port;
}
}
+5 -2
View File
@@ -1,13 +1,16 @@
#ifndef PORTUTILS_H
#define PORTUTILS_H
#include <functional>
#include <optional>
namespace portUtils
{
using PortCheck = std::function<bool(int)>;
bool isPortAvailable(int port);
bool waitForPort(int port, int timeoutMs);
std::optional<int> findFirstAvailablePort(int startPort, int endPort);
bool waitForPort(int port, int timeoutMs, const PortCheck &isAvailable = isPortAvailable);
std::optional<int> findFirstAvailablePort(int startPort, int endPort, const PortCheck &isAvailable = isPortAvailable);
}
#endif // PORTUTILS_H
+1 -1
View File
@@ -28,7 +28,7 @@ class AmneziaVPN(ConanFile):
else:
self.requires("awg-go/3.1.20260814")
self.requires("amnezia-xray-bindings/1.4.0")
self.requires("amnezia-xray-bindings/1.5.0")
self.requires("tun2socks/2.6.0")
self.requires("openvpn/2.7.0")
self.requires("v2ray-rules-dat/202603162227")
+1
View File
@@ -43,6 +43,7 @@ class IpcInterface
SLOT(qint64 xrayStartOwned(const QString &config));
SLOT(bool xrayStopOwned(qint64 token));
SLOT(qint64 xrayCurrentToken());
SLOT(bool isTcpPortAvailable(int port));
SLOT( bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) );
SLOT( bool stopNetworkCheck() );
+17
View File
@@ -12,6 +12,7 @@
#include <QRemoteObjectNode>
#include <QString>
#include <QStringList>
#include <QTcpServer>
#include "logger.h"
#include "router.h"
@@ -348,3 +349,19 @@ qint64 IpcServer::xrayCurrentToken()
return Xray::getInstance().currentToken();
}
bool IpcServer::isTcpPortAvailable(int port)
{
#ifdef MZ_DEBUG
qDebug() << "IpcServer::isTcpPortAvailable" << port;
#endif
if (port < 1 || port > 65535) {
return false;
}
QTcpServer server;
const bool available = server.listen(QHostAddress::LocalHost, static_cast<quint16>(port));
server.close();
return available;
}
+1
View File
@@ -47,6 +47,7 @@ public:
virtual qint64 xrayStartOwned(const QString& cfg) override;
virtual bool xrayStopOwned(qint64 token) override;
virtual qint64 xrayCurrentToken() override;
virtual bool isTcpPortAvailable(int port) override;
virtual bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) override;
virtual bool stopNetworkCheck() override;
+2 -3
View File
@@ -13,11 +13,10 @@ import shlex
class AmneziaXrayBindings(ConanFile):
name = "amnezia-xray-bindings"
version = "1.4.0"
version = "1.5.0"
settings = "os", "arch", "compiler"
_arch_map = {
"x86": "386",
"x86_64": "amd64",
"armv8": "arm64"
}
@@ -77,7 +76,7 @@ class AmneziaXrayBindings(ConanFile):
def source(self):
get(self, f"https://github.com/amnezia-vpn/amnezia-xray-bindings/archive/refs/tags/v{self.version}.zip",
sha256="8977896bba99f1a3bad61d734b2929ec3d01c3ca0e206ee8ce5eb013d38ab118", strip_root=True)
sha256="60e4eeceb0ec0332f37cb5e4f653149dc9034c4eeb8bee9947f3126f098287ad", strip_root=True)
def generate(self):
tc = AutotoolsToolchain(self)