mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-10-23 03:26:59 +09:00
fix: prepare gateway request (#3291)
* fix: prepare the gateway request once instead of a blocking callback per attempt * chore: libagw 1.0.8, gateway and failover timeouts 6s, health check 1s
This commit is contained in:
1 parent
db951e9928
commit
30ff3451c7
6 files changed
+65
-38
No files matched your search
@@ -5,11 +5,13 @@
|
||||
#include <QFutureWatcher>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QMetaObject>
|
||||
#include <QJsonObject>
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
#include "core/repositories/secureAppSettingsRepository.h"
|
||||
#include "core/utils/constants/apiConstants.h"
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "core/utils/api/apiUtils.h"
|
||||
|
||||
@@ -32,6 +34,9 @@ namespace
|
||||
constexpr QLatin1String s3FallbackEndpoints("s3_fallback_endpoints");
|
||||
constexpr QLatin1String isDevEnvironment("is_dev_environment");
|
||||
constexpr QLatin1String requestTimeoutMsecs("request_timeout_msecs");
|
||||
constexpr QLatin1String proxyRequestTimeoutMsecs("proxy_request_timeout_msecs");
|
||||
constexpr QLatin1String proxyStorageTimeoutMsecs("proxy_storage_timeout_msecs");
|
||||
constexpr QLatin1String proxyHealthTimeoutMsecs("proxy_health_timeout_msecs");
|
||||
}
|
||||
|
||||
namespace agwOptionsKey
|
||||
@@ -40,6 +45,11 @@ namespace
|
||||
constexpr QLatin1String userCountryCode("user_country_code");
|
||||
}
|
||||
|
||||
namespace agwStateKey
|
||||
{
|
||||
constexpr QLatin1String workingProxy("working_proxy");
|
||||
}
|
||||
|
||||
constexpr QLatin1String agwStateCacheKey("agw_state");
|
||||
constexpr QLatin1String agwTracePrefix("agw trace:");
|
||||
constexpr QLatin1String agwTraceFailoverMarker("suspicious");
|
||||
@@ -71,6 +81,7 @@ GatewayController::GatewayController(const QString &gatewayEndpoint, const bool
|
||||
const bool isStrictKillSwitchEnabled, SecureAppSettingsRepository *appSettingsRepository,
|
||||
QObject *parent)
|
||||
: QObject(parent),
|
||||
m_gatewayEndpoint(gatewayEndpoint),
|
||||
m_isStrictKillSwitchEnabled(isStrictKillSwitchEnabled),
|
||||
m_appSettingsRepository(appSettingsRepository)
|
||||
{
|
||||
@@ -93,13 +104,11 @@ GatewayController::GatewayController(const QString &gatewayEndpoint, const bool
|
||||
config[agwConfigKey::s3FallbackEndpoints] = QJsonArray::fromStringList(fallbackEndpoints);
|
||||
config[agwConfigKey::isDevEnvironment] = isDevEnvironment;
|
||||
config[agwConfigKey::requestTimeoutMsecs] = requestTimeoutMsecs;
|
||||
config[agwConfigKey::proxyRequestTimeoutMsecs] = apiDefs::proxyRequestTimeoutMsecs;
|
||||
config[agwConfigKey::proxyStorageTimeoutMsecs] = apiDefs::proxyStorageTimeoutMsecs;
|
||||
config[agwConfigKey::proxyHealthTimeoutMsecs] = apiDefs::proxyHealthTimeoutMsecs;
|
||||
|
||||
agw_callbacks callbacks {};
|
||||
callbacks.struct_size = sizeof(agw_callbacks);
|
||||
callbacks.on_before_request = &GatewayController::onBeforeRequest;
|
||||
callbacks.on_before_request_user_data = this;
|
||||
|
||||
m_client = agw_client_create(QJsonDocument(config).toJson(QJsonDocument::Compact).constData(), &callbacks);
|
||||
m_client = agw_client_create(QJsonDocument(config).toJson(QJsonDocument::Compact).constData(), nullptr);
|
||||
if (m_client == 0) {
|
||||
qCritical() << "GatewayController: failed to create gateway client (missing key or endpoint?)";
|
||||
return;
|
||||
@@ -137,6 +146,7 @@ amnezia::ErrorCode GatewayController::post(const QString &endpoint, const QJsonO
|
||||
|
||||
QFuture<QPair<amnezia::ErrorCode, QByteArray>> GatewayController::postAsync(const QString &endpoint, const QJsonObject apiPayload)
|
||||
{
|
||||
prepareRequest();
|
||||
return QtConcurrent::run(
|
||||
[this, endpoint, apiPayload]() -> QPair<amnezia::ErrorCode, QByteArray> { return executePost(endpoint, apiPayload); });
|
||||
}
|
||||
@@ -190,44 +200,55 @@ amnezia::ErrorCode GatewayController::mapResultCode(const int code, const QByteA
|
||||
}
|
||||
}
|
||||
|
||||
void GatewayController::onBeforeRequest(const char *host, void *userData)
|
||||
{
|
||||
auto *controller = static_cast<GatewayController *>(userData);
|
||||
const QString hostString = QString::fromUtf8(host);
|
||||
if (QThread::currentThread() == controller->thread()) {
|
||||
controller->handleBeforeRequest(hostString);
|
||||
} else {
|
||||
QMetaObject::invokeMethod(
|
||||
controller, [controller, hostString]() { controller->handleBeforeRequest(hostString); },
|
||||
Qt::BlockingQueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void GatewayController::handleBeforeRequest(const QString &host)
|
||||
void GatewayController::prepareRequest()
|
||||
{
|
||||
#ifdef Q_OS_IOS
|
||||
Q_UNUSED(host);
|
||||
IosController::Instance()->requestInetAccess();
|
||||
QThread::msleep(10);
|
||||
#endif
|
||||
|
||||
#ifdef AMNEZIA_DESKTOP
|
||||
if (m_isStrictKillSwitchEnabled) {
|
||||
if (!m_isStrictKillSwitchEnabled) {
|
||||
return;
|
||||
}
|
||||
QStringList ips;
|
||||
for (const QString &host : requestHosts()) {
|
||||
const QString ip = NetworkUtilities::getIPAddress(host);
|
||||
if (!ip.isEmpty()) {
|
||||
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||
QRemoteObjectPendingReply<bool> reply = iface->addKillSwitchAllowedRange(QStringList { ip });
|
||||
if (!reply.waitForFinished(1000) || !reply.returnValue()) {
|
||||
qWarning() << "GatewayController::handleBeforeRequest(): failed to add killswitch exception for" << host;
|
||||
}
|
||||
});
|
||||
ips.append(ip);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(host);
|
||||
if (ips.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||
QRemoteObjectPendingReply<bool> reply = iface->addKillSwitchAllowedRange(ips);
|
||||
if (!reply.waitForFinished(1000) || !reply.returnValue()) {
|
||||
qWarning() << "GatewayController::prepareRequest(): Failed to execute remote addKillSwitchAllowedRange call";
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
QStringList GatewayController::requestHosts() const
|
||||
{
|
||||
QStringList hosts;
|
||||
if (m_client != 0) {
|
||||
char *state = agw_export_state(m_client);
|
||||
if (state != nullptr) {
|
||||
const QString workingProxy = QJsonDocument::fromJson(QByteArray(state)).object().value(agwStateKey::workingProxy).toString();
|
||||
agw_string_free(state);
|
||||
if (!workingProxy.isEmpty()) {
|
||||
hosts.append(QUrl(workingProxy).host());
|
||||
}
|
||||
}
|
||||
}
|
||||
hosts.append(QUrl(m_gatewayEndpoint).host());
|
||||
hosts.removeAll(QString());
|
||||
hosts.removeDuplicates();
|
||||
return hosts;
|
||||
}
|
||||
|
||||
void GatewayController::persistState()
|
||||
{
|
||||
if (m_client == 0 || m_appSettingsRepository == nullptr) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include "core/utils/errorCodes.h"
|
||||
|
||||
@@ -28,13 +29,14 @@ public:
|
||||
QFuture<QPair<amnezia::ErrorCode, QByteArray>> postAsync(const QString &endpoint, const QJsonObject apiPayload);
|
||||
|
||||
private:
|
||||
static void onBeforeRequest(const char *host, void *userData);
|
||||
void handleBeforeRequest(const QString &host);
|
||||
void prepareRequest();
|
||||
QStringList requestHosts() const;
|
||||
|
||||
QPair<amnezia::ErrorCode, QByteArray> executePost(const QString &endpoint, const QJsonObject &apiPayload);
|
||||
static amnezia::ErrorCode mapResultCode(const int code, const QByteArray &responseBody);
|
||||
void persistState();
|
||||
|
||||
QString m_gatewayEndpoint;
|
||||
bool m_isStrictKillSwitchEnabled = false;
|
||||
SecureAppSettingsRepository *m_appSettingsRepository = nullptr;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "core/utils/api/gatewayPayloadBuilder.h"
|
||||
#include "core/utils/appUiConfig.h"
|
||||
#include "core/utils/constants/apiConstants.h"
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "core/utils/selfhosted/scriptsRegistry.h"
|
||||
|
||||
@@ -140,7 +141,7 @@ void UpdateController::checkForUpdates()
|
||||
|
||||
auto gatewayController = QSharedPointer<GatewayController>::create(m_appSettingsRepository->getGatewayEndpoint(),
|
||||
m_appSettingsRepository->isDevGatewayEnv(),
|
||||
7000,
|
||||
apiDefs::requestTimeoutMsecs,
|
||||
m_appSettingsRepository->isStrictKillSwitchEnabled(),
|
||||
m_appSettingsRepository);
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
namespace apiDefs
|
||||
{
|
||||
|
||||
constexpr int requestTimeoutMsecs = 12 * 1000; // 12 secs
|
||||
constexpr int requestTimeoutMsecs = 6 * 1000;
|
||||
constexpr int proxyRequestTimeoutMsecs = 6 * 1000;
|
||||
constexpr int proxyStorageTimeoutMsecs = 6 * 1000;
|
||||
constexpr int proxyHealthTimeoutMsecs = 1000;
|
||||
|
||||
} // namespace apiDefs
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ class AmneziaVPN(ConanFile):
|
||||
def requirements(self):
|
||||
os = str(self.settings.os)
|
||||
|
||||
self.requires("libagw/1.0.6")
|
||||
self.requires("libagw/1.0.8")
|
||||
|
||||
has_ne = os == "iOS" or (os == "Macos" and self.options.macos_ne)
|
||||
has_service = os == "Windows" or os == "Linux" or (os == "Macos" and not has_ne)
|
||||
|
||||
@@ -13,7 +13,7 @@ import shlex
|
||||
|
||||
class Libagw(ConanFile):
|
||||
name = "libagw"
|
||||
version = "1.0.6"
|
||||
version = "1.0.8"
|
||||
settings = "os", "arch", "compiler"
|
||||
|
||||
_headers = ("agw.h", "agw_types.h")
|
||||
@@ -91,7 +91,7 @@ class Libagw(ConanFile):
|
||||
|
||||
def source(self):
|
||||
get(self, f"https://github.com/amnezia-vpn/libagw/archive/refs/tags/v{self.version}.zip",
|
||||
sha256="148f421e20e31b53c7686a29a368e03720c41776facce457c55748d8b2974ddb", strip_root=True
|
||||
sha256="ad36125be7ff4a77603107a0bc2194da6778d5612e649f53c9d954c742bb70db", strip_root=True
|
||||
)
|
||||
|
||||
def generate(self):
|
||||
|
||||
Reference in new issue
Block a user