From 2d22a74b229f322f2489efd097e8793bf47e7300 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Fri, 20 Jun 2025 22:18:47 +0800 Subject: [PATCH 1/3] refactoring: added classes for working with server configs --- CMakeLists.txt | 2 +- client/cmake/sources.cmake | 18 ++ client/core/api/apiDefs.h | 5 - client/core/api/apiUtils.cpp | 12 +- client/core/api/apiUtils.h | 2 +- client/core/controllers/coreController.cpp | 3 - client/core/defs.h | 7 + .../models/containers/containerConfig.cpp | 5 + .../core/models/containers/containerConfig.h | 19 ++ .../models/protocols/awgProtocolConfig.cpp | 198 ++++++++++++++++++ .../core/models/protocols/awgProtocolConfig.h | 65 ++++++ .../models/protocols/cloakProtocolConfig.cpp | 43 ++++ .../models/protocols/cloakProtocolConfig.h | 35 ++++ .../protocols/openvpnProtocolConfig.cpp | 83 ++++++++ .../models/protocols/openvpnProtocolConfig.h | 46 ++++ .../core/models/protocols/protocolConfig.cpp | 12 ++ client/core/models/protocols/protocolConfig.h | 16 ++ .../protocols/shadowsocksProtocolConfig.cpp | 39 ++++ .../protocols/shadowsocksProtocolConfig.h | 34 +++ .../protocols/wireguardProtocolConfig.cpp | 120 +++++++++++ .../protocols/wireguardProtocolConfig.h | 58 +++++ .../models/protocols/xrayProtocolConfig.cpp | 43 ++++ .../models/protocols/xrayProtocolConfig.h | 35 ++++ .../core/models/servers/apiV1ServerConfig.cpp | 30 +++ .../core/models/servers/apiV1ServerConfig.h | 17 ++ .../core/models/servers/apiV2ServerConfig.cpp | 125 +++++++++++ .../core/models/servers/apiV2ServerConfig.h | 54 +++++ .../models/servers/selfHostedServerConfig.cpp | 48 +++++ .../models/servers/selfHostedServerConfig.h | 19 ++ client/core/models/servers/serverConfig.cpp | 145 +++++++++++++ client/core/models/servers/serverConfig.h | 32 +++ .../controllers/api/apiConfigsController.cpp | 10 +- client/ui/models/servers_model.cpp | 144 +++++++------ client/ui/models/servers_model.h | 8 +- 34 files changed, 1441 insertions(+), 91 deletions(-) create mode 100644 client/core/models/containers/containerConfig.cpp create mode 100644 client/core/models/containers/containerConfig.h create mode 100644 client/core/models/protocols/awgProtocolConfig.cpp create mode 100644 client/core/models/protocols/awgProtocolConfig.h create mode 100644 client/core/models/protocols/cloakProtocolConfig.cpp create mode 100644 client/core/models/protocols/cloakProtocolConfig.h create mode 100644 client/core/models/protocols/openvpnProtocolConfig.cpp create mode 100644 client/core/models/protocols/openvpnProtocolConfig.h create mode 100644 client/core/models/protocols/protocolConfig.cpp create mode 100644 client/core/models/protocols/protocolConfig.h create mode 100644 client/core/models/protocols/shadowsocksProtocolConfig.cpp create mode 100644 client/core/models/protocols/shadowsocksProtocolConfig.h create mode 100644 client/core/models/protocols/wireguardProtocolConfig.cpp create mode 100644 client/core/models/protocols/wireguardProtocolConfig.h create mode 100644 client/core/models/protocols/xrayProtocolConfig.cpp create mode 100644 client/core/models/protocols/xrayProtocolConfig.h create mode 100644 client/core/models/servers/apiV1ServerConfig.cpp create mode 100644 client/core/models/servers/apiV1ServerConfig.h create mode 100644 client/core/models/servers/apiV2ServerConfig.cpp create mode 100644 client/core/models/servers/apiV2ServerConfig.h create mode 100644 client/core/models/servers/selfHostedServerConfig.cpp create mode 100644 client/core/models/servers/selfHostedServerConfig.h create mode 100644 client/core/models/servers/serverConfig.cpp create mode 100644 client/core/models/servers/serverConfig.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 424dcf3a..a759bd80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") endif() set(QT_BUILD_TOOLS_WHEN_CROSS_COMPILING ON) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(APPLE AND NOT IOS) diff --git a/client/cmake/sources.cmake b/client/cmake/sources.cmake index c3af531a..fe8e37e3 100644 --- a/client/cmake/sources.cmake +++ b/client/cmake/sources.cmake @@ -116,6 +116,7 @@ file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/models/services/*.h ${CLIENT_ROOT_DIR}/ui/models/api/*.h ) + file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/models/*.cpp ${CLIENT_ROOT_DIR}/ui/models/protocols/*.cpp @@ -127,17 +128,33 @@ file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/controllers/*.h ${CLIENT_ROOT_DIR}/ui/controllers/api/*.h ) + file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CLIENT_ROOT_DIR}/ui/controllers/*.cpp ${CLIENT_ROOT_DIR}/ui/controllers/api/*.cpp ) +file(GLOB CORE_MODELS_H CONFIGURE_DEPENDS + ${CLIENT_ROOT_DIR}/core/models/*.h + ${CLIENT_ROOT_DIR}/core/models/containers/*.h + ${CLIENT_ROOT_DIR}/core/models/protocols/*.h + ${CLIENT_ROOT_DIR}/core/models/servers/*.h +) + +file(GLOB CORE_MODELS_CPP CONFIGURE_DEPENDS + ${CLIENT_ROOT_DIR}/core/models/*.cpp + ${CLIENT_ROOT_DIR}/core/models/containers/*.cpp + ${CLIENT_ROOT_DIR}/core/models/protocols/*.cpp + ${CLIENT_ROOT_DIR}/core/models/servers/*.cpp +) + set(HEADERS ${HEADERS} ${COMMON_FILES_H} ${PAGE_LOGIC_H} ${CONFIGURATORS_H} ${UI_MODELS_H} ${UI_CONTROLLERS_H} + ${CORE_MODELS_H} ) set(SOURCES ${SOURCES} ${COMMON_FILES_CPP} @@ -145,6 +162,7 @@ set(SOURCES ${SOURCES} ${CONFIGURATORS_CPP} ${UI_MODELS_CPP} ${UI_CONTROLLERS_CPP} + ${CORE_MODELS_CPP} ) if(WIN32) diff --git a/client/core/api/apiDefs.h b/client/core/api/apiDefs.h index 4588ef04..a7b134f0 100644 --- a/client/core/api/apiDefs.h +++ b/client/core/api/apiDefs.h @@ -14,11 +14,6 @@ namespace apiDefs ExternalPremium }; - enum ConfigSource { - Telegram = 1, - AmneziaGateway - }; - namespace key { constexpr QLatin1String configVersion("config_version"); diff --git a/client/core/api/apiUtils.cpp b/client/core/api/apiUtils.cpp index 7f3e6db3..8e5ac28c 100644 --- a/client/core/api/apiUtils.cpp +++ b/client/core/api/apiUtils.cpp @@ -32,8 +32,8 @@ bool apiUtils::isServerFromApi(const QJsonObject &serverConfigObject) { auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt(); switch (configVersion) { - case apiDefs::ConfigSource::Telegram: return true; - case apiDefs::ConfigSource::AmneziaGateway: return true; + case amnezia::ServerConfigType::ApiV1: return true; + case amnezia::ServerConfigType::ApiV2: return true; default: return false; } } @@ -43,7 +43,7 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt(); switch (configVersion) { - case apiDefs::ConfigSource::Telegram: { + case amnezia::ServerConfigType::ApiV1: { constexpr QLatin1String freeV2Endpoint(FREE_V2_ENDPOINT); constexpr QLatin1String premiumV1Endpoint(PREM_V1_ENDPOINT); @@ -55,7 +55,7 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec return apiDefs::ConfigType::AmneziaFreeV2; } }; - case apiDefs::ConfigSource::AmneziaGateway: { + case amnezia::ServerConfigType::ApiV2: { constexpr QLatin1String servicePremium("amnezia-premium"); constexpr QLatin1String serviceFree("amnezia-free"); constexpr QLatin1String serviceExternalPremium("external-premium"); @@ -77,9 +77,9 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec }; } -apiDefs::ConfigSource apiUtils::getConfigSource(const QJsonObject &serverConfigObject) +amnezia::ServerConfigType apiUtils::getConfigSource(const QJsonObject &serverConfigObject) { - return static_cast(serverConfigObject.value(apiDefs::key::configVersion).toInt()); + return static_cast(serverConfigObject.value(apiDefs::key::configVersion).toInt()); } amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList &sslErrors, QNetworkReply *reply) diff --git a/client/core/api/apiUtils.h b/client/core/api/apiUtils.h index 45eaf2de..9e6fdbbe 100644 --- a/client/core/api/apiUtils.h +++ b/client/core/api/apiUtils.h @@ -16,7 +16,7 @@ namespace apiUtils bool isPremiumServer(const QJsonObject &serverConfigObject); apiDefs::ConfigType getConfigType(const QJsonObject &serverConfigObject); - apiDefs::ConfigSource getConfigSource(const QJsonObject &serverConfigObject); + amnezia::ServerConfigType getConfigSource(const QJsonObject &serverConfigObject); amnezia::ErrorCode checkNetworkReplyErrors(const QList &sslErrors, QNetworkReply *reply); diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index 0e72ef1a..a4dbc6d6 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -299,13 +299,10 @@ void CoreController::setQmlRoot() void CoreController::initApiCountryModelUpdateHandler() { - // TODO connect(m_serversModel.get(), &ServersModel::updateApiCountryModel, this, [this]() { m_apiCountryModel->updateModel(m_serversModel->getProcessedServerData("apiAvailableCountries").toJsonArray(), m_serversModel->getProcessedServerData("apiServerCountryCode").toString()); }); - connect(m_serversModel.get(), &ServersModel::updateApiServicesModel, this, - [this]() { m_apiServicesModel->updateModel(m_serversModel->getProcessedServerData("apiConfig").toJsonObject()); }); } void CoreController::initContainerModelUpdateHandler() diff --git a/client/core/defs.h b/client/core/defs.h index df6a1342..3d64932a 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -19,6 +19,13 @@ namespace amnezia } }; + enum ServerConfigType + { + SelfHosted, + ApiV1, + ApiV2 + }; + struct InstalledAppInfo { QString appName; QString packageName; diff --git a/client/core/models/containers/containerConfig.cpp b/client/core/models/containers/containerConfig.cpp new file mode 100644 index 00000000..119ff2b6 --- /dev/null +++ b/client/core/models/containers/containerConfig.cpp @@ -0,0 +1,5 @@ +#include "containerConfig.h" + +ContainerConfig::ContainerConfig() +{ +} diff --git a/client/core/models/containers/containerConfig.h b/client/core/models/containers/containerConfig.h new file mode 100644 index 00000000..7207d028 --- /dev/null +++ b/client/core/models/containers/containerConfig.h @@ -0,0 +1,19 @@ +#ifndef CONTAINERCONFIG_H +#define CONTAINERCONFIG_H + +#include +#include +#include + +#include "core/models/protocols/protocolConfig.h" + +class ContainerConfig +{ +public: + ContainerConfig(); + + QString containerName; + QMap> protocolConfigs; +}; + +#endif // CONTAINERCONFIG_H diff --git a/client/core/models/protocols/awgProtocolConfig.cpp b/client/core/models/protocols/awgProtocolConfig.cpp new file mode 100644 index 00000000..f77c0385 --- /dev/null +++ b/client/core/models/protocols/awgProtocolConfig.cpp @@ -0,0 +1,198 @@ +#include "awgProtocolConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +AwgProtocolConfig::AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + + serverProtocolConfig.awgData.junkPacketCount = protocolConfigObject.value(config_key::junkPacketCount).toString(); + serverProtocolConfig.awgData.junkPacketMinSize = protocolConfigObject.value(config_key::junkPacketMinSize).toString(); + serverProtocolConfig.awgData.junkPacketMaxSize = protocolConfigObject.value(config_key::junkPacketMaxSize).toString(); + serverProtocolConfig.awgData.initPacketJunkSize = protocolConfigObject.value(config_key::initPacketJunkSize).toString(); + serverProtocolConfig.awgData.responsePacketJunkSize = protocolConfigObject.value(config_key::responsePacketJunkSize).toString(); + serverProtocolConfig.awgData.initPacketMagicHeader = protocolConfigObject.value(config_key::initPacketMagicHeader).toString(); + serverProtocolConfig.awgData.responsePacketMagicHeader = protocolConfigObject.value(config_key::responsePacketMagicHeader).toString(); + serverProtocolConfig.awgData.underloadPacketMagicHeader = protocolConfigObject.value(config_key::underloadPacketMagicHeader).toString(); + serverProtocolConfig.awgData.transportPacketMagicHeader = protocolConfigObject.value(config_key::transportPacketMagicHeader).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + + clientProtocolConfig.awgData.junkPacketCount = clientProtocolConfigObject.value(config_key::junkPacketCount).toString(); + clientProtocolConfig.awgData.junkPacketMinSize = clientProtocolConfigObject.value(config_key::junkPacketMinSize).toString(); + clientProtocolConfig.awgData.junkPacketMaxSize = clientProtocolConfigObject.value(config_key::junkPacketMaxSize).toString(); + clientProtocolConfig.awgData.initPacketJunkSize = clientProtocolConfigObject.value(config_key::initPacketJunkSize).toString(); + clientProtocolConfig.awgData.responsePacketJunkSize = clientProtocolConfigObject.value(config_key::responsePacketJunkSize).toString(); + clientProtocolConfig.awgData.initPacketMagicHeader = clientProtocolConfigObject.value(config_key::initPacketMagicHeader).toString(); + clientProtocolConfig.awgData.responsePacketMagicHeader = + clientProtocolConfigObject.value(config_key::responsePacketMagicHeader).toString(); + clientProtocolConfig.awgData.underloadPacketMagicHeader = + clientProtocolConfigObject.value(config_key::underloadPacketMagicHeader).toString(); + clientProtocolConfig.awgData.transportPacketMagicHeader = + clientProtocolConfigObject.value(config_key::transportPacketMagicHeader).toString(); + + clientProtocolConfig.clientId = clientProtocolConfigObject.value(config_key::clientId).toString(); + + clientProtocolConfig.wireGuardData.clientIp = clientProtocolConfigObject.value(config_key::client_ip).toString(); + clientProtocolConfig.wireGuardData.clientPrivateKey = clientProtocolConfigObject.value(config_key::client_priv_key).toString(); + clientProtocolConfig.wireGuardData.clientPublicKey = clientProtocolConfigObject.value(config_key::client_pub_key).toString(); + clientProtocolConfig.wireGuardData.persistentKeepAlive = + clientProtocolConfigObject.value(config_key::persistent_keep_alive).toString(); + clientProtocolConfig.wireGuardData.pskKey = clientProtocolConfigObject.value(config_key::psk_key).toString(); + clientProtocolConfig.wireGuardData.serverPubKey = clientProtocolConfigObject.value(config_key::server_pub_key).toString(); + clientProtocolConfig.wireGuardData.mtu = clientProtocolConfigObject.value(config_key::mtu).toString(); + + clientProtocolConfig.hostname = clientProtocolConfigObject.value(config_key::hostName).toString(); + clientProtocolConfig.port = clientProtocolConfigObject.value(config_key::port).toInt(0); + + clientProtocolConfig.nativeConfig = clientProtocolConfigObject.value(config_key::config).toString(); + + if (clientProtocolConfigObject.contains(config_key::allowed_ips) + && clientProtocolConfigObject.value(config_key::allowed_ips).isArray()) { + auto allowedIpsArray = clientProtocolConfigObject.value(config_key::allowed_ips).toArray(); + for (const auto &ip : allowedIpsArray) { + clientProtocolConfig.wireGuardData.allowedIps.append(ip.toString()); + } + } + } +} + +QJsonObject AwgProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + if (!serverProtocolConfig.subnetAddress.isEmpty()) { + json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; + } + + if (!serverProtocolConfig.awgData.junkPacketCount.isEmpty()) { + json[config_key::junkPacketCount] = serverProtocolConfig.awgData.junkPacketCount; + } + if (!serverProtocolConfig.awgData.junkPacketMinSize.isEmpty()) { + json[config_key::junkPacketMinSize] = serverProtocolConfig.awgData.junkPacketMinSize; + } + if (!serverProtocolConfig.awgData.junkPacketMaxSize.isEmpty()) { + json[config_key::junkPacketMaxSize] = serverProtocolConfig.awgData.junkPacketMaxSize; + } + if (!serverProtocolConfig.awgData.initPacketJunkSize.isEmpty()) { + json[config_key::initPacketJunkSize] = serverProtocolConfig.awgData.initPacketJunkSize; + } + if (!serverProtocolConfig.awgData.responsePacketJunkSize.isEmpty()) { + json[config_key::responsePacketJunkSize] = serverProtocolConfig.awgData.responsePacketJunkSize; + } + if (!serverProtocolConfig.awgData.initPacketMagicHeader.isEmpty()) { + json[config_key::initPacketMagicHeader] = serverProtocolConfig.awgData.initPacketMagicHeader; + } + if (!serverProtocolConfig.awgData.responsePacketMagicHeader.isEmpty()) { + json[config_key::responsePacketMagicHeader] = serverProtocolConfig.awgData.responsePacketMagicHeader; + } + if (!serverProtocolConfig.awgData.underloadPacketMagicHeader.isEmpty()) { + json[config_key::underloadPacketMagicHeader] = serverProtocolConfig.awgData.underloadPacketMagicHeader; + } + if (!serverProtocolConfig.awgData.transportPacketMagicHeader.isEmpty()) { + json[config_key::transportPacketMagicHeader] = serverProtocolConfig.awgData.transportPacketMagicHeader; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + + if (!clientProtocolConfig.clientId.isEmpty()) { + clientConfigJson[config_key::clientId] = clientProtocolConfig.clientId; + } + + if (!clientProtocolConfig.awgData.junkPacketCount.isEmpty()) { + clientConfigJson[config_key::junkPacketCount] = clientProtocolConfig.awgData.junkPacketCount; + } + if (!clientProtocolConfig.awgData.junkPacketMinSize.isEmpty()) { + clientConfigJson[config_key::junkPacketMinSize] = clientProtocolConfig.awgData.junkPacketMinSize; + } + if (!clientProtocolConfig.awgData.junkPacketMaxSize.isEmpty()) { + clientConfigJson[config_key::junkPacketMaxSize] = clientProtocolConfig.awgData.junkPacketMaxSize; + } + if (!clientProtocolConfig.awgData.initPacketJunkSize.isEmpty()) { + clientConfigJson[config_key::initPacketJunkSize] = clientProtocolConfig.awgData.initPacketJunkSize; + } + if (!clientProtocolConfig.awgData.responsePacketJunkSize.isEmpty()) { + clientConfigJson[config_key::responsePacketJunkSize] = clientProtocolConfig.awgData.responsePacketJunkSize; + } + if (!clientProtocolConfig.awgData.initPacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::initPacketMagicHeader] = clientProtocolConfig.awgData.initPacketMagicHeader; + } + if (!clientProtocolConfig.awgData.responsePacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::responsePacketMagicHeader] = clientProtocolConfig.awgData.responsePacketMagicHeader; + } + if (!clientProtocolConfig.awgData.underloadPacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::underloadPacketMagicHeader] = clientProtocolConfig.awgData.underloadPacketMagicHeader; + } + if (!clientProtocolConfig.awgData.transportPacketMagicHeader.isEmpty()) { + clientConfigJson[config_key::transportPacketMagicHeader] = clientProtocolConfig.awgData.transportPacketMagicHeader; + } + + if (!clientProtocolConfig.wireGuardData.clientIp.isEmpty()) { + clientConfigJson[config_key::client_ip] = clientProtocolConfig.wireGuardData.clientIp; + } + if (!clientProtocolConfig.wireGuardData.clientPrivateKey.isEmpty()) { + clientConfigJson[config_key::client_priv_key] = clientProtocolConfig.wireGuardData.clientPrivateKey; + } + if (!clientProtocolConfig.wireGuardData.clientPublicKey.isEmpty()) { + clientConfigJson[config_key::client_pub_key] = clientProtocolConfig.wireGuardData.clientPublicKey; + } + if (!clientProtocolConfig.wireGuardData.persistentKeepAlive.isEmpty()) { + clientConfigJson[config_key::persistent_keep_alive] = clientProtocolConfig.wireGuardData.persistentKeepAlive; + } + if (!clientProtocolConfig.wireGuardData.pskKey.isEmpty()) { + clientConfigJson[config_key::psk_key] = clientProtocolConfig.wireGuardData.pskKey; + } + if (!clientProtocolConfig.wireGuardData.serverPubKey.isEmpty()) { + clientConfigJson[config_key::server_pub_key] = clientProtocolConfig.wireGuardData.serverPubKey; + } + if (!clientProtocolConfig.wireGuardData.mtu.isEmpty()) { + clientConfigJson[config_key::mtu] = clientProtocolConfig.wireGuardData.mtu; + } + + if (!clientProtocolConfig.wireGuardData.allowedIps.isEmpty()) { + QJsonArray allowedIpsArray; + for (const auto &ip : clientProtocolConfig.wireGuardData.allowedIps) { + if (!ip.isEmpty()) { + allowedIpsArray.append(ip); + } + } + if (!allowedIpsArray.isEmpty()) { + clientConfigJson[config_key::allowed_ips] = allowedIpsArray; + } + } + + if (!clientProtocolConfig.hostname.isEmpty()) { + clientConfigJson[config_key::hostName] = clientProtocolConfig.hostname; + } + if (clientProtocolConfig.port) { + clientConfigJson[config_key::port] = clientProtocolConfig.port; + } + if (!clientProtocolConfig.nativeConfig.isEmpty()) { + clientConfigJson[config_key::config] = clientProtocolConfig.nativeConfig; + } + + if (!clientConfigJson.isEmpty()) { + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson(QJsonDocument::Compact)); + } + } + + return json; +} diff --git a/client/core/models/protocols/awgProtocolConfig.h b/client/core/models/protocols/awgProtocolConfig.h new file mode 100644 index 00000000..7c4fcf06 --- /dev/null +++ b/client/core/models/protocols/awgProtocolConfig.h @@ -0,0 +1,65 @@ +#ifndef AWGPROTOCOLCONFIG_H +#define AWGPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" +#include "wireguardProtocolConfig.h" + +namespace awg +{ + struct AwgData + { + QString junkPacketCount; + QString junkPacketMinSize; + QString junkPacketMaxSize; + + QString initPacketJunkSize; + QString responsePacketJunkSize; + + QString initPacketMagicHeader; + QString responsePacketMagicHeader; + QString underloadPacketMagicHeader; + QString transportPacketMagicHeader; + }; + + struct ServerProtocolConfig + { + QString port; + QString transportProto; + + QString subnetAddress; + + AwgData awgData; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString clientId; + + wireguard::WireGuardData wireGuardData; + + AwgData awgData; + + QString hostname; + int port; + + QString nativeConfig; + }; +} + +class AwgProtocolConfig : public ProtocolConfig +{ +public: + AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + awg::ServerProtocolConfig serverProtocolConfig; + awg::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // AWGPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/cloakProtocolConfig.cpp b/client/core/models/protocols/cloakProtocolConfig.cpp new file mode 100644 index 00000000..b32e652e --- /dev/null +++ b/client/core/models/protocols/cloakProtocolConfig.cpp @@ -0,0 +1,43 @@ +#include "cloakProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +CloakProtocolConfig::CloakProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + } +} + +QJsonObject CloakProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.cipher.isEmpty()) { + json[config_key::cipher] = serverProtocolConfig.cipher; + } + if (!serverProtocolConfig.site.isEmpty()) { + json[config_key::site] = serverProtocolConfig.site; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + + return json; +} diff --git a/client/core/models/protocols/cloakProtocolConfig.h b/client/core/models/protocols/cloakProtocolConfig.h new file mode 100644 index 00000000..191e3f2d --- /dev/null +++ b/client/core/models/protocols/cloakProtocolConfig.h @@ -0,0 +1,35 @@ +#ifndef CLOAKPROTOCOLCONFIG_H +#define CLOAKPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace cloak +{ + struct ServerProtocolConfig + { + QString port; + QString cipher; + QString site; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class CloakProtocolConfig : public ProtocolConfig +{ +public: + CloakProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + cloak::ServerProtocolConfig serverProtocolConfig; + cloak::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // CLOAKPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/openvpnProtocolConfig.cpp b/client/core/models/protocols/openvpnProtocolConfig.cpp new file mode 100644 index 00000000..cf994566 --- /dev/null +++ b/client/core/models/protocols/openvpnProtocolConfig.cpp @@ -0,0 +1,83 @@ +#include "openvpnProtocolConfig.h" + +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +OpenVpnProtocolConfig::OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.ncpDisable = protocolConfigObject.value(config_key::ncp_disable).toString(); + serverProtocolConfig.hash = protocolConfigObject.value(config_key::hash).toString(); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + serverProtocolConfig.tlsAuth = protocolConfigObject.value(config_key::tls_auth).toString(); + serverProtocolConfig.blockOutsideDns = protocolConfigObject.value(config_key::block_outside_dns).toString(); + serverProtocolConfig.additionalClientConfig = protocolConfigObject.value(config_key::additional_client_config).toString(); + serverProtocolConfig.additionalServerConfig = protocolConfigObject.value(config_key::additional_server_config).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + + clientProtocolConfig.clientId = clientProtocolConfigObject.value(config_key::clientId).toString(); + clientProtocolConfig.nativeConfig = clientProtocolConfigObject.value(config_key::config).toString(); + } +} + +QJsonObject OpenVpnProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.subnetAddress.isEmpty()) { + json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.ncpDisable.isEmpty()) { + json[config_key::ncp_disable] = serverProtocolConfig.ncpDisable; + } + if (!serverProtocolConfig.hash.isEmpty()) { + json[config_key::hash] = serverProtocolConfig.hash; + } + if (!serverProtocolConfig.cipher.isEmpty()) { + json[config_key::cipher] = serverProtocolConfig.cipher; + } + if (!serverProtocolConfig.tlsAuth.isEmpty()) { + json[config_key::tls_auth] = serverProtocolConfig.tlsAuth; + } + if (!serverProtocolConfig.blockOutsideDns.isEmpty()) { + json[config_key::block_outside_dns] = serverProtocolConfig.blockOutsideDns; + } + if (!serverProtocolConfig.additionalClientConfig.isEmpty()) { + json[config_key::additional_client_config] = serverProtocolConfig.additionalClientConfig; + } + if (!serverProtocolConfig.additionalServerConfig.isEmpty()) { + json[config_key::additional_server_config] = serverProtocolConfig.additionalServerConfig; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + + if (!clientProtocolConfig.clientId.isEmpty()) { + clientConfigJson[config_key::clientId] = clientProtocolConfig.clientId; + } + if (!clientProtocolConfig.nativeConfig.isEmpty()) { + clientConfigJson[config_key::config] = clientProtocolConfig.nativeConfig; + } + + if (!clientConfigJson.isEmpty()) { + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + } + + return json; +} diff --git a/client/core/models/protocols/openvpnProtocolConfig.h b/client/core/models/protocols/openvpnProtocolConfig.h new file mode 100644 index 00000000..0e6d4e6a --- /dev/null +++ b/client/core/models/protocols/openvpnProtocolConfig.h @@ -0,0 +1,46 @@ +#ifndef OPENVPNPROTOCOLCONFIG_H +#define OPENVPNPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace openvpn +{ + struct ServerProtocolConfig + { + QString subnetAddress; + QString transportProto; + QString port; + QString ncpDisable; + QString hash; + QString cipher; + QString tlsAuth; + QString blockOutsideDns; + QString additionalClientConfig; + QString additionalServerConfig; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString clientId; + + QString nativeConfig; + }; +} + +class OpenVpnProtocolConfig : public ProtocolConfig +{ +public: + OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + openvpn::ServerProtocolConfig serverProtocolConfig; + openvpn::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // OPENVPNPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/protocolConfig.cpp b/client/core/models/protocols/protocolConfig.cpp new file mode 100644 index 00000000..58b9387d --- /dev/null +++ b/client/core/models/protocols/protocolConfig.cpp @@ -0,0 +1,12 @@ +#include "protocolConfig.h" + +#include + +ProtocolConfig::ProtocolConfig(const QString &protocolName) : protocolName(protocolName) +{ +} + +QJsonObject ProtocolConfig::toJson() const +{ + return QJsonObject(); +} diff --git a/client/core/models/protocols/protocolConfig.h b/client/core/models/protocols/protocolConfig.h new file mode 100644 index 00000000..ce917002 --- /dev/null +++ b/client/core/models/protocols/protocolConfig.h @@ -0,0 +1,16 @@ +#ifndef PROTOCOLCONFIG_H +#define PROTOCOLCONFIG_H + +#include + +class ProtocolConfig +{ +public: + ProtocolConfig(const QString &protocolName); + + QString protocolName; + + virtual QJsonObject toJson() const; +}; + +#endif // PROTOCOLCONFIG_H diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.cpp b/client/core/models/protocols/shadowsocksProtocolConfig.cpp new file mode 100644 index 00000000..e5f9b978 --- /dev/null +++ b/client/core/models/protocols/shadowsocksProtocolConfig.cpp @@ -0,0 +1,39 @@ +#include "shadowsocksProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +ShadowsocksProtocolConfig::ShadowsocksProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + } +} + +QJsonObject ShadowsocksProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.cipher.isEmpty()) { + json[config_key::cipher] = serverProtocolConfig.cipher; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + + return json; +} diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.h b/client/core/models/protocols/shadowsocksProtocolConfig.h new file mode 100644 index 00000000..3c615f8a --- /dev/null +++ b/client/core/models/protocols/shadowsocksProtocolConfig.h @@ -0,0 +1,34 @@ +#ifndef SHADOWSOCKSPROTOCOLCONFIG_H +#define SHADOWSOCKSPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace shadowsocks +{ + struct ServerProtocolConfig + { + QString port; + QString cipher; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class ShadowsocksProtocolConfig : public ProtocolConfig +{ +public: + ShadowsocksProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + shadowsocks::ServerProtocolConfig serverProtocolConfig; + shadowsocks::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // SHADOWSOCKSPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/wireguardProtocolConfig.cpp b/client/core/models/protocols/wireguardProtocolConfig.cpp new file mode 100644 index 00000000..602cbce5 --- /dev/null +++ b/client/core/models/protocols/wireguardProtocolConfig.cpp @@ -0,0 +1,120 @@ +#include "wireguardProtocolConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +WireGuardProtocolConfig::WireGuardProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) + : ProtocolConfig(protocolName) +{ + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + + clientProtocolConfig.clientId = clientProtocolConfigObject.value(config_key::clientId).toString(); + + clientProtocolConfig.wireGuardData.clientIp = clientProtocolConfigObject.value(config_key::client_ip).toString(); + clientProtocolConfig.wireGuardData.clientPrivateKey = clientProtocolConfigObject.value(config_key::client_priv_key).toString(); + clientProtocolConfig.wireGuardData.clientPublicKey = clientProtocolConfigObject.value(config_key::client_pub_key).toString(); + clientProtocolConfig.wireGuardData.persistentKeepAlive = + clientProtocolConfigObject.value(config_key::persistent_keep_alive).toString(); + clientProtocolConfig.wireGuardData.pskKey = clientProtocolConfigObject.value(config_key::psk_key).toString(); + clientProtocolConfig.wireGuardData.serverPubKey = clientProtocolConfigObject.value(config_key::server_pub_key).toString(); + clientProtocolConfig.wireGuardData.mtu = clientProtocolConfigObject.value(config_key::mtu).toString(); + + clientProtocolConfig.hostname = clientProtocolConfigObject.value(config_key::hostName).toString(); + clientProtocolConfig.port = clientProtocolConfigObject.value(config_key::port).toInt(0); + + clientProtocolConfig.nativeConfig = clientProtocolConfigObject.value(config_key::config).toString(); + + if (clientProtocolConfigObject.contains(config_key::allowed_ips) + && clientProtocolConfigObject.value(config_key::allowed_ips).isArray()) { + auto allowedIpsArray = clientProtocolConfigObject.value(config_key::allowed_ips).toArray(); + for (const auto &ip : allowedIpsArray) { + clientProtocolConfig.wireGuardData.allowedIps.append(ip.toString()); + } + } + } +} + +QJsonObject WireGuardProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + if (!serverProtocolConfig.subnetAddress.isEmpty()) { + json[config_key::subnet_address] = serverProtocolConfig.subnetAddress; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + + if (!clientProtocolConfig.clientId.isEmpty()) { + clientConfigJson[config_key::clientId] = clientProtocolConfig.clientId; + } + + if (!clientProtocolConfig.wireGuardData.clientIp.isEmpty()) { + clientConfigJson[config_key::client_ip] = clientProtocolConfig.wireGuardData.clientIp; + } + if (!clientProtocolConfig.wireGuardData.clientPrivateKey.isEmpty()) { + clientConfigJson[config_key::client_priv_key] = clientProtocolConfig.wireGuardData.clientPrivateKey; + } + if (!clientProtocolConfig.wireGuardData.clientPublicKey.isEmpty()) { + clientConfigJson[config_key::client_pub_key] = clientProtocolConfig.wireGuardData.clientPublicKey; + } + if (!clientProtocolConfig.wireGuardData.persistentKeepAlive.isEmpty()) { + clientConfigJson[config_key::persistent_keep_alive] = clientProtocolConfig.wireGuardData.persistentKeepAlive; + } + if (!clientProtocolConfig.wireGuardData.pskKey.isEmpty()) { + clientConfigJson[config_key::psk_key] = clientProtocolConfig.wireGuardData.pskKey; + } + if (!clientProtocolConfig.wireGuardData.serverPubKey.isEmpty()) { + clientConfigJson[config_key::server_pub_key] = clientProtocolConfig.wireGuardData.serverPubKey; + } + if (!clientProtocolConfig.wireGuardData.mtu.isEmpty()) { + clientConfigJson[config_key::mtu] = clientProtocolConfig.wireGuardData.mtu; + } + + if (!clientProtocolConfig.wireGuardData.allowedIps.isEmpty()) { + QJsonArray allowedIpsArray; + for (const auto &ip : clientProtocolConfig.wireGuardData.allowedIps) { + if (!ip.isEmpty()) { + allowedIpsArray.append(ip); + } + } + if (!allowedIpsArray.isEmpty()) { + clientConfigJson[config_key::allowed_ips] = allowedIpsArray; + } + } + + if (!clientProtocolConfig.hostname.isEmpty()) { + clientConfigJson[config_key::hostName] = clientProtocolConfig.hostname; + } + if (clientProtocolConfig.port) { + clientConfigJson[config_key::port] = clientProtocolConfig.port; + } + if (!clientProtocolConfig.nativeConfig.isEmpty()) { + clientConfigJson[config_key::config] = clientProtocolConfig.nativeConfig; + } + + if (!clientConfigJson.isEmpty()) { + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + } + + return json; +} diff --git a/client/core/models/protocols/wireguardProtocolConfig.h b/client/core/models/protocols/wireguardProtocolConfig.h new file mode 100644 index 00000000..acefafe2 --- /dev/null +++ b/client/core/models/protocols/wireguardProtocolConfig.h @@ -0,0 +1,58 @@ +#ifndef WIREGUARDPROTOCOLCONFIG_H +#define WIREGUARDPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace wireguard +{ + struct WireGuardData + { + QStringList allowedIps; + + QString clientIp; + QString clientPrivateKey; + QString clientPublicKey; + QString mtu; + QString persistentKeepAlive; + QString pskKey; + QString serverPubKey; + }; + + struct ServerProtocolConfig + { + QString port; + QString transportProto; + + QString subnetAddress; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + + QString clientId; + + WireGuardData wireGuardData; + + QString hostname; + int port; + + QString nativeConfig; + }; +} + +class WireGuardProtocolConfig : public ProtocolConfig +{ +public: + WireGuardProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + wireguard::ServerProtocolConfig serverProtocolConfig; + wireguard::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // WIREGUARDPROTOCOLCONFIG_H diff --git a/client/core/models/protocols/xrayProtocolConfig.cpp b/client/core/models/protocols/xrayProtocolConfig.cpp new file mode 100644 index 00000000..32ad108a --- /dev/null +++ b/client/core/models/protocols/xrayProtocolConfig.cpp @@ -0,0 +1,43 @@ +#include "xrayProtocolConfig.h" + +#include +#include +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +XrayProtocolConfig::XrayProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +{ + serverProtocolConfig.site = protocolConfigObject.value(config_key::site).toString(); + serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); + serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); + + auto clientProtocolString = protocolConfigObject.value(config_key::last_config).toString(); + if (!clientProtocolString.isEmpty()) { + clientProtocolConfig.isEmpty = false; + + QJsonObject clientProtocolConfigObject = QJsonDocument::fromJson(clientProtocolString.toUtf8()).object(); + } +} + +QJsonObject XrayProtocolConfig::toJson() const +{ + QJsonObject json; + + if (!serverProtocolConfig.site.isEmpty()) { + json[config_key::site] = serverProtocolConfig.site; + } + if (!serverProtocolConfig.port.isEmpty()) { + json[config_key::port] = serverProtocolConfig.port; + } + if (!serverProtocolConfig.transportProto.isEmpty()) { + json[config_key::transport_proto] = serverProtocolConfig.transportProto; + } + + if (!clientProtocolConfig.isEmpty) { + QJsonObject clientConfigJson; + json[config_key::last_config] = QString(QJsonDocument(clientConfigJson).toJson()); + } + + return json; +} diff --git a/client/core/models/protocols/xrayProtocolConfig.h b/client/core/models/protocols/xrayProtocolConfig.h new file mode 100644 index 00000000..87023954 --- /dev/null +++ b/client/core/models/protocols/xrayProtocolConfig.h @@ -0,0 +1,35 @@ +#ifndef XRAYPROTOCOLCONFIG_H +#define XRAYPROTOCOLCONFIG_H + +#include +#include + +#include "protocolConfig.h" + +namespace xray +{ + struct ServerProtocolConfig + { + QString site; + QString port; + QString transportProto; + }; + + struct ClientProtocolConfig + { + bool isEmpty = true; + }; +} + +class XrayProtocolConfig : public ProtocolConfig +{ +public: + XrayProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + + QJsonObject toJson() const override; + + xray::ServerProtocolConfig serverProtocolConfig; + xray::ClientProtocolConfig clientProtocolConfig; +}; + +#endif // XRAYPROTOCOLCONFIG_H diff --git a/client/core/models/servers/apiV1ServerConfig.cpp b/client/core/models/servers/apiV1ServerConfig.cpp new file mode 100644 index 00000000..363c1d9e --- /dev/null +++ b/client/core/models/servers/apiV1ServerConfig.cpp @@ -0,0 +1,30 @@ +#include "apiV1ServerConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +ApiV1ServerConfig::ApiV1ServerConfig(const QJsonObject &serverConfigObject) : ServerConfig(serverConfigObject) +{ + name = serverConfigObject.value(config_key::name).toString(); + description = serverConfigObject.value(config_key::description).toString(); +} + +QJsonObject ApiV1ServerConfig::toJson() const +{ + // Сначала вызываем родительскую функцию для сериализации базовых полей + QJsonObject json = ServerConfig::toJson(); + + // Добавляем свои поля только если они не пустые + if (!name.isEmpty()) { + json[config_key::name] = name; + } + if (!description.isEmpty()) { + json[config_key::description] = description; + } + + return json; +} diff --git a/client/core/models/servers/apiV1ServerConfig.h b/client/core/models/servers/apiV1ServerConfig.h new file mode 100644 index 00000000..c3a9e52b --- /dev/null +++ b/client/core/models/servers/apiV1ServerConfig.h @@ -0,0 +1,17 @@ +#ifndef APIV1SERVERCONFIG_H +#define APIV1SERVERCONFIG_H + +#include "serverConfig.h" + +class ApiV1ServerConfig : public ServerConfig +{ +public: + ApiV1ServerConfig(const QJsonObject &serverConfigObject); + + QJsonObject toJson() const override; + + QString name; + QString description; +}; + +#endif // APIV1SERVERCONFIG_H diff --git a/client/core/models/servers/apiV2ServerConfig.cpp b/client/core/models/servers/apiV2ServerConfig.cpp new file mode 100644 index 00000000..97e27dcb --- /dev/null +++ b/client/core/models/servers/apiV2ServerConfig.cpp @@ -0,0 +1,125 @@ +#include "apiV2ServerConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +ApiV2ServerConfig::ApiV2ServerConfig(const QJsonObject &serverConfigObject) : ServerConfig(serverConfigObject) +{ + name = serverConfigObject.value(config_key::name).toString(); + description = serverConfigObject.value(config_key::description).toString(); + + auto apiConfigObject = serverConfigObject.value("api_config").toObject(); + + auto availableCountriesArray = apiConfigObject.value("available_countries").toArray(); + for (const auto &countryValue : availableCountriesArray) { + auto countryObject = countryValue.toObject(); + apiv2::Country country; + country.code = countryObject.value("server_country_code").toString(); + country.name = countryObject.value("server_country_name").toString(); + apiConfig.availableCountries.append(country); + } + + auto subscriptionObject = apiConfigObject.value("subscription").toObject(); + apiConfig.subscription.end_date = subscriptionObject.value("end_date").toString(); + + auto publicKeyObject = apiConfigObject.value("public_key").toObject(); + apiConfig.publicKey.expiresAt = publicKeyObject.value("expires_at").toString(); + + apiConfig.serverCountryCode = apiConfigObject.value("server_country_code").toString(); + apiConfig.serverCountryName = apiConfigObject.value("server_country_name").toString(); + + apiConfig.serviceProtocol = apiConfigObject.value("service_protocol").toString(); + apiConfig.serviceType = apiConfigObject.value("service_type").toString(); + + apiConfig.userCountryCode = apiConfigObject.value("user_country_code").toString(); + + apiConfig.vpnKey = apiConfigObject.value("vpn_key").toString(); +} + +QJsonObject ApiV2ServerConfig::toJson() const +{ + // Сначала вызываем родительскую функцию для сериализации базовых полей + QJsonObject json = ServerConfig::toJson(); + + // Добавляем свои поля только если они не пустые + if (!name.isEmpty()) { + json[config_key::name] = name; + } + if (!description.isEmpty()) { + json[config_key::description] = description; + } + + // Сериализация API конфигурации + QJsonObject apiConfigJson; + + // Сериализация доступных стран только если массив не пустой + if (!apiConfig.availableCountries.isEmpty()) { + QJsonArray availableCountriesArray; + for (const auto &country : apiConfig.availableCountries) { + QJsonObject countryObject; + if (!country.code.isEmpty()) { + countryObject["server_country_code"] = country.code; + } + if (!country.name.isEmpty()) { + countryObject["server_country_name"] = country.name; + } + if (!countryObject.isEmpty()) { + availableCountriesArray.append(countryObject); + } + } + if (!availableCountriesArray.isEmpty()) { + apiConfigJson["available_countries"] = availableCountriesArray; + } + } + + // Сериализация подписки только если есть данные + if (!apiConfig.subscription.end_date.isEmpty()) { + QJsonObject subscriptionObject; + subscriptionObject["end_date"] = apiConfig.subscription.end_date; + apiConfigJson["subscription"] = subscriptionObject; + } + + // Сериализация публичного ключа только если есть данные + if (!apiConfig.publicKey.expiresAt.isEmpty()) { + QJsonObject publicKeyObject; + publicKeyObject["expires_at"] = apiConfig.publicKey.expiresAt; + apiConfigJson["public_key"] = publicKeyObject; + } + + // Сериализация информации о сервере только если не пустая + if (!apiConfig.serverCountryCode.isEmpty()) { + apiConfigJson["server_country_code"] = apiConfig.serverCountryCode; + } + if (!apiConfig.serverCountryName.isEmpty()) { + apiConfigJson["server_country_name"] = apiConfig.serverCountryName; + } + + // Сериализация информации о сервисе только если не пустая + if (!apiConfig.serviceProtocol.isEmpty()) { + apiConfigJson["service_protocol"] = apiConfig.serviceProtocol; + } + if (!apiConfig.serviceType.isEmpty()) { + apiConfigJson["service_type"] = apiConfig.serviceType; + } + + // Сериализация информации о пользователе только если не пустая + if (!apiConfig.userCountryCode.isEmpty()) { + apiConfigJson["user_country_code"] = apiConfig.userCountryCode; + } + + // Сериализация VPN ключа только если не пустой + if (!apiConfig.vpnKey.isEmpty()) { + apiConfigJson["vpn_key"] = apiConfig.vpnKey; + } + + // Добавляем API конфигурацию в основной JSON только если есть данные + if (!apiConfigJson.isEmpty()) { + json["api_config"] = apiConfigJson; + } + + return json; +} diff --git a/client/core/models/servers/apiV2ServerConfig.h b/client/core/models/servers/apiV2ServerConfig.h new file mode 100644 index 00000000..782e82ef --- /dev/null +++ b/client/core/models/servers/apiV2ServerConfig.h @@ -0,0 +1,54 @@ +#ifndef APIV2SERVERCONFIG_H +#define APIV2SERVERCONFIG_H + +#include "serverConfig.h" + +namespace apiv2 +{ + struct Country { + QString code; + QString name; + }; + + struct PublicKey + { + QString expiresAt; + }; + + struct Subscription + { + QString end_date; + }; + + struct ApiConfig { + QVector availableCountries; + + Subscription subscription; + PublicKey publicKey; + + QString serverCountryCode; + QString serverCountryName; + + QString serviceProtocol; + QString serviceType; + + QString userCountryCode; + + QString vpnKey; + }; +} + +class ApiV2ServerConfig : public ServerConfig +{ +public: + ApiV2ServerConfig(const QJsonObject &serverConfigObject); + + QJsonObject toJson() const override; + + QString name; + QString description; + + apiv2::ApiConfig apiConfig; +}; + +#endif // APIV2SERVERCONFIG_H diff --git a/client/core/models/servers/selfHostedServerConfig.cpp b/client/core/models/servers/selfHostedServerConfig.cpp new file mode 100644 index 00000000..b2cf189a --- /dev/null +++ b/client/core/models/servers/selfHostedServerConfig.cpp @@ -0,0 +1,48 @@ +#include "selfHostedServerConfig.h" + +#include +#include + +#include "protocols/protocols_defs.h" + +using namespace amnezia; + +SelfHostedServerConfig::SelfHostedServerConfig(const QJsonObject &serverConfigObject) : ServerConfig(serverConfigObject) +{ + name = serverConfigObject.value(config_key::description).toString(); + if (name.isEmpty()) { + name = serverConfigObject.value(config_key::hostName).toString(); + } + + serverCredentials.hostName = serverConfigObject.value(config_key::hostName).toString(); + serverCredentials.userName = serverConfigObject.value(config_key::userName).toString(); + serverCredentials.secretData = serverConfigObject.value(config_key::password).toString(); + serverCredentials.port = serverConfigObject.value(config_key::port).toInt(22); +} + +QJsonObject SelfHostedServerConfig::toJson() const +{ + // Сначала вызываем родительскую функцию для сериализации базовых полей + QJsonObject json = ServerConfig::toJson(); + + // Добавляем имя только если оно не пустое + if (!name.isEmpty()) { + json[config_key::description] = name; // Используем description как в конструкторе + } + + // Добавляем credentials только если они не пустые + if (!serverCredentials.hostName.isEmpty()) { + json[config_key::hostName] = serverCredentials.hostName; + } + if (!serverCredentials.userName.isEmpty()) { + json[config_key::userName] = serverCredentials.userName; + } + if (!serverCredentials.secretData.isEmpty()) { + json[config_key::password] = serverCredentials.secretData; + } + if (serverCredentials.port != 22) { // Добавляем порт только если не дефолтный + json[config_key::port] = serverCredentials.port; + } + + return json; +} diff --git a/client/core/models/servers/selfHostedServerConfig.h b/client/core/models/servers/selfHostedServerConfig.h new file mode 100644 index 00000000..c11b8aa4 --- /dev/null +++ b/client/core/models/servers/selfHostedServerConfig.h @@ -0,0 +1,19 @@ +#ifndef SELFHOSTEDSERVERCONFIG_H +#define SELFHOSTEDSERVERCONFIG_H + +#include "core/defs.h" +#include "serverConfig.h" + +class SelfHostedServerConfig : public ServerConfig +{ +public: + SelfHostedServerConfig(const QJsonObject &serverConfigObject); + + QJsonObject toJson() const override; + + QString name; + + amnezia::ServerCredentials serverCredentials; +}; + +#endif // SELFHOSTEDSERVERCONFIG_H diff --git a/client/core/models/servers/serverConfig.cpp b/client/core/models/servers/serverConfig.cpp new file mode 100644 index 00000000..977f8763 --- /dev/null +++ b/client/core/models/servers/serverConfig.cpp @@ -0,0 +1,145 @@ +#include "serverConfig.h" + +#include + +#include "apiV1ServerConfig.h" +#include "apiV2ServerConfig.h" +#include "containers/containers_defs.h" +#include "core/models/protocols/awgProtocolConfig.h" +#include "core/models/protocols/cloakProtocolConfig.h" +#include "core/models/protocols/openvpnProtocolConfig.h" +#include "core/models/protocols/protocolConfig.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "core/models/protocols/xrayProtocolConfig.h" +#include "protocols/protocols_defs.h" +#include "selfHostedServerConfig.h" + +using namespace amnezia; + +ServerConfig::ServerConfig(const QJsonObject &serverConfigObject) +{ + type = static_cast(serverConfigObject.value(config_key::configVersion).toInt(0)); + + hostName = serverConfigObject.value(config_key::hostName).toString(); + + dns1 = serverConfigObject.value(config_key::dns1).toString(); + dns2 = serverConfigObject.value(config_key::dns2).toString(); + + defaultContainer = serverConfigObject.value(config_key::defaultContainer).toString(); + + auto containers = serverConfigObject.value(config_key::containers).toArray(); + for (const auto &container : std::as_const(containers)) { + auto containerObject = container.toObject(); + + auto containerName = containerObject.value(config_key::container).toString(); + + ContainerConfig containerConfig; + containerConfig.containerName = containerName; + + auto protocols = ContainerProps::protocolsForContainer(ContainerProps::containerFromString(containerName)); + for (const auto &protocol : protocols) { + auto protocolName = ProtocolProps::protoToString(protocol); + auto protocolConfigObject = containerObject.value(protocolName).toObject(); + + switch (protocol) { + case Proto::OpenVpn: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::ShadowSocks: { + containerConfig.protocolConfigs.insert( + protocolName, QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Cloak: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::WireGuard: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Awg: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Xray: { + containerConfig.protocolConfigs.insert(protocolName, + QSharedPointer::create(protocolConfigObject, protocolName)); + break; + } + case Proto::Ikev2: break; + case Proto::L2tp: break; + case Proto::SSXray: break; + case Proto::TorWebSite: break; + case Proto::Dns: break; + case Proto::Sftp: break; + case Proto::Socks5Proxy: break; + default: break; + } + } + + containerConfigs.insert(containerName, containerConfig); + } +} + +QSharedPointer ServerConfig::createServerConfig(const QJsonObject &serverConfigObject) +{ + auto type = static_cast(serverConfigObject.value(config_key::configVersion).toInt(0)); + + switch (type) { + case ServerConfigType::SelfHosted: return QSharedPointer::create(serverConfigObject); + case ServerConfigType::ApiV1: return QSharedPointer::create(serverConfigObject); + case ServerConfigType::ApiV2: return QSharedPointer::create(serverConfigObject); + } +} + +QJsonObject ServerConfig::toJson() const +{ + QJsonObject json; + + if (type != ServerConfigType::SelfHosted) { + json[config_key::configVersion] = static_cast(type); + } + + if (!hostName.isEmpty()) { + json[config_key::hostName] = hostName; + } + if (!dns1.isEmpty()) { + json[config_key::dns1] = dns1; + } + if (!dns2.isEmpty()) { + json[config_key::dns2] = dns2; + } + if (!defaultContainer.isEmpty()) { + json[config_key::defaultContainer] = defaultContainer; + } + + if (!containerConfigs.isEmpty()) { + QJsonArray containersArray; + for (const auto &containerConfig : containerConfigs) { + QJsonObject containerObject; + containerObject[config_key::container] = containerConfig.containerName; + + if (!containerConfig.protocolConfigs.isEmpty()) { + for (const auto &protocolConfig : containerConfig.protocolConfigs) { + QJsonObject protocolJson = protocolConfig->toJson(); + if (!protocolJson.isEmpty()) { + containerObject[protocolConfig->protocolName] = protocolJson; + } + } + } + + containersArray.append(containerObject); + } + if (!containersArray.isEmpty()) { + json[config_key::containers] = containersArray; + } + } + + return json; +} diff --git a/client/core/models/servers/serverConfig.h b/client/core/models/servers/serverConfig.h new file mode 100644 index 00000000..5559b507 --- /dev/null +++ b/client/core/models/servers/serverConfig.h @@ -0,0 +1,32 @@ +#ifndef SERVERCONFIG_H +#define SERVERCONFIG_H + +#include +#include +#include + +#include "core/defs.h" +#include "core/models/containers/containerConfig.h" + +class ServerConfig +{ +public: + ServerConfig(const QJsonObject &serverConfigObject); + + virtual QJsonObject toJson() const; + + static QSharedPointer createServerConfig(const QJsonObject &serverConfigObject); + + amnezia::ServerConfigType type; + + QString hostName; + + QString dns1; + QString dns2; + + QString defaultContainer; + + QMap containerConfigs; +}; + +#endif // SERVERCONFIG_H diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 4c58140c..a805dae2 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -398,16 +398,16 @@ bool ApiConfigsController::isConfigValid() QJsonObject serverConfigObject = m_serversModel->getServerConfig(serverIndex); auto configSource = apiUtils::getConfigSource(serverConfigObject); - if (configSource == apiDefs::ConfigSource::Telegram + if (configSource == amnezia::ServerConfigType::ApiV1 && !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { m_serversModel->removeApiConfig(serverIndex); return updateServiceFromTelegram(serverIndex); - } else if (configSource == apiDefs::ConfigSource::AmneziaGateway + } else if (configSource == amnezia::ServerConfigType::ApiV2 && !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) { return updateServiceFromGateway(serverIndex, "", ""); } else if (configSource && m_serversModel->isApiKeyExpired(serverIndex)) { qDebug() << "attempt to update api config by expires_at event"; - if (configSource == apiDefs::ConfigSource::AmneziaGateway) { + if (configSource == amnezia::ServerConfigType::ApiV2) { return updateServiceFromGateway(serverIndex, "", ""); } else { m_serversModel->removeApiConfig(serverIndex); @@ -499,7 +499,7 @@ void ApiConfigsController::fillServerConfig(const QString &protocol, const ApiPa serverConfig[config_key::containers] = newServerConfig.value(config_key::containers); serverConfig[config_key::hostName] = newServerConfig.value(config_key::hostName); - if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) { + if (newServerConfig.value(config_key::configVersion).toInt() == amnezia::ServerConfigType::ApiV2) { serverConfig[config_key::configVersion] = newServerConfig.value(config_key::configVersion); serverConfig[config_key::description] = newServerConfig.value(config_key::description); serverConfig[config_key::name] = newServerConfig.value(config_key::name); @@ -512,7 +512,7 @@ void ApiConfigsController::fillServerConfig(const QString &protocol, const ApiPa map.insert(newServerConfig.value(configKey::apiConfig).toObject().toVariantMap()); auto apiConfig = QJsonObject::fromVariantMap(map); - if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) { + if (newServerConfig.value(config_key::configVersion).toInt() == amnezia::ServerConfigType::ApiV2) { apiConfig.insert(configKey::serviceInfo, QJsonDocument::fromJson(apiResponseBody).object().value(configKey::serviceInfo).toObject()); } diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 5a70c16f..f76fea89 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -2,6 +2,9 @@ #include "core/api/apiDefs.h" #include "core/controllers/serverController.h" +#include "core/models/servers/apiV1ServerConfig.h" +#include "core/models/servers/apiV2ServerConfig.h" +#include "core/models/servers/selfHostedServerConfig.h" #include "core/networkUtilities.h" #ifdef Q_OS_IOS @@ -24,6 +27,9 @@ namespace constexpr char publicKeyInfo[] = "public_key"; constexpr char expiresAt[] = "expires_at"; } + + using ServerConfigVariant = + std::variant, QSharedPointer, QSharedPointer >; } ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) @@ -91,29 +97,26 @@ bool ServersModel::setData(const int index, const QVariant &value, int role) QVariant ServersModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers.size())) { + if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers1.size())) { return QVariant(); } - const QJsonObject server = m_servers.at(index.row()).toObject(); - const auto apiConfig = server.value(configKey::apiConfig).toObject(); - const auto configVersion = server.value(config_key::configVersion).toInt(); + QSharedPointer serverConfig = m_servers1.at(index.row()); + ServerConfigVariant variant; + switch (serverConfig->type) { + case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; + } + switch (role) { case NameRole: { - if (configVersion) { - return server.value(config_key::name).toString(); - } - auto name = server.value(config_key::description).toString(); - if (name.isEmpty()) { - return server.value(config_key::hostName).toString(); - } - return name; + return std::visit([](const auto &ptr) -> QString { return ptr->name; }, variant); } case ServerDescriptionRole: { - auto description = getServerDescription(server, index.row()); - return configVersion ? description : description + server.value(config_key::hostName).toString(); + return getServerDescription(index.row()); } - case HostNameRole: return server.value(config_key::hostName).toString(); + case HostNameRole: return serverConfig->hostName; case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row())); case CredentialsLoginRole: return serverCredentials(index.row()).userName; case IsDefaultRole: return index.row() == m_defaultServerIndex; @@ -123,36 +126,28 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty()); } case ContainsAmneziaDnsRole: { - QString primaryDns = server.value(config_key::dns1).toString(); - return primaryDns == protocols::dns::amneziaDnsIp; + return serverConfig->dns1 == protocols::dns::amneziaDnsIp; } case DefaultContainerRole: { - return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + return ContainerProps::containerFromString(serverConfig->defaultContainer); } case HasInstalledContainers: { return serverHasInstalledContainers(index.row()); } case IsServerFromTelegramApiRole: { - return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::Telegram; + return serverConfig->type == amnezia::ServerConfigType::ApiV1; } case IsServerFromGatewayApiRole: { - return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway; - } - case ApiConfigRole: { - return apiConfig; + return serverConfig->type == amnezia::ServerConfigType::ApiV2; } case IsCountrySelectionAvailableRole: { - return !apiConfig.value(configKey::availableCountries).toArray().isEmpty(); + return !qSharedPointerCast(serverConfig)->apiConfig.availableCountries.isEmpty(); } case ApiAvailableCountriesRole: { - return apiConfig.value(configKey::availableCountries).toArray(); + return QVariant::fromValue(qSharedPointerCast(serverConfig)->apiConfig.availableCountries); } case ApiServerCountryCodeRole: { - return apiConfig.value(configKey::serverCountryCode).toString(); - } - case HasAmneziaDns: { - QString primaryDns = server.value(config_key::dns1).toString(); - return primaryDns == protocols::dns::amneziaDnsIp; + return qSharedPointerCast(serverConfig)->apiConfig.serverCountryCode; } } @@ -171,6 +166,25 @@ void ServersModel::resetModel() m_servers = m_settings->serversArray(); m_defaultServerIndex = m_settings->defaultServerIndex(); m_processedServerIndex = m_defaultServerIndex; + + for (auto server : m_servers) { + auto serverConfig = ServerConfig::createServerConfig(server.toObject()); + m_servers1.push_back(serverConfig); + qDebug() << "333"; + qDebug() << server.toObject(); + qDebug() << "333"; + + ServerConfigVariant variant; + switch (serverConfig->type) { + case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; + } + qDebug() << "123"; + qDebug() << std::visit([](const auto &ptr) -> QJsonObject { return ptr->toJson(); }, variant); + qDebug() << "123"; + } + endResetModel(); emit defaultServerIndexChanged(m_defaultServerIndex); } @@ -192,34 +206,40 @@ const QString ServersModel::getDefaultServerName() return qvariant_cast(data(m_defaultServerIndex, NameRole)); } -QString ServersModel::getServerDescription(const QJsonObject &server, const int index) const +QString ServersModel::getServerDescription(const int index) const { - const auto configVersion = server.value(config_key::configVersion).toInt(); - const auto apiConfig = server.value(configKey::apiConfig).toObject(); - - QString description; - - if (configVersion && !apiConfig.value(configKey::serverCountryCode).toString().isEmpty()) { - return apiConfig.value(configKey::serverCountryName).toString(); - } else if (configVersion) { - return server.value(config_key::description).toString(); - } else if (data(index, HasWriteAccessRole).toBool()) { - if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) { - description += "Amnezia DNS | "; - } - } else { - if (data(index, HasAmneziaDns).toBool()) { - description += "Amnezia DNS | "; + auto serverConfig = m_servers1.at(index); + switch (serverConfig->type) { + case amnezia::ServerConfigType::ApiV1: return qSharedPointerCast(serverConfig)->description; + case amnezia::ServerConfigType::ApiV2: { + auto apiV2ServerConfig = qSharedPointerCast(serverConfig); + if (apiV2ServerConfig->apiConfig.serverCountryCode.isEmpty()) { + return apiV2ServerConfig->description; + } else { + return apiV2ServerConfig->apiConfig.serverCountryName; } } - return description; + case amnezia::ServerConfigType::SelfHosted: { + QString description; + if (data(index, HasWriteAccessRole).toBool()) { + if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) { + description += "Amnezia DNS | " + serverConfig->hostName; + } + } else { + if (data(index, ContainsAmneziaDnsRole).toBool()) { + description += "Amnezia DNS | " + serverConfig->hostName; + } + } + return description; + } + } } const QString ServersModel::getDefaultServerDescriptionCollapsed() { const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); const auto configVersion = server.value(config_key::configVersion).toInt(); - auto description = getServerDescription(server, m_defaultServerIndex); + auto description = getServerDescription(m_defaultServerIndex); if (configVersion) { return description; } @@ -233,7 +253,7 @@ const QString ServersModel::getDefaultServerDescriptionExpanded() { const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); const auto configVersion = server.value(config_key::configVersion).toInt(); - auto description = getServerDescription(server, m_defaultServerIndex); + auto description = getServerDescription(m_defaultServerIndex); if (configVersion) { return description; } @@ -395,7 +415,6 @@ QHash ServersModel::roleNames() const roles[IsServerFromTelegramApiRole] = "isServerFromTelegramApi"; roles[IsServerFromGatewayApiRole] = "isServerFromGatewayApi"; - roles[ApiConfigRole] = "apiConfig"; roles[IsCountrySelectionAvailableRole] = "isCountrySelectionAvailable"; roles[ApiAvailableCountriesRole] = "apiAvailableCountries"; roles[ApiServerCountryCodeRole] = "apiServerCountryCode"; @@ -404,15 +423,8 @@ QHash ServersModel::roleNames() const ServerCredentials ServersModel::serverCredentials(int index) const { - const QJsonObject &s = m_servers.at(index).toObject(); - - ServerCredentials credentials; - credentials.hostName = s.value(config_key::hostName).toString(); - credentials.userName = s.value(config_key::userName).toString(); - credentials.secretData = s.value(config_key::password).toString(); - credentials.port = s.value(config_key::port).toInt(); - - return credentials; + const auto serverConfig = m_servers1.at(index); + return qSharedPointerCast(serverConfig)->serverCredentials; } void ServersModel::updateContainersModel() @@ -670,14 +682,14 @@ bool ServersModel::isServerFromApiAlreadyExists(const QString &userCountryCode, bool ServersModel::serverHasInstalledContainers(const int serverIndex) const { - QJsonObject server = m_servers.at(serverIndex).toObject(); - const auto containers = server.value(config_key::containers).toArray(); - for (auto it = containers.begin(); it != containers.end(); it++) { - auto container = ContainerProps::containerFromString(it->toObject().value(config_key::container).toString()); - if (ContainerProps::containerService(container) == ServiceType::Vpn) { + auto server = m_servers1.at(serverIndex); + const auto containers = server->containerConfigs; + for (const auto &container : containers) { + auto dockerContainer = ContainerProps::containerFromString(container.containerName); + if (ContainerProps::containerService(dockerContainer) == ServiceType::Vpn) { return true; } - if (container == DockerContainer::SSXray) { + if (dockerContainer == DockerContainer::SSXray) { return true; } } diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index c4803708..f0649e7d 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -4,6 +4,7 @@ #include #include "core/controllers/serverController.h" +#include "core/models/servers/serverConfig.h" #include "settings.h" class ServersModel : public QAbstractListModel @@ -36,9 +37,7 @@ public: ApiConfigRole, IsCountrySelectionAvailableRole, ApiAvailableCountriesRole, - ApiServerCountryCodeRole, - - HasAmneziaDns + ApiServerCountryCodeRole }; ServersModel(std::shared_ptr settings, QObject *parent = nullptr); @@ -150,13 +149,14 @@ private: void updateContainersModel(); void updateDefaultServerContainersModel(); - QString getServerDescription(const QJsonObject &server, const int index) const; + QString getServerDescription(const int index) const; bool isAmneziaDnsContainerInstalled(const int serverIndex) const; bool serverHasInstalledContainers(const int serverIndex) const; QJsonArray m_servers; + QVector> m_servers1; std::shared_ptr m_settings; From 65f60ab9221f8ef023d62e15b5b5db6343371864 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Thu, 26 Jun 2025 09:57:29 +0800 Subject: [PATCH 2/3] refactoring: replaced part of the code to work with new config classes --- client/core/controllers/coreController.cpp | 29 +- client/core/controllers/coreController.h | 18 +- .../models/protocols/awgProtocolConfig.cpp | 44 ++ .../core/models/protocols/awgProtocolConfig.h | 9 + .../core/models/protocols/protocolConfig.cpp | 65 ++- client/core/models/protocols/protocolConfig.h | 19 +- .../core/models/servers/apiV1ServerConfig.cpp | 2 - .../core/models/servers/apiV2ServerConfig.cpp | 24 +- .../core/models/servers/apiV2ServerConfig.h | 7 + client/core/models/servers/serverConfig.cpp | 22 + client/core/models/servers/serverConfig.h | 13 + client/ui/controllers/installController.cpp | 61 ++- client/ui/controllers/installController.h | 6 +- client/ui/models/containers_model.cpp | 21 +- client/ui/models/containers_model.h | 7 +- client/ui/models/protocols/awgConfigModel.cpp | 204 +++------ client/ui/models/protocols/awgConfigModel.h | 43 +- client/ui/models/protocols_model.cpp | 149 +++++-- client/ui/models/protocols_model.h | 46 +- client/ui/models/servers_model.cpp | 409 +++++++----------- client/ui/models/servers_model.h | 17 +- .../qml/Pages2/PageSettingsServerProtocol.qml | 17 +- 22 files changed, 637 insertions(+), 595 deletions(-) diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index a4dbc6d6..2a116a29 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -54,38 +54,43 @@ void CoreController::initModels() m_appSplitTunnelingModel.reset(new AppSplitTunnelingModel(m_settings, this)); m_engine->rootContext()->setContextProperty("AppSplitTunnelingModel", m_appSplitTunnelingModel.get()); - m_protocolsModel.reset(new ProtocolsModel(m_settings, this)); - m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get()); - - m_openVpnConfigModel.reset(new OpenVpnConfigModel(this)); + m_openVpnConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get()); - m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this)); + m_shadowSocksConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get()); - m_cloakConfigModel.reset(new CloakConfigModel(this)); + m_cloakConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get()); - m_wireGuardConfigModel.reset(new WireGuardConfigModel(this)); + m_wireGuardConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get()); - m_awgConfigModel.reset(new AwgConfigModel(this)); + m_awgConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get()); - m_xrayConfigModel.reset(new XrayConfigModel(this)); + m_xrayConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("XrayConfigModel", m_xrayConfigModel.get()); #ifdef Q_OS_WINDOWS - m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this)); + m_ikev2ConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get()); #endif - m_sftpConfigModel.reset(new SftpConfigModel(this)); + m_sftpConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get()); - m_socks5ConfigModel.reset(new Socks5ProxyConfigModel(this)); + m_socks5ConfigModel = QSharedPointer::create(this); m_engine->rootContext()->setContextProperty("Socks5ProxyConfigModel", m_socks5ConfigModel.get()); + m_protocolsModel.reset(new ProtocolsModel(m_openVpnConfigModel, m_shadowSocksConfigModel, m_cloakConfigModel, m_wireGuardConfigModel, + m_awgConfigModel, m_xrayConfigModel, +#ifdef Q_OS_WINDOWS + m_ikev2ConfigModel, +#endif + m_sftpConfigModel, m_socks5ConfigModel, this)); + m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get()); + m_clientManagementModel.reset(new ClientManagementModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get()); diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 9ae53562..a3b6616d 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -129,17 +129,17 @@ private: QSharedPointer m_apiAccountInfoModel; QSharedPointer m_apiDevicesModel; - QScopedPointer m_openVpnConfigModel; - QScopedPointer m_shadowSocksConfigModel; - QScopedPointer m_cloakConfigModel; - QScopedPointer m_xrayConfigModel; - QScopedPointer m_wireGuardConfigModel; - QScopedPointer m_awgConfigModel; + QSharedPointer m_openVpnConfigModel; + QSharedPointer m_shadowSocksConfigModel; + QSharedPointer m_cloakConfigModel; + QSharedPointer m_xrayConfigModel; + QSharedPointer m_wireGuardConfigModel; + QSharedPointer m_awgConfigModel; #ifdef Q_OS_WINDOWS - QScopedPointer m_ikev2ConfigModel; + QSharedPointer m_ikev2ConfigModel; #endif - QScopedPointer m_sftpConfigModel; - QScopedPointer m_socks5ConfigModel; + QSharedPointer m_sftpConfigModel; + QSharedPointer m_socks5ConfigModel; }; #endif // CORECONTROLLER_H diff --git a/client/core/models/protocols/awgProtocolConfig.cpp b/client/core/models/protocols/awgProtocolConfig.cpp index f77c0385..9e82cede 100644 --- a/client/core/models/protocols/awgProtocolConfig.cpp +++ b/client/core/models/protocols/awgProtocolConfig.cpp @@ -7,6 +7,10 @@ using namespace amnezia; +AwgProtocolConfig::AwgProtocolConfig(const QString &protocolName) : ProtocolConfig(protocolName) +{ +} + AwgProtocolConfig::AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) { serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); @@ -68,6 +72,12 @@ AwgProtocolConfig::AwgProtocolConfig(const QJsonObject &protocolConfigObject, co } } +AwgProtocolConfig::AwgProtocolConfig(const AwgProtocolConfig &other) : ProtocolConfig(other.protocolName) +{ + serverProtocolConfig = other.serverProtocolConfig; + clientProtocolConfig = other.clientProtocolConfig; +} + QJsonObject AwgProtocolConfig::toJson() const { QJsonObject json; @@ -196,3 +206,37 @@ QJsonObject AwgProtocolConfig::toJson() const return json; } + +bool AwgProtocolConfig::hasEqualServerSettings(const AwgProtocolConfig &other) const +{ + if (serverProtocolConfig.subnetAddress != other.serverProtocolConfig.subnetAddress + || serverProtocolConfig.port != other.serverProtocolConfig.port + || serverProtocolConfig.awgData.junkPacketCount != other.serverProtocolConfig.awgData.junkPacketCount + || serverProtocolConfig.awgData.junkPacketMinSize != other.serverProtocolConfig.awgData.junkPacketMinSize + || serverProtocolConfig.awgData.junkPacketMaxSize != other.serverProtocolConfig.awgData.junkPacketMaxSize + || serverProtocolConfig.awgData.initPacketJunkSize != other.serverProtocolConfig.awgData.initPacketJunkSize + || serverProtocolConfig.awgData.responsePacketJunkSize != other.serverProtocolConfig.awgData.responsePacketJunkSize + || serverProtocolConfig.awgData.initPacketMagicHeader != other.serverProtocolConfig.awgData.initPacketMagicHeader + || serverProtocolConfig.awgData.responsePacketMagicHeader != other.serverProtocolConfig.awgData.responsePacketMagicHeader + || serverProtocolConfig.awgData.underloadPacketMagicHeader != other.serverProtocolConfig.awgData.underloadPacketMagicHeader + || serverProtocolConfig.awgData.transportPacketMagicHeader != other.serverProtocolConfig.awgData.transportPacketMagicHeader) { + return false; + } + return true; +} + +bool AwgProtocolConfig::hasEqualClientSettings(const AwgProtocolConfig &other) const +{ + if (clientProtocolConfig.wireGuardData.mtu != other.clientProtocolConfig.wireGuardData.mtu + || clientProtocolConfig.awgData.junkPacketCount != other.clientProtocolConfig.awgData.junkPacketCount + || clientProtocolConfig.awgData.junkPacketMinSize != other.clientProtocolConfig.awgData.junkPacketMinSize + || clientProtocolConfig.awgData.junkPacketMaxSize != other.clientProtocolConfig.awgData.junkPacketMaxSize) { + return false; + } + return true; +} + +void AwgProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = awg::ClientProtocolConfig(); +} diff --git a/client/core/models/protocols/awgProtocolConfig.h b/client/core/models/protocols/awgProtocolConfig.h index 7c4fcf06..90ef9ba4 100644 --- a/client/core/models/protocols/awgProtocolConfig.h +++ b/client/core/models/protocols/awgProtocolConfig.h @@ -49,15 +49,24 @@ namespace awg QString nativeConfig; }; + + const int messageInitiationSize = 148; + const int messageResponseSize = 92; } class AwgProtocolConfig : public ProtocolConfig { public: + AwgProtocolConfig(const QString &protocolName); AwgProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName); + AwgProtocolConfig(const AwgProtocolConfig &other); QJsonObject toJson() const override; + bool hasEqualServerSettings(const AwgProtocolConfig &other) const; + bool hasEqualClientSettings(const AwgProtocolConfig &other) const; + void clearClientSettings(); + awg::ServerProtocolConfig serverProtocolConfig; awg::ClientProtocolConfig clientProtocolConfig; }; diff --git a/client/core/models/protocols/protocolConfig.cpp b/client/core/models/protocols/protocolConfig.cpp index 58b9387d..16e3ea9f 100644 --- a/client/core/models/protocols/protocolConfig.cpp +++ b/client/core/models/protocols/protocolConfig.cpp @@ -1,11 +1,74 @@ #include "protocolConfig.h" -#include +#include "core/models/protocols/awgProtocolConfig.h" +#include "core/models/protocols/cloakProtocolConfig.h" +#include "core/models/protocols/openvpnProtocolConfig.h" +#include "core/models/protocols/protocolConfig.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "core/models/protocols/xrayProtocolConfig.h" +#include "protocols/protocols_defs.h" + +using namespace amnezia; ProtocolConfig::ProtocolConfig(const QString &protocolName) : protocolName(protocolName) { } +ProtocolConfigVariant ProtocolConfig::getProtocolConfigVariant(const QSharedPointer &protocolConfig) +{ + ProtocolConfigVariant variant; + auto proto = ProtocolProps::protoFromString(protocolConfig->protocolName); + switch (proto) { + case Proto::OpenVpn: variant = qSharedPointerCast(protocolConfig); break; + case Proto::WireGuard: variant = qSharedPointerCast(protocolConfig); break; + case Proto::ShadowSocks: variant = qSharedPointerCast(protocolConfig); break; + case Proto::Cloak: variant = qSharedPointerCast(protocolConfig); break; + case Proto::Xray: variant = qSharedPointerCast(protocolConfig); break; + case Proto::Awg: variant = qSharedPointerCast(protocolConfig); break; + default: break; + } + return variant; +} + +bool ProtocolConfig::isServerSettingsEqual(const QSharedPointer &other) +{ + auto proto = ProtocolProps::protoFromString(protocolName); + + switch (proto) { + case Proto::OpenVpn: { + auto thisConfig = qSharedPointerCast(QSharedPointer(this)); + auto otherConfig = qSharedPointerCast(other); + return false; + } + case Proto::WireGuard: { + auto thisConfig = qSharedPointerCast(QSharedPointer(this)); + auto otherConfig = qSharedPointerCast(other); + return false; + } + case Proto::ShadowSocks: { + auto thisConfig = qSharedPointerCast(QSharedPointer(this)); + auto otherConfig = qSharedPointerCast(other); + return false; + } + case Proto::Cloak: { + auto thisConfig = qSharedPointerCast(QSharedPointer(this)); + auto otherConfig = qSharedPointerCast(other); + return false; + } + case Proto::Xray: { + auto thisConfig = qSharedPointerCast(QSharedPointer(this)); + auto otherConfig = qSharedPointerCast(other); + return false; + } + case Proto::Awg: { + auto thisConfig = qSharedPointerCast(QSharedPointer(this)); + auto otherConfig = qSharedPointerCast(other); + return thisConfig->hasEqualServerSettings(*otherConfig.data()); + } + default: return false; + } +} + QJsonObject ProtocolConfig::toJson() const { return QJsonObject(); diff --git a/client/core/models/protocols/protocolConfig.h b/client/core/models/protocols/protocolConfig.h index ce917002..899e6ec0 100644 --- a/client/core/models/protocols/protocolConfig.h +++ b/client/core/models/protocols/protocolConfig.h @@ -2,15 +2,30 @@ #define PROTOCOLCONFIG_H #include +#include +#include + +class OpenVpnProtocolConfig; +class WireGuardProtocolConfig; +class ShadowsocksProtocolConfig; +class CloakProtocolConfig; +class XrayProtocolConfig; +class AwgProtocolConfig; + +using ProtocolConfigVariant = + std::variant, QSharedPointer, QSharedPointer, + QSharedPointer, QSharedPointer, QSharedPointer >; class ProtocolConfig { public: ProtocolConfig(const QString &protocolName); + virtual QJsonObject toJson() const; + + static ProtocolConfigVariant getProtocolConfigVariant(const QSharedPointer &protocolConfig); + bool isServerSettingsEqual(const QSharedPointer &protocolConfig); QString protocolName; - - virtual QJsonObject toJson() const; }; #endif // PROTOCOLCONFIG_H diff --git a/client/core/models/servers/apiV1ServerConfig.cpp b/client/core/models/servers/apiV1ServerConfig.cpp index 363c1d9e..71fc4b7a 100644 --- a/client/core/models/servers/apiV1ServerConfig.cpp +++ b/client/core/models/servers/apiV1ServerConfig.cpp @@ -15,10 +15,8 @@ ApiV1ServerConfig::ApiV1ServerConfig(const QJsonObject &serverConfigObject) : Se QJsonObject ApiV1ServerConfig::toJson() const { - // Сначала вызываем родительскую функцию для сериализации базовых полей QJsonObject json = ServerConfig::toJson(); - // Добавляем свои поля только если они не пустые if (!name.isEmpty()) { json[config_key::name] = name; } diff --git a/client/core/models/servers/apiV2ServerConfig.cpp b/client/core/models/servers/apiV2ServerConfig.cpp index 97e27dcb..19eeb39d 100644 --- a/client/core/models/servers/apiV2ServerConfig.cpp +++ b/client/core/models/servers/apiV2ServerConfig.cpp @@ -38,14 +38,15 @@ ApiV2ServerConfig::ApiV2ServerConfig(const QJsonObject &serverConfigObject) : Se apiConfig.userCountryCode = apiConfigObject.value("user_country_code").toString(); apiConfig.vpnKey = apiConfigObject.value("vpn_key").toString(); + + auto authDataObject = serverConfigObject.value("auth_data").toObject(); + apiConfig.authData.apiKey = authDataObject.value("api_key").toString(); } QJsonObject ApiV2ServerConfig::toJson() const { - // Сначала вызываем родительскую функцию для сериализации базовых полей QJsonObject json = ServerConfig::toJson(); - // Добавляем свои поля только если они не пустые if (!name.isEmpty()) { json[config_key::name] = name; } @@ -53,10 +54,8 @@ QJsonObject ApiV2ServerConfig::toJson() const json[config_key::description] = description; } - // Сериализация API конфигурации QJsonObject apiConfigJson; - // Сериализация доступных стран только если массив не пустой if (!apiConfig.availableCountries.isEmpty()) { QJsonArray availableCountriesArray; for (const auto &country : apiConfig.availableCountries) { @@ -76,21 +75,18 @@ QJsonObject ApiV2ServerConfig::toJson() const } } - // Сериализация подписки только если есть данные if (!apiConfig.subscription.end_date.isEmpty()) { QJsonObject subscriptionObject; subscriptionObject["end_date"] = apiConfig.subscription.end_date; apiConfigJson["subscription"] = subscriptionObject; } - // Сериализация публичного ключа только если есть данные if (!apiConfig.publicKey.expiresAt.isEmpty()) { QJsonObject publicKeyObject; publicKeyObject["expires_at"] = apiConfig.publicKey.expiresAt; apiConfigJson["public_key"] = publicKeyObject; } - // Сериализация информации о сервере только если не пустая if (!apiConfig.serverCountryCode.isEmpty()) { apiConfigJson["server_country_code"] = apiConfig.serverCountryCode; } @@ -98,7 +94,6 @@ QJsonObject ApiV2ServerConfig::toJson() const apiConfigJson["server_country_name"] = apiConfig.serverCountryName; } - // Сериализация информации о сервисе только если не пустая if (!apiConfig.serviceProtocol.isEmpty()) { apiConfigJson["service_protocol"] = apiConfig.serviceProtocol; } @@ -106,17 +101,22 @@ QJsonObject ApiV2ServerConfig::toJson() const apiConfigJson["service_type"] = apiConfig.serviceType; } - // Сериализация информации о пользователе только если не пустая if (!apiConfig.userCountryCode.isEmpty()) { apiConfigJson["user_country_code"] = apiConfig.userCountryCode; } - // Сериализация VPN ключа только если не пустой if (!apiConfig.vpnKey.isEmpty()) { apiConfigJson["vpn_key"] = apiConfig.vpnKey; } - - // Добавляем API конфигурацию в основной JSON только если есть данные + + QJsonObject authDataJson; + if (!apiConfig.authData.apiKey.isEmpty()) { + authDataJson["api_key"] = apiConfig.authData.apiKey; + } + if (!authDataJson.isEmpty()) { + apiConfigJson["auth_data"] = authDataJson; + } + if (!apiConfigJson.isEmpty()) { json["api_config"] = apiConfigJson; } diff --git a/client/core/models/servers/apiV2ServerConfig.h b/client/core/models/servers/apiV2ServerConfig.h index 782e82ef..cb72c612 100644 --- a/client/core/models/servers/apiV2ServerConfig.h +++ b/client/core/models/servers/apiV2ServerConfig.h @@ -20,12 +20,19 @@ namespace apiv2 QString end_date; }; + struct AuthData + { + QString apiKey; + }; + struct ApiConfig { QVector availableCountries; Subscription subscription; PublicKey publicKey; + AuthData authData; + QString serverCountryCode; QString serverCountryName; diff --git a/client/core/models/servers/serverConfig.cpp b/client/core/models/servers/serverConfig.cpp index 977f8763..bf6f184b 100644 --- a/client/core/models/servers/serverConfig.cpp +++ b/client/core/models/servers/serverConfig.cpp @@ -27,6 +27,9 @@ ServerConfig::ServerConfig(const QJsonObject &serverConfigObject) defaultContainer = serverConfigObject.value(config_key::defaultContainer).toString(); + crc = serverConfigObject.value(config_key::crc).toInt(0); + nameOverriddenByUser = serverConfigObject.value(config_key::nameOverriddenByUser).toBool(false); + auto containers = serverConfigObject.value(config_key::containers).toArray(); for (const auto &container : std::as_const(containers)) { auto containerObject = container.toObject(); @@ -98,6 +101,17 @@ QSharedPointer ServerConfig::createServerConfig(const QJsonObject } } +ServerConfigVariant ServerConfig::getServerConfigVariant(const QSharedPointer &serverConfig) +{ + ServerConfigVariant variant; + switch (serverConfig->type) { + case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; + case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; + } + return variant; +} + QJsonObject ServerConfig::toJson() const { QJsonObject json; @@ -143,3 +157,11 @@ QJsonObject ServerConfig::toJson() const return json; } + +void ServerConfig::updateProtocolConfig(const QString &containerName, const QMap> &protocolConfigs) +{ + if (containerConfigs.contains(containerName)) { + ContainerConfig &containerConfig = containerConfigs[containerName]; + containerConfig.protocolConfigs = protocolConfigs; + } +} diff --git a/client/core/models/servers/serverConfig.h b/client/core/models/servers/serverConfig.h index 5559b507..6b0f6ff6 100644 --- a/client/core/models/servers/serverConfig.h +++ b/client/core/models/servers/serverConfig.h @@ -8,6 +8,13 @@ #include "core/defs.h" #include "core/models/containers/containerConfig.h" +class SelfHostedServerConfig; +class ApiV1ServerConfig; +class ApiV2ServerConfig; + +using ServerConfigVariant = + std::variant, QSharedPointer, QSharedPointer >; + class ServerConfig { public: @@ -16,6 +23,9 @@ public: virtual QJsonObject toJson() const; static QSharedPointer createServerConfig(const QJsonObject &serverConfigObject); + static ServerConfigVariant getServerConfigVariant(const QSharedPointer &serverConfig); + + void updateProtocolConfig(const QString &containerName, const QMap> &protocolConfigs); amnezia::ServerConfigType type; @@ -26,6 +36,9 @@ public: QString defaultContainer; + bool nameOverriddenByUser; + int crc; // TODO it makes sense to add for all server types or move it to the api + QMap containerConfigs; }; diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index eab8979a..80ef5090 100755 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -8,14 +8,15 @@ #include #include +#include "core/api/apiUtils.h" #include "core/controllers/serverController.h" #include "core/controllers/vpnConfigurationController.h" +#include "core/models/servers/selfHostedServerConfig.h" #include "core/networkUtilities.h" #include "logger.h" #include "ui/models/protocols/awgConfigModel.h" #include "ui/models/protocols/wireguardConfigModel.h" #include "utilities.h" -#include "core/api/apiUtils.h" namespace { @@ -552,28 +553,34 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia return ErrorCode::NoError; } -void InstallController::updateContainer(QJsonObject config) +void InstallController::updateContainer() { int serverIndex = m_serversModel->getProcessedServerIndex(); - ServerCredentials serverCredentials = - qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole)); + auto oldServerConfig = m_serversModel->getServerConfig(serverIndex); + auto newServerConfig = QSharedPointer::create(oldServerConfig); + + const DockerContainer container = static_cast(m_containersModel->getProcessedContainerIndex()); + const QString containerName = m_containersModel->getProcessedContainerName(); + auto protocolConfigs = m_protocolModel->getProtocolConfigs(); + newServerConfig->updateProtocolConfig(containerName, protocolConfigs); + + auto oldProtocolConfigs = oldServerConfig->containerConfigs[containerName].protocolConfigs; + auto newProtocolConfigs = newServerConfig->containerConfigs[containerName].protocolConfigs; - const DockerContainer container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - QJsonObject oldContainerConfig = m_containersModel->getContainerConfig(container); ErrorCode errorCode = ErrorCode::NoError; - if (isUpdateDockerContainerRequired(container, oldContainerConfig, config)) { + if (isUpdateDockerContainerRequired(container, oldProtocolConfigs, newProtocolConfigs)) { QSharedPointer serverController(new ServerController(m_settings)); connect(serverController.get(), &ServerController::serverIsBusy, this, &InstallController::serverIsBusy); connect(this, &InstallController::cancelInstallation, serverController.get(), &ServerController::cancelInstallation); - errorCode = serverController->updateContainer(serverCredentials, container, oldContainerConfig, config); + errorCode = serverController->updateContainer(newServerConfig->serverCredentials, container, oldContainerConfig, config); clearCachedProfile(serverController); } if (errorCode == ErrorCode::NoError) { - m_serversModel->updateContainerConfig(container, config); - m_protocolModel->updateModel(config); + m_serversModel->editServer(newServerConfig, serverIndex); + m_protocolModel->updateModel(protocolConfigs); auto defaultContainer = qvariant_cast(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole)); if ((serverIndex == m_serversModel->getDefaultServerIndex()) && (container == defaultContainer)) { @@ -607,7 +614,7 @@ void InstallController::removeProcessedServer() int serverIndex = m_serversModel->getProcessedServerIndex(); QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString(); - m_serversModel->removeServer(); + m_serversModel->removeProcessedServer(); emit removeProcessedServerFinished(tr("Server '%1' was removed").arg(serverName)); } @@ -913,29 +920,21 @@ bool InstallController::isConfigValid() return true; } -bool InstallController::isUpdateDockerContainerRequired(const DockerContainer container, const QJsonObject &oldConfig, - const QJsonObject &newConfig) +bool InstallController::isUpdateDockerContainerRequired(const DockerContainer container, + const QMap> &oldProtocolConfigs, + const QMap> &newProtocolConfigs) { Proto mainProto = ContainerProps::defaultProtocol(container); - const QJsonObject &oldProtoConfig = oldConfig.value(ProtocolProps::protoToString(mainProto)).toObject(); - const QJsonObject &newProtoConfig = newConfig.value(ProtocolProps::protoToString(mainProto)).toObject(); + const auto oldProtoConfig = oldProtocolConfigs.value(ProtocolProps::protoToString(mainProto)); + const auto newProtoConfig = newProtocolConfigs.value(ProtocolProps::protoToString(mainProto)); - if (container == DockerContainer::Awg) { - const AwgConfig oldConfig(oldProtoConfig); - const AwgConfig newConfig(newProtoConfig); - - if (oldConfig.hasEqualServerSettings(newConfig)) { - return false; - } - } else if (container == DockerContainer::WireGuard) { - const WgConfig oldConfig(oldProtoConfig); - const WgConfig newConfig(newProtoConfig); - - if (oldConfig.hasEqualServerSettings(newConfig)) { - return false; - } + switch (mainProto) { + case Proto::Awg: { + auto newConfig = qSharedPointerCast(oldProtoConfig); + auto oldConfig = qSharedPointerCast(newProtoConfig); + return !newConfig->hasEqualServerSettings(*oldConfig.data()); + } + default: return true; } - - return true; } diff --git a/client/ui/controllers/installController.h b/client/ui/controllers/installController.h index 8e42b5b2..c01c0646 100644 --- a/client/ui/controllers/installController.h +++ b/client/ui/controllers/installController.h @@ -28,7 +28,7 @@ public slots: void scanServerForInstalledContainers(); - void updateContainer(QJsonObject config); + void updateContainer(); void removeProcessedServer(); void rebootProcessedServer(); @@ -94,7 +94,9 @@ private: ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, const QSharedPointer &serverController, QMap &installedContainers); - bool isUpdateDockerContainerRequired(const DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig); + bool isUpdateDockerContainerRequired(const DockerContainer container, + const QMap> &oldProtocolConfigs, + const QMap> &newProtocolConfigs); QSharedPointer m_serversModel; QSharedPointer m_containersModel; diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 41d26bc7..817004ae 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -2,8 +2,7 @@ #include -ContainersModel::ContainersModel(QObject *parent) - : QAbstractListModel(parent) +ContainersModel::ContainersModel(QObject *parent) : QAbstractListModel(parent) { } @@ -37,7 +36,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const case EasySetupHeaderRole: return ContainerProps::easySetupHeader(container); case EasySetupDescriptionRole: return ContainerProps::easySetupDescription(container); case EasySetupOrderRole: return ContainerProps::easySetupOrder(container); - case IsInstalledRole: return m_containers.contains(container); + case IsInstalledRole: return m_containerConfigs.contains(ContainerProps::containerToString(container)); case IsCurrentlyProcessedRole: return container == static_cast(m_processedContainerIndex); case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container); case IsShareableRole: return ContainerProps::isShareable(container); @@ -53,14 +52,10 @@ QVariant ContainersModel::data(const int index, int role) const return data(modelIndex, role); } -void ContainersModel::updateModel(const QJsonArray &containers) +void ContainersModel::updateModel(const QMap &containerConfigs) { beginResetModel(); - m_containers.clear(); - for (const QJsonValue &val : containers) { - m_containers.insert(ContainerProps::containerFromString(val.toObject().value(config_key::container).toString()), - val.toObject()); - } + m_containerConfigs = containerConfigs; endResetModel(); } @@ -96,8 +91,8 @@ bool ContainersModel::isServiceContainer(const int containerIndex) bool ContainersModel::hasInstalledServices() { - for (const auto &container : m_containers.keys()) { - if (ContainerProps::containerService(container) == ServiceType::Other) { + for (const auto &containerName : m_containerConfigs.keys()) { + if (ContainerProps::containerService(ContainerProps::containerFromString(containerName)) == ServiceType::Other) { return true; } } @@ -106,8 +101,8 @@ bool ContainersModel::hasInstalledServices() bool ContainersModel::hasInstalledProtocols() { - for (const auto &container : m_containers.keys()) { - if (ContainerProps::containerService(container) == ServiceType::Vpn) { + for (const auto &containerName : m_containerConfigs.keys()) { + if (ContainerProps::containerService(ContainerProps::containerFromString(containerName)) == ServiceType::Vpn) { return true; } } diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 3bd0ddc1..9d1407a1 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -3,10 +3,9 @@ #include #include -#include -#include #include "containers/containers_defs.h" +#include "core/models/containers/containerConfig.h" class ContainersModel : public QAbstractListModel { @@ -42,7 +41,7 @@ public: QVariant data(const int index, int role) const; public slots: - void updateModel(const QJsonArray &containers); + void updateModel(const QMap &containerConfigs); void setProcessedContainerIndex(int containerIndex); int getProcessedContainerIndex(); @@ -64,7 +63,7 @@ signals: void containersModelUpdated(); private: - QMap m_containers; + QMap m_containerConfigs; int m_processedContainerIndex; }; diff --git a/client/ui/models/protocols/awgConfigModel.cpp b/client/ui/models/protocols/awgConfigModel.cpp index 860c8395..08c8338f 100644 --- a/client/ui/models/protocols/awgConfigModel.cpp +++ b/client/ui/models/protocols/awgConfigModel.cpp @@ -4,7 +4,10 @@ #include "protocols/protocols_defs.h" -AwgConfigModel::AwgConfigModel(QObject *parent) : QAbstractListModel(parent) +AwgConfigModel::AwgConfigModel(QObject *parent) + : QAbstractListModel(parent), + m_newAwgProtocolConfig(ProtocolProps::protoToString(Proto::Awg)), + m_oldAwgProtocolConfig(ProtocolProps::protoToString(Proto::Awg)) { } @@ -21,30 +24,42 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in } switch (role) { - case Roles::SubnetAddressRole: m_serverProtocolConfig.insert(config_key::subnet_address, value.toString()); break; - case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break; + case Roles::SubnetAddressRole: m_newAwgProtocolConfig.serverProtocolConfig.subnetAddress = value.toString(); break; + case Roles::PortRole: m_newAwgProtocolConfig.serverProtocolConfig.port = value.toString(); break; - case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break; - case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break; - case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break; - case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break; - - case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break; - case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break; - case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break; - case Roles::ServerInitPacketJunkSizeRole: m_serverProtocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break; - case Roles::ServerResponsePacketJunkSizeRole: - m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString()); + case Roles::ClientMtuRole: m_newAwgProtocolConfig.clientProtocolConfig.wireGuardData.mtu = value.toString(); break; + case Roles::ClientJunkPacketCountRole: m_newAwgProtocolConfig.clientProtocolConfig.awgData.junkPacketCount = value.toString(); break; + case Roles::ClientJunkPacketMinSizeRole: + m_newAwgProtocolConfig.clientProtocolConfig.awgData.junkPacketMinSize = value.toString(); + break; + case Roles::ClientJunkPacketMaxSizeRole: + m_newAwgProtocolConfig.clientProtocolConfig.awgData.junkPacketMaxSize = value.toString(); + break; + + case Roles::ServerJunkPacketCountRole: m_newAwgProtocolConfig.serverProtocolConfig.awgData.junkPacketCount = value.toString(); break; + case Roles::ServerJunkPacketMinSizeRole: + m_newAwgProtocolConfig.serverProtocolConfig.awgData.junkPacketMinSize = value.toString(); + break; + case Roles::ServerJunkPacketMaxSizeRole: + m_newAwgProtocolConfig.serverProtocolConfig.awgData.junkPacketMaxSize = value.toString(); + break; + case Roles::ServerInitPacketJunkSizeRole: + m_newAwgProtocolConfig.serverProtocolConfig.awgData.initPacketJunkSize = value.toString(); + break; + case Roles::ServerResponsePacketJunkSizeRole: + m_newAwgProtocolConfig.serverProtocolConfig.awgData.responsePacketJunkSize = value.toString(); + break; + case Roles::ServerInitPacketMagicHeaderRole: + m_newAwgProtocolConfig.serverProtocolConfig.awgData.initPacketMagicHeader = value.toString(); break; - case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break; case Roles::ServerResponsePacketMagicHeaderRole: - m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); + m_newAwgProtocolConfig.serverProtocolConfig.awgData.responsePacketMagicHeader = value.toString(); break; case Roles::ServerUnderloadPacketMagicHeaderRole: - m_serverProtocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); + m_newAwgProtocolConfig.serverProtocolConfig.awgData.underloadPacketMagicHeader = value.toString(); break; case Roles::ServerTransportPacketMagicHeaderRole: - m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); + m_newAwgProtocolConfig.serverProtocolConfig.awgData.transportPacketMagicHeader = value.toString(); break; } @@ -59,94 +74,42 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::SubnetAddressRole: return m_serverProtocolConfig.value(config_key::subnet_address).toString(); - case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString(); + case Roles::SubnetAddressRole: return m_newAwgProtocolConfig.serverProtocolConfig.subnetAddress; + case Roles::PortRole: return m_newAwgProtocolConfig.serverProtocolConfig.port; - case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu); - case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount); - case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize); - case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize); + case Roles::ClientMtuRole: return m_newAwgProtocolConfig.clientProtocolConfig.wireGuardData.mtu; + case Roles::ClientJunkPacketCountRole: return m_newAwgProtocolConfig.clientProtocolConfig.awgData.junkPacketCount; + case Roles::ClientJunkPacketMinSizeRole: return m_newAwgProtocolConfig.clientProtocolConfig.awgData.junkPacketMinSize; + case Roles::ClientJunkPacketMaxSizeRole: return m_newAwgProtocolConfig.clientProtocolConfig.awgData.junkPacketMaxSize; - case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount); - case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize); - case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize); - case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize); - case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize); - case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader); - case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader); - case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader); - case Roles::ServerTransportPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::transportPacketMagicHeader); + case Roles::ServerJunkPacketCountRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.junkPacketCount; + case Roles::ServerJunkPacketMinSizeRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.junkPacketMinSize; + case Roles::ServerJunkPacketMaxSizeRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.junkPacketMaxSize; + case Roles::ServerInitPacketJunkSizeRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.initPacketJunkSize; + case Roles::ServerResponsePacketJunkSizeRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.responsePacketJunkSize; + case Roles::ServerInitPacketMagicHeaderRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.initPacketMagicHeader; + case Roles::ServerResponsePacketMagicHeaderRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.responsePacketMagicHeader; + case Roles::ServerUnderloadPacketMagicHeaderRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.underloadPacketMagicHeader; + case Roles::ServerTransportPacketMagicHeaderRole: return m_newAwgProtocolConfig.serverProtocolConfig.awgData.transportPacketMagicHeader; } return QVariant(); } -void AwgConfigModel::updateModel(const QJsonObject &config) +void AwgConfigModel::updateModel(const AwgProtocolConfig awgProtocolConfig) { beginResetModel(); - m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - - m_fullConfig = config; - - QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject(); - - auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg); - m_serverProtocolConfig.insert(config_key::transport_proto, - serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config); - m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); - m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); - m_serverProtocolConfig[config_key::junkPacketCount] = - serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); - m_serverProtocolConfig[config_key::junkPacketMinSize] = - serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); - m_serverProtocolConfig[config_key::junkPacketMaxSize] = - serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); - m_serverProtocolConfig[config_key::initPacketJunkSize] = - serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); - m_serverProtocolConfig[config_key::responsePacketJunkSize] = - serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); - m_serverProtocolConfig[config_key::initPacketMagicHeader] = - serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); - m_serverProtocolConfig[config_key::responsePacketMagicHeader] = - serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); - m_serverProtocolConfig[config_key::underloadPacketMagicHeader] = - serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); - m_serverProtocolConfig[config_key::transportPacketMagicHeader] = - serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); - - auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu); - m_clientProtocolConfig[config_key::junkPacketCount] = - clientProtocolConfig.value(config_key::junkPacketCount).toString(m_serverProtocolConfig[config_key::junkPacketCount].toString()); - m_clientProtocolConfig[config_key::junkPacketMinSize] = - clientProtocolConfig.value(config_key::junkPacketMinSize).toString(m_serverProtocolConfig[config_key::junkPacketMinSize].toString()); - m_clientProtocolConfig[config_key::junkPacketMaxSize] = - clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(m_serverProtocolConfig[config_key::junkPacketMaxSize].toString()); + m_newAwgProtocolConfig = awgProtocolConfig; + m_oldAwgProtocolConfig = awgProtocolConfig; endResetModel(); } -QJsonObject AwgConfigModel::getConfig() +QSharedPointer AwgConfigModel::getConfig() { - const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); - const AwgConfig newConfig(m_serverProtocolConfig); - - if (!oldConfig.hasEqualServerSettings(newConfig)) { - m_serverProtocolConfig.remove(config_key::last_config); - } else { - auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu]; - jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount]; - jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize]; - jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize]; - - m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); + if (m_oldAwgProtocolConfig.hasEqualServerSettings(m_newAwgProtocolConfig)) { + m_newAwgProtocolConfig.clearClientSettings(); } - - m_fullConfig.insert(config_key::awg, m_serverProtocolConfig); - return m_fullConfig; + return QSharedPointer::create(m_newAwgProtocolConfig); } bool AwgConfigModel::isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4) @@ -156,15 +119,12 @@ bool AwgConfigModel::isHeadersEqual(const QString &h1, const QString &h2, const bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2) { - return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2); + return (awg::messageInitiationSize + s1 == awg::messageResponseSize + s2); } bool AwgConfigModel::isServerSettingsEqual() { - const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); - const AwgConfig newConfig(m_serverProtocolConfig); - - return oldConfig.hasEqualServerSettings(newConfig); + return m_oldAwgProtocolConfig.hasEqualServerSettings(m_newAwgProtocolConfig); } QHash AwgConfigModel::roleNames() const @@ -191,53 +151,3 @@ QHash AwgConfigModel::roleNames() const return roles; } - -AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig) -{ - auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu); - clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); - clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); - clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); - - subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); - port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); - serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); - serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); - serverJunkPacketMaxSize = serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); - serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); - serverResponsePacketJunkSize = - serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); - serverInitPacketMagicHeader = - serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); - serverResponsePacketMagicHeader = - serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); - serverUnderloadPacketMagicHeader = - serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); - serverTransportPacketMagicHeader = - serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); -} - -bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const -{ - if (subnetAddress != other.subnetAddress || port != other.port || serverJunkPacketCount != other.serverJunkPacketCount - || serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize - || serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize - || serverInitPacketMagicHeader != other.serverInitPacketMagicHeader - || serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader - || serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader - || serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) { - return false; - } - return true; -} - -bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const -{ - if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount - || clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) { - return false; - } - return true; -} diff --git a/client/ui/models/protocols/awgConfigModel.h b/client/ui/models/protocols/awgConfigModel.h index c1f8bb27..26363c61 100644 --- a/client/ui/models/protocols/awgConfigModel.h +++ b/client/ui/models/protocols/awgConfigModel.h @@ -5,38 +5,7 @@ #include #include "containers/containers_defs.h" - -namespace AwgConstant { - const int messageInitiationSize = 148; - const int messageResponseSize = 92; -} - -struct AwgConfig -{ - AwgConfig(const QJsonObject &jsonConfig); - - QString subnetAddress; - QString port; - - QString clientMtu; - QString clientJunkPacketCount; - QString clientJunkPacketMinSize; - QString clientJunkPacketMaxSize; - - QString serverJunkPacketCount; - QString serverJunkPacketMinSize; - QString serverJunkPacketMaxSize; - QString serverInitPacketJunkSize; - QString serverResponsePacketJunkSize; - QString serverInitPacketMagicHeader; - QString serverResponsePacketMagicHeader; - QString serverUnderloadPacketMagicHeader; - QString serverTransportPacketMagicHeader; - - bool hasEqualServerSettings(const AwgConfig &other) const; - bool hasEqualClientSettings(const AwgConfig &other) const; - -}; +#include "core/models/protocols/awgProtocolConfig.h" class AwgConfigModel : public QAbstractListModel { @@ -71,8 +40,8 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &config); - QJsonObject getConfig(); + void updateModel(const AwgProtocolConfig awgProtocolConfig); + QSharedPointer getConfig(); bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4); bool isPacketSizeEqual(const int s1, const int s2); @@ -83,10 +52,8 @@ protected: QHash roleNames() const override; private: - DockerContainer m_container; - QJsonObject m_serverProtocolConfig; - QJsonObject m_clientProtocolConfig; - QJsonObject m_fullConfig; + AwgProtocolConfig m_newAwgProtocolConfig; + AwgProtocolConfig m_oldAwgProtocolConfig; }; #endif // AWGCONFIGMODEL_H diff --git a/client/ui/models/protocols_model.cpp b/client/ui/models/protocols_model.cpp index 019b2d2f..6a996ec0 100644 --- a/client/ui/models/protocols_model.cpp +++ b/client/ui/models/protocols_model.cpp @@ -1,14 +1,41 @@ #include "protocols_model.h" -ProtocolsModel::ProtocolsModel(std::shared_ptr settings, QObject *parent) - : m_settings(settings), QAbstractListModel(parent) +#include "core/models/protocols/awgProtocolConfig.h" +#include "core/models/protocols/cloakProtocolConfig.h" +#include "core/models/protocols/openvpnProtocolConfig.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "core/models/protocols/wireguardProtocolConfig.h" +#include "core/models/protocols/xrayProtocolConfig.h" + +ProtocolsModel::ProtocolsModel(QObject *parent) : QAbstractListModel(parent) +{ +} + +ProtocolsModel::ProtocolsModel(const QSharedPointer &openVpnConfigModel, + const QSharedPointer &shadowSocksConfigModel, + const QSharedPointer &cloakConfigModel, + const QSharedPointer &wireGuardConfigModel, + const QSharedPointer &awgConfigModel, const QSharedPointer &xrayConfigModel, + const QSharedPointer &ikev2ConfigModel, + const QSharedPointer &sftpConfigModel, + const QSharedPointer &socks5ProxyConfigModel, QObject *parent) + : QAbstractListModel(parent), + m_openVpnConfigModel(openVpnConfigModel), + m_shadowSocksConfigModel(shadowSocksConfigModel), + m_cloakConfigModel(cloakConfigModel), + m_wireGuardConfigModel(wireGuardConfigModel), + m_awgConfigModel(awgConfigModel), + m_xrayConfigModel(xrayConfigModel), + m_ikev2ConfigModel(ikev2ConfigModel), + m_sftpConfigModel(sftpConfigModel), + m_socks5ProxyConfigModel(socks5ProxyConfigModel) { } int ProtocolsModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return m_content.size(); + return m_protocolConfigs.size(); } QHash ProtocolsModel::roleNames() const @@ -27,60 +54,102 @@ QHash ProtocolsModel::roleNames() const QVariant ProtocolsModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() < 0 || index.row() >= m_content.size()) { + if (!index.isValid() || index.row() < 0 || index.row() >= m_protocolConfigs.size()) { return QVariant(); } + auto protocolConfig = m_protocolConfigs.at(index.row()); + amnezia::Proto protocol = ProtocolProps::protoFromString(protocolConfig->protocolName); + switch (role) { case ProtocolNameRole: { - amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row())); - return ProtocolProps::protocolHumanNames().value(proto); + return ProtocolProps::protocolHumanNames().value(protocol); } - case ServerProtocolPageRole: - return static_cast(serverProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row())))); - case ClientProtocolPageRole: - return static_cast(clientProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row())))); - case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row())); - case RawConfigRole: { - auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject(); - auto lastConfigJsonDoc = - QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8()); - auto lastConfigJson = lastConfigJsonDoc.object(); + case ServerProtocolPageRole: return static_cast(serverProtocolPage(protocol)); + case ClientProtocolPageRole: return static_cast(clientProtocolPage(protocol)); + case ProtocolIndexRole: return protocol; + // case RawConfigRole: { + // auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject(); + // auto lastConfigJsonDoc = QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8()); + // auto lastConfigJson = lastConfigJsonDoc.object(); - QString rawConfig; - QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n"); - for (const QString &l : lines) { - rawConfig.append(l + "\n"); - } - return rawConfig; - } + // QString rawConfig; + // QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n"); + // for (const QString &l : lines) { + // rawConfig.append(l + "\n"); + // } + // return rawConfig; + // } case IsClientProtocolExistsRole: { - auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject(); - auto lastConfigJsonDoc = - QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8()); - auto lastConfigJson = lastConfigJsonDoc.object(); - - auto configString = lastConfigJson.value(config_key::config).toString(); - return !configString.isEmpty(); + auto protocolVariant = ProtocolConfig::getProtocolConfigVariant(protocolConfig); + return std::visit([](const auto &ptr) -> bool { return ptr->clientProtocolConfig.isEmpty; }, protocolVariant); } } return QVariant(); } -void ProtocolsModel::updateModel(const QJsonObject &content) +void ProtocolsModel::updateModel(const QMap> &protocolConfigs) { - m_container = ContainerProps::containerFromString(content.value(config_key::container).toString()); - - m_content = content; - m_content.remove(config_key::container); + beginResetModel(); + m_protocolConfigs.clear(); + for (const auto &protocolConfig : protocolConfigs) { + m_protocolConfigs.push_back(protocolConfig); + } + endResetModel(); } -QJsonObject ProtocolsModel::getConfig() +void ProtocolsModel::updateProtocolModel(amnezia::Proto protocol) { - QJsonObject config = m_content; - config.insert(config_key::container, ContainerProps::containerToString(m_container)); - return config; + QSharedPointer protocolConfig; + + for (const auto &config : m_protocolConfigs) { + if (ProtocolProps::protoFromString(config->protocolName) == protocol) { + protocolConfig = config; + break; + } + } + + switch (protocol) { + case Proto::OpenVpn: m_openVpnConfigModel->updateModel(config); break; + case Proto::ShadowSocks: m_shadowSocksConfigModel->updateModel(config); break; + case Proto::Cloak: m_cloakConfigModel->updateModel(config); break; + case Proto::WireGuard: m_wireGuardConfigModel->updateModel(config); break; + case Proto::Awg: m_awgConfigModel->updateModel(config); break; + case Proto::Xray: m_xrayConfigModel->updateModel(config); break; +#ifdef Q_OS_WINDOWS + case Proto::Ikev2: + case Proto::L2tp: m_ikev2ConfigModel->updateModel(config); break; +#endif + case Proto::Sftp: m_sftpConfigModel->updateModel(config); break; + case Proto::Socks5Proxy: m_socks5ProxyConfigModel->updateModel(config); break; + default: break; + } +} + +QMap> ProtocolsModel::getProtocolConfigs() +{ + QMap> protocolConfigs; + + for (const auto &config : m_protocolConfigs) { + switch (ProtocolProps::protoFromString(config->protocolName)) { + case Proto::OpenVpn: protocolConfigs.insert(config->protocolName, m_openVpnConfigModel->getConfig()); break; + case Proto::ShadowSocks: m_shadowSocksConfigModel->updateModel(config); break; + case Proto::Cloak: m_cloakConfigModel->updateModel(config); break; + case Proto::WireGuard: m_wireGuardConfigModel->updateModel(config); break; + case Proto::Awg: protocolConfigs.insert(config->protocolName, m_awgConfigModel->getConfig()); break; + case Proto::Xray: m_xrayConfigModel->updateModel(config); break; +#ifdef Q_OS_WINDOWS + case Proto::Ikev2: + case Proto::L2tp: m_ikev2ConfigModel->updateModel(config); break; +#endif + case Proto::Sftp: m_sftpConfigModel->updateModel(config); break; + case Proto::Socks5Proxy: m_socks5ProxyConfigModel->updateModel(config); break; + default: break; + } + } + + return protocolConfigs; } PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const @@ -94,7 +163,7 @@ PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const case Proto::Ikev2: return PageLoader::PageEnum::PageProtocolIKev2Settings; case Proto::L2tp: return PageLoader::PageEnum::PageProtocolIKev2Settings; case Proto::Xray: return PageLoader::PageEnum::PageProtocolXraySettings; - + // non-vpn case Proto::TorWebSite: return PageLoader::PageEnum::PageServiceTorWebsiteSettings; case Proto::Dns: return PageLoader::PageEnum::PageServiceDnsSettings; diff --git a/client/ui/models/protocols_model.h b/client/ui/models/protocols_model.h index 5c52ee86..64599962 100644 --- a/client/ui/models/protocols_model.h +++ b/client/ui/models/protocols_model.h @@ -4,8 +4,19 @@ #include #include -#include "../controllers/pageController.h" -#include "settings.h" +#include "core/models/protocols/protocolConfig.h" +#include "ui/controllers/pageController.h" +#include "ui/models/protocols/awgConfigModel.h" +#include "ui/models/protocols/cloakConfigModel.h" +#include "ui/models/protocols/openvpnConfigModel.h" +#include "ui/models/protocols/shadowsocksConfigModel.h" +#include "ui/models/protocols/wireguardConfigModel.h" +#include "ui/models/protocols/xrayConfigModel.h" +#ifdef Q_OS_WINDOWS + #include "ui/models/protocols/ikev2ConfigModel.h" +#endif +#include "ui/models/services/sftpConfigModel.h" +#include "ui/models/services/socks5ProxyConfigModel.h" class ProtocolsModel : public QAbstractListModel { @@ -20,16 +31,26 @@ public: IsClientProtocolExistsRole }; - ProtocolsModel(std::shared_ptr settings, QObject *parent = nullptr); + ProtocolsModel(QObject *parent = nullptr); + ProtocolsModel(const QSharedPointer &openVpnConfigModel, + const QSharedPointer &shadowSocksConfigModel, + const QSharedPointer &cloakConfigModel, const QSharedPointer &wireGuardConfigModel, + const QSharedPointer &awgConfigModel, const QSharedPointer &xrayConfigModel, +#ifdef Q_OS_WINDOWS + const QSharedPointer &ikev2ConfigModel, +#endif + const QSharedPointer &sftpConfigModel, + const QSharedPointer &socks5ProxyConfigModel, QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &content); + void updateModel(const QMap> &protocolConfigs); + void updateProtocolModel(amnezia::Proto protocol); - QJsonObject getConfig(); + QMap> getProtocolConfigs(); protected: QHash roleNames() const override; @@ -38,10 +59,19 @@ private: PageLoader::PageEnum serverProtocolPage(Proto protocol) const; PageLoader::PageEnum clientProtocolPage(Proto protocol) const; - std::shared_ptr m_settings; + QVector> m_protocolConfigs; - DockerContainer m_container; - QJsonObject m_content; + QSharedPointer m_openVpnConfigModel; + QSharedPointer m_shadowSocksConfigModel; + QSharedPointer m_cloakConfigModel; + QSharedPointer m_wireGuardConfigModel; + QSharedPointer m_awgConfigModel; + QSharedPointer m_xrayConfigModel; +#ifdef Q_OS_WINDOWS + QSharedPointer m_ikev2ConfigModel; +#endif + QSharedPointer m_sftpConfigModel; + QSharedPointer m_socks5ProxyConfigModel; }; #endif // PROTOCOLS_MODEL_H diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index f76fea89..986ade8a 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -5,6 +5,7 @@ #include "core/models/servers/apiV1ServerConfig.h" #include "core/models/servers/apiV2ServerConfig.h" #include "core/models/servers/selfHostedServerConfig.h" +#include "core/models/servers/serverConfig.h" #include "core/networkUtilities.h" #ifdef Q_OS_IOS @@ -27,9 +28,6 @@ namespace constexpr char publicKeyInfo[] = "public_key"; constexpr char expiresAt[] = "expires_at"; } - - using ServerConfigVariant = - std::variant, QSharedPointer, QSharedPointer >; } ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent) @@ -39,8 +37,7 @@ ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged); connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) { - auto defaultContainer = - ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString()); + auto defaultContainer = ContainerProps::containerFromString(m_servers1.at(serverIndex)->defaultContainer); emit ServersModel::defaultServerDefaultContainerChanged(defaultContainer); emit ServersModel::defaultServerNameChanged(); updateDefaultServerContainersModel(); @@ -53,28 +50,25 @@ ServersModel::ServersModel(std::shared_ptr settings, QObject *parent) int ServersModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return static_cast(m_servers.size()); + return static_cast(m_servers1.size()); } bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers.size())) { + if (!index.isValid() || index.row() < 0 || index.row() >= static_cast(m_servers1.size())) { return false; } - QJsonObject server = m_servers.at(index.row()).toObject(); - const auto configVersion = server.value(config_key::configVersion).toInt(); + QSharedPointer serverConfig = m_servers1.at(index.row()); + ServerConfigVariant variant = ServerConfig::getServerConfigVariant(serverConfig); switch (role) { case NameRole: { - if (configVersion) { - server.insert(config_key::name, value.toString()); - } else { - server.insert(config_key::description, value.toString()); - } - server.insert(config_key::nameOverriddenByUser, true); - m_settings->editServer(index.row(), server); - m_servers.replace(index.row(), server); + std::visit([&value](const auto &ptr) -> void { ptr->name = value.toString(); }, variant); + serverConfig->nameOverriddenByUser = true; + + m_settings->editServer(index.row(), serverConfig->toJson()); + m_servers1.replace(index.row(), serverConfig); if (index.row() == m_defaultServerIndex) { emit defaultServerNameChanged(); } @@ -102,12 +96,7 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const } QSharedPointer serverConfig = m_servers1.at(index.row()); - ServerConfigVariant variant; - switch (serverConfig->type) { - case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; - case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; - case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; - } + ServerConfigVariant variant = ServerConfig::getServerConfigVariant(serverConfig); switch (role) { case NameRole: { @@ -163,26 +152,13 @@ QVariant ServersModel::data(const int index, int role) const void ServersModel::resetModel() { beginResetModel(); - m_servers = m_settings->serversArray(); + auto servers = m_settings->serversArray(); m_defaultServerIndex = m_settings->defaultServerIndex(); m_processedServerIndex = m_defaultServerIndex; - for (auto server : m_servers) { + for (auto server : servers) { auto serverConfig = ServerConfig::createServerConfig(server.toObject()); m_servers1.push_back(serverConfig); - qDebug() << "333"; - qDebug() << server.toObject(); - qDebug() << "333"; - - ServerConfigVariant variant; - switch (serverConfig->type) { - case amnezia::ServerConfigType::SelfHosted: variant = qSharedPointerCast(serverConfig); break; - case amnezia::ServerConfigType::ApiV1: variant = qSharedPointerCast(serverConfig); break; - case amnezia::ServerConfigType::ApiV2: variant = qSharedPointerCast(serverConfig); break; - } - qDebug() << "123"; - qDebug() << std::visit([](const auto &ptr) -> QJsonObject { return ptr->toJson(); }, variant); - qDebug() << "123"; } endResetModel(); @@ -237,33 +213,33 @@ QString ServersModel::getServerDescription(const int index) const const QString ServersModel::getDefaultServerDescriptionCollapsed() { - const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); - const auto configVersion = server.value(config_key::configVersion).toInt(); + auto serverConfig = m_servers1.at(m_defaultServerIndex); auto description = getServerDescription(m_defaultServerIndex); - if (configVersion) { + auto containerName = ContainerProps::containerFromString(serverConfig->defaultContainer); + + if (serverConfig->type != ServerConfigType::SelfHosted) { return description; } - auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); - - return description += ContainerProps::containerHumanNames().value(container) + " | " + server.value(config_key::hostName).toString(); + return description += ContainerProps::containerHumanNames().value(containerName) + " | " + serverConfig->hostName; } const QString ServersModel::getDefaultServerDescriptionExpanded() { - const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); - const auto configVersion = server.value(config_key::configVersion).toInt(); + auto serverConfig = m_servers1.at(m_defaultServerIndex); auto description = getServerDescription(m_defaultServerIndex); - if (configVersion) { + auto containerName = ContainerProps::containerFromString(serverConfig->defaultContainer); + + if (serverConfig->type != ServerConfigType::SelfHosted) { return description; } - return description += server.value(config_key::hostName).toString(); + return description += serverConfig->hostName; } const int ServersModel::getServersCount() { - return m_servers.count(); + return m_servers1.count(); } bool ServersModel::hasServerWithWriteAccess() @@ -325,18 +301,22 @@ bool ServersModel::isDefaultServerHasWriteAccess() return qvariant_cast(data(m_defaultServerIndex, HasWriteAccessRole)); } -void ServersModel::addServer(const QJsonObject &server) +void ServersModel::addServer(const QSharedPointer &serverConfig) { beginResetModel(); - m_settings->addServer(server); - m_servers = m_settings->serversArray(); + m_settings->addServer(serverConfig->toJson()); + auto servers = m_settings->serversArray(); + for (auto server : servers) { + auto serverConfig = ServerConfig::createServerConfig(server.toObject()); + m_servers1.push_back(serverConfig); + } endResetModel(); } -void ServersModel::editServer(const QJsonObject &server, const int serverIndex) +void ServersModel::editServer(const QSharedPointer &serverConfig, const int serverIndex) { - m_settings->editServer(serverIndex, server); - m_servers.replace(serverIndex, m_settings->serversArray().at(serverIndex)); + m_settings->editServer(serverIndex, serverConfig->toJson()); + m_servers1[serverIndex] = serverConfig; emit dataChanged(index(serverIndex, 0), index(serverIndex, 0)); if (serverIndex == m_defaultServerIndex) { @@ -350,30 +330,20 @@ void ServersModel::editServer(const QJsonObject &server, const int serverIndex) } } -void ServersModel::removeServer() +void ServersModel::removeProcessedServer() { - beginResetModel(); - m_settings->removeServer(m_processedServerIndex); - m_servers = m_settings->serversArray(); - - if (m_settings->defaultServerIndex() == m_processedServerIndex) { - setDefaultServerIndex(0); - } else if (m_settings->defaultServerIndex() > m_processedServerIndex) { - setDefaultServerIndex(m_settings->defaultServerIndex() - 1); - } - - if (m_settings->serversCount() == 0) { - setDefaultServerIndex(-1); - } - setProcessedServerIndex(m_defaultServerIndex); - endResetModel(); + removeServer(m_processedServerIndex); } void ServersModel::removeServer(const int serverIndex) { beginResetModel(); m_settings->removeServer(serverIndex); - m_servers = m_settings->serversArray(); + auto servers = m_settings->serversArray(); + for (auto server : servers) { + auto serverConfig = ServerConfig::createServerConfig(server.toObject()); + m_servers1.push_back(serverConfig); + } if (m_settings->defaultServerIndex() == serverIndex) { setDefaultServerIndex(0); @@ -429,84 +399,27 @@ ServerCredentials ServersModel::serverCredentials(int index) const void ServersModel::updateContainersModel() { - auto containers = m_servers.at(m_processedServerIndex).toObject().value(config_key::containers).toArray(); - emit containersUpdated(containers); + auto containerConfigs = m_servers1.at(m_processedServerIndex)->containerConfigs; + emit containersUpdated(containerConfigs); } void ServersModel::updateDefaultServerContainersModel() { - auto containers = m_servers.at(m_defaultServerIndex).toObject().value(config_key::containers).toArray(); - emit defaultServerContainersUpdated(containers); + auto containerConfigs = m_servers1.at(m_defaultServerIndex)->containerConfigs; + emit defaultServerContainersUpdated(containerConfigs); } -QJsonObject ServersModel::getServerConfig(const int serverIndex) +QSharedPointer ServersModel::getServerConfig(const int serverIndex) { - return m_servers.at(serverIndex).toObject(); -} - -void ServersModel::reloadDefaultServerContainerConfig() -{ - QJsonObject server = m_servers.at(m_defaultServerIndex).toObject(); - auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); - - auto containers = server.value(config_key::containers).toArray(); - - auto config = m_settings->containerConfig(m_defaultServerIndex, container); - for (auto i = 0; i < containers.size(); i++) { - auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString()); - if (c == container) { - containers.replace(i, config); - break; - } - } - - server.insert(config_key::containers, containers); - editServer(server, m_defaultServerIndex); -} - -void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config) -{ - auto container = static_cast(containerIndex); - QJsonObject server = m_servers.at(m_processedServerIndex).toObject(); - - auto containers = server.value(config_key::containers).toArray(); - for (auto i = 0; i < containers.size(); i++) { - auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString()); - if (c == container) { - containers.replace(i, config); - break; - } - } - - server.insert(config_key::containers, containers); - editServer(server, m_processedServerIndex); -} - -void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config) -{ - auto container = static_cast(containerIndex); - QJsonObject server = m_servers.at(m_processedServerIndex).toObject(); - - auto containers = server.value(config_key::containers).toArray(); - containers.push_back(config); - - server.insert(config_key::containers, containers); - - auto defaultContainer = server.value(config_key::defaultContainer).toString(); - if (ContainerProps::containerFromString(defaultContainer) == DockerContainer::None - && ContainerProps::containerService(container) != ServiceType::Other && ContainerProps::isSupportedByCurrentPlatform(container)) { - server.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); - } - - editServer(server, m_processedServerIndex); + return m_servers1.at(serverIndex); } void ServersModel::setDefaultContainer(const int serverIndex, const int containerIndex) { auto container = static_cast(containerIndex); - QJsonObject s = m_servers.at(serverIndex).toObject(); - s.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); - editServer(s, serverIndex); // check + auto serverConfig = m_servers1.at(serverIndex); + serverConfig->defaultContainer = ContainerProps::containerToString(container); + editServer(serverConfig, serverIndex); } const QString ServersModel::getDefaultServerDefaultContainerName() @@ -517,25 +430,19 @@ const QString ServersModel::getDefaultServerDefaultContainerName() ErrorCode ServersModel::removeAllContainers(const QSharedPointer &serverController) { - ErrorCode errorCode = serverController->removeAllContainers(m_settings->serverCredentials(m_processedServerIndex)); if (errorCode == ErrorCode::NoError) { - QJsonObject s = m_servers.at(m_processedServerIndex).toObject(); - s.insert(config_key::containers, {}); - s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); - - editServer(s, m_processedServerIndex); + auto serverConfig = m_servers1.at(m_processedServerIndex); + serverConfig->containerConfigs.clear(); + editServer(serverConfig, m_processedServerIndex); } return errorCode; } ErrorCode ServersModel::rebootServer(const QSharedPointer &serverController) { - - auto credentials = m_settings->serverCredentials(m_processedServerIndex); - - ErrorCode errorCode = serverController->rebootServer(credentials); + ErrorCode errorCode = serverController->rebootServer(m_settings->serverCredentials(m_processedServerIndex)); return errorCode; } @@ -548,30 +455,19 @@ ErrorCode ServersModel::removeContainer(const QSharedPointer & ErrorCode errorCode = serverController->removeContainer(credentials, dockerContainer); if (errorCode == ErrorCode::NoError) { - QJsonObject server = m_servers.at(m_processedServerIndex).toObject(); + auto serverConfig = m_servers1.at(m_processedServerIndex); + serverConfig->containerConfigs.remove(ContainerProps::containerToString(dockerContainer)); - auto containers = server.value(config_key::containers).toArray(); - for (auto it = containers.begin(); it != containers.end(); it++) { - if (it->toObject().value(config_key::container).toString() == ContainerProps::containerToString(dockerContainer)) { - containers.erase(it); - break; - } - } - - server.insert(config_key::containers, containers); - - auto defaultContainer = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + auto defaultContainer = ContainerProps::containerFromString(serverConfig->defaultContainer); if (defaultContainer == containerIndex) { - if (containers.empty()) { - defaultContainer = DockerContainer::None; + if (serverConfig->containerConfigs.empty()) { + serverConfig->defaultContainer = ContainerProps::containerToString(DockerContainer::None); } else { - defaultContainer = - ContainerProps::containerFromString(containers.begin()->toObject().value(config_key::container).toString()); + serverConfig->defaultContainer = serverConfig->containerConfigs.begin()->containerName; } - server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer)); } - editServer(server, m_processedServerIndex); + editServer(serverConfig, m_processedServerIndex); } return errorCode; } @@ -579,7 +475,9 @@ ErrorCode ServersModel::removeContainer(const QSharedPointer & void ServersModel::clearCachedProfile(const DockerContainer container) { m_settings->clearLastConnectionConfig(m_processedServerIndex, container); - m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex)); + auto serverConfig = ServerConfig::createServerConfig(m_settings->server(m_processedServerIndex)); + + m_servers1.replace(m_processedServerIndex, serverConfig); if (m_processedServerIndex == m_defaultServerIndex) { updateDefaultServerContainersModel(); } @@ -588,10 +486,9 @@ void ServersModel::clearCachedProfile(const DockerContainer container) bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex) const { - QJsonObject server = m_servers.at(serverIndex).toObject(); - auto containers = server.value(config_key::containers).toArray(); - for (auto it = containers.begin(); it != containers.end(); it++) { - if (it->toObject().value(config_key::container).toString() == ContainerProps::containerToString(DockerContainer::Dns)) { + auto serverConfig = m_servers1.at(serverIndex); + for (const auto &container : serverConfig->containerConfigs) { + if (container.containerName == ContainerProps::containerToString(DockerContainer::Dns)) { return true; } } @@ -602,17 +499,16 @@ QPair ServersModel::getDnsPair(int serverIndex) { QPair dns; - const QJsonObject &server = m_servers.at(m_processedServerIndex).toObject(); - const auto containers = server.value(config_key::containers).toArray(); + auto serverConfig = m_servers1.at(serverIndex); bool isDnsContainerInstalled = false; - for (const QJsonValue &container : containers) { - if (ContainerProps::containerFromString(container.toObject().value(config_key::container).toString()) == DockerContainer::Dns) { + for (const auto &container : serverConfig->containerConfigs) { + if (container.containerName == ContainerProps::containerToString(DockerContainer::Dns)) { isDnsContainerInstalled = true; } } - dns.first = server.value(config_key::dns1).toString(); - dns.second = server.value(config_key::dns2).toString(); + dns.first = serverConfig->dns1; + dns.second = serverConfig->dns2; if (dns.first.isEmpty() || !NetworkUtilities::checkIPv4Format(dns.first)) { if (m_isAmneziaDnsEnabled && isDnsContainerInstalled) { @@ -631,18 +527,17 @@ QPair ServersModel::getDnsPair(int serverIndex) QStringList ServersModel::getAllInstalledServicesName(const int serverIndex) { QStringList servicesName; - QJsonObject server = m_servers.at(serverIndex).toObject(); - const auto containers = server.value(config_key::containers).toArray(); - for (auto it = containers.begin(); it != containers.end(); it++) { - auto container = ContainerProps::containerFromString(it->toObject().value(config_key::container).toString()); - if (ContainerProps::containerService(container) == ServiceType::Other) { - if (container == DockerContainer::Dns) { + auto serverConfig = m_servers1.at(serverIndex); + for (const auto &container : serverConfig->containerConfigs) { + auto containerType = ContainerProps::containerFromString(container.containerName); + if (ContainerProps::containerService(containerType) == ServiceType::Other) { + if (containerType == DockerContainer::Dns) { servicesName.append("DNS"); - } else if (container == DockerContainer::Sftp) { + } else if (containerType == DockerContainer::Sftp) { servicesName.append("SFTP"); - } else if (container == DockerContainer::TorWebSite) { + } else if (containerType == DockerContainer::TorWebSite) { servicesName.append("TOR"); - } else if (container == DockerContainer::Socks5Proxy) { + } else if (containerType == DockerContainer::Socks5Proxy) { servicesName.append("SOCKS5"); } } @@ -659,8 +554,8 @@ void ServersModel::toggleAmneziaDns(bool enabled) bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc) { - for (const auto &server : std::as_const(m_servers)) { - if (static_cast(server.toObject().value(config_key::crc).toInt()) == crc) { + for (const auto &server : std::as_const(m_servers1)) { + if (static_cast(server->crc) == crc) { return true; } } @@ -669,11 +564,10 @@ bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc) bool ServersModel::isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType, const QString &serviceProtocol) { - for (const auto &server : std::as_const(m_servers)) { - const auto apiConfig = server.toObject().value(configKey::apiConfig).toObject(); - if (apiConfig.value(configKey::userCountryCode).toString() == userCountryCode - && apiConfig.value(configKey::serviceType).toString() == serviceType - && apiConfig.value(configKey::serviceProtocol).toString() == serviceProtocol) { + for (const auto &serverConfig : std::as_const(m_servers1)) { + const auto apiV2ServerConfig = qSharedPointerCast(serverConfig); + if (apiV2ServerConfig->apiConfig.userCountryCode == userCountryCode && apiV2ServerConfig->apiConfig.serviceType == serviceType + && apiV2ServerConfig->apiConfig.serviceProtocol == serviceProtocol) { return true; } } @@ -734,27 +628,46 @@ bool ServersModel::setProcessedServerData(const QString &roleString, const QVari bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling() { - auto server = m_servers.at(m_defaultServerIndex).toObject(); - auto defaultContainer = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString()); + auto serverConfig = m_servers1.at(m_defaultServerIndex); + auto defaultContainer = ContainerProps::containerFromString(serverConfig->defaultContainer); - auto containers = server.value(config_key::containers).toArray(); - for (auto i = 0; i < containers.size(); i++) { - auto container = containers.at(i).toObject(); - if (container.value(config_key::container).toString() != ContainerProps::containerToString(defaultContainer)) { + for (const auto &container : serverConfig->containerConfigs) { + if (container.containerName != serverConfig->defaultContainer) { continue; } if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) { - QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToString(defaultContainer)).toObject(); - QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject clientProtocolConfig = QJsonDocument::fromJson(clientProtocolConfigString.toUtf8()).object(); - return (clientProtocolConfigString.contains("AllowedIPs") && !clientProtocolConfigString.contains("AllowedIPs = 0.0.0.0/0, ::/0")) - || (!clientProtocolConfig.value(config_key::allowed_ips).toArray().isEmpty() - && !clientProtocolConfig.value(config_key::allowed_ips).toArray().contains("0.0.0.0/0")); + auto protocolConfigVariant = ProtocolConfig::getProtocolConfigVariant(container.protocolConfigs[serverConfig->defaultContainer]); + return std::visit( + [](const auto &ptr) -> bool { + if constexpr (requires { + ptr->clientProtocolConfig; + ptr->clientProtocolConfig.wireGuardData; + }) { + const auto nativeConfig = ptr->clientProtocolConfig.nativeConfig; + const auto allowedIps = ptr->clientProtocolConfig.wireGuardData.allowedIps; + + return (nativeConfig.contains("AllowedIPs") && !nativeConfig.contains("AllowedIPs = 0.0.0.0/0, ::/0")) + || (!allowedIps.isEmpty() && !allowedIps.contains("0.0.0.0/0")); + } else { + return false; + } + }, + protocolConfigVariant); } else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn || defaultContainer == DockerContainer::ShadowSocks) { - auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)).toObject(); - QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString(); - return !clientProtocolConfigString.isEmpty() && !clientProtocolConfigString.contains("redirect-gateway"); + auto protocolConfigVariant = ProtocolConfig::getProtocolConfigVariant( + container.protocolConfigs[ContainerProps::containerTypeToString(DockerContainer::OpenVpn)]); + return std::visit( + [](const auto &ptr) -> bool { + if constexpr (requires { ptr->clientProtocolConfig; }) { + const auto nativeConfig = ptr->clientProtocolConfig.nativeConfig; + + return (!nativeConfig.isEmpty() && !nativeConfig.contains("redirect-gateway")); + } else { + return false; + } + }, + protocolConfigVariant); } } return false; @@ -767,62 +680,62 @@ bool ServersModel::isServerFromApi(const int serverIndex) bool ServersModel::isApiKeyExpired(const int serverIndex) { - auto serverConfig = m_servers.at(serverIndex).toObject(); - auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); + // auto serverConfig = m_servers1.at(serverIndex); + // auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); - auto publicKeyInfo = apiConfig.value(configKey::publicKeyInfo).toObject(); - const QString expiresAt = publicKeyInfo.value(configKey::expiresAt).toString(); - if (expiresAt.isEmpty()) { - publicKeyInfo.insert(configKey::expiresAt, QDateTime::currentDateTimeUtc().addDays(1).toString(Qt::ISODate)); - apiConfig.insert(configKey::publicKeyInfo, publicKeyInfo); - serverConfig.insert(configKey::apiConfig, apiConfig); - editServer(serverConfig, serverIndex); + // auto publicKeyInfo = apiConfig.value(configKey::publicKeyInfo).toObject(); + // const QString expiresAt = publicKeyInfo.value(configKey::expiresAt).toString(); + // if (expiresAt.isEmpty()) { + // publicKeyInfo.insert(configKey::expiresAt, QDateTime::currentDateTimeUtc().addDays(1).toString(Qt::ISODate)); + // apiConfig.insert(configKey::publicKeyInfo, publicKeyInfo); + // serverConfig.insert(configKey::apiConfig, apiConfig); + // editServer(serverConfig, serverIndex); - return false; - } + // return false; + // } - auto expiresAtDateTime = QDateTime::fromString(expiresAt, Qt::ISODate).toUTC(); - if (expiresAtDateTime < QDateTime::currentDateTimeUtc()) { - return true; - } - return false; + // auto expiresAtDateTime = QDateTime::fromString(expiresAt, Qt::ISODate).toUTC(); + // if (expiresAtDateTime < QDateTime::currentDateTimeUtc()) { + // return true; + // } + // return false; } void ServersModel::removeApiConfig(const int serverIndex) { - auto serverConfig = getServerConfig(serverIndex); +// auto serverConfig = m_servers1.at(serverIndex); -#ifdef Q_OS_IOS - QString vpncName = QString("%1 (%2) %3") - .arg(serverConfig[config_key::description].toString()) - .arg(serverConfig[config_key::hostName].toString()) - .arg(serverConfig[config_key::vpnproto].toString()); +// #ifdef Q_OS_IOS +// QString vpncName = QString("%1 (%2) %3") +// .arg(serverConfig[config_key::description].toString()) +// .arg(serverConfig[config_key::hostName].toString()) +// .arg(serverConfig[config_key::vpnproto].toString()); - AmneziaVPN::removeVPNC(vpncName.toStdString()); -#endif +// AmneziaVPN::removeVPNC(vpncName.toStdString()); +// #endif - serverConfig.remove(config_key::dns1); - serverConfig.remove(config_key::dns2); - serverConfig.remove(config_key::containers); - serverConfig.remove(config_key::hostName); +// serverConfig.remove(config_key::dns1); +// serverConfig.remove(config_key::dns2); +// serverConfig.remove(config_key::containers); +// serverConfig.remove(config_key::hostName); - auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); - apiConfig.remove(configKey::publicKeyInfo); - serverConfig.insert(configKey::apiConfig, apiConfig); +// auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); +// apiConfig.remove(configKey::publicKeyInfo); +// serverConfig.insert(configKey::apiConfig, apiConfig); - serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); +// serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); - editServer(serverConfig, serverIndex); +// editServer(serverConfig, serverIndex); } const QString ServersModel::getDefaultServerImagePathCollapsed() { - const auto server = m_servers.at(m_defaultServerIndex).toObject(); - const auto apiConfig = server.value(configKey::apiConfig).toObject(); - const auto countryCode = apiConfig.value(configKey::serverCountryCode).toString(); + // const auto server = m_servers.at(m_defaultServerIndex).toObject(); + // const auto apiConfig = server.value(configKey::apiConfig).toObject(); + // const auto countryCode = apiConfig.value(configKey::serverCountryCode).toString(); - if (countryCode.isEmpty()) { - return ""; - } - return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(countryCode.toUpper()); + // if (countryCode.isEmpty()) { + // return ""; + // } + // return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(countryCode.toUpper()); } diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index f0649e7d..447b720e 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -86,16 +86,12 @@ public slots: const ServerCredentials getProcessedServerCredentials(); const ServerCredentials getServerCredentials(const int index); - void addServer(const QJsonObject &server); - void editServer(const QJsonObject &server, const int serverIndex); - void removeServer(); + void addServer(const QSharedPointer &serverConfig); + void editServer(const QSharedPointer &serverConfig, const int serverIndex); + void removeProcessedServer(); void removeServer(const int serverIndex); - QJsonObject getServerConfig(const int serverIndex); - - void reloadDefaultServerContainerConfig(); - void updateContainerConfig(const int containerIndex, const QJsonObject config); - void addContainerConfig(const int containerIndex, const QJsonObject config); + QSharedPointer getServerConfig(const int serverIndex); void clearCachedProfile(const DockerContainer container); @@ -136,8 +132,8 @@ signals: void defaultServerNameChanged(); void defaultServerDescriptionChanged(); - void containersUpdated(const QJsonArray &containers); - void defaultServerContainersUpdated(const QJsonArray &containers); + void containersUpdated(const QMap &containerConfigs); + void defaultServerContainersUpdated(const QMap &containerConfigs); void defaultServerDefaultContainerChanged(const int containerIndex); void updateApiCountryModel(); @@ -155,7 +151,6 @@ private: bool serverHasInstalledContainers(const int serverIndex) const; - QJsonArray m_servers; QVector> m_servers1; std::shared_ptr m_settings; diff --git a/client/ui/qml/Pages2/PageSettingsServerProtocol.qml b/client/ui/qml/Pages2/PageSettingsServerProtocol.qml index fce9b2a3..706ab091 100644 --- a/client/ui/qml/Pages2/PageSettingsServerProtocol.qml +++ b/client/ui/qml/Pages2/PageSettingsServerProtocol.qml @@ -101,10 +101,7 @@ PageType { clickedFunction: function() { if (isClientProtocolExists) { - switch (protocolIndex) { - case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Awg: AwgConfigModel.updateModel(ProtocolsModel.getConfig()); break; - } + ProtocolsModel.updateProtocolModel(protocolIndex) PageController.goToPage(clientProtocolPage); } else { PageController.showNotificationMessage(qsTr("Click the \"connect\" button to create a connection configuration")) @@ -132,17 +129,7 @@ PageType { visible: delegateContent.isServerSettingsVisible clickedFunction: function() { - switch (protocolIndex) { - case ProtocolEnum.OpenVpn: OpenVpnConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.ShadowSocks: ShadowSocksConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Cloak: CloakConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Awg: AwgConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Xray: XrayConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Sftp: SftpConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break; - case ProtocolEnum.Socks5Proxy: Socks5ProxyConfigModel.updateModel(ProtocolsModel.getConfig()); break; - } + ProtocolsModel.updateProtocolModel(protocolIndex) PageController.goToPage(serverProtocolPage); } From d766a001e3eb8d20f9bb4ce644b9c7534aae5373 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Thu, 3 Jul 2025 10:20:01 +0800 Subject: [PATCH 3/3] refactoring: all protocol models now work with c++ classes --- .../models/protocols/cloakProtocolConfig.cpp | 15 +++ .../models/protocols/cloakProtocolConfig.h | 3 + .../protocols/openvpnProtocolConfig.cpp | 47 +++++--- .../models/protocols/openvpnProtocolConfig.h | 9 +- .../core/models/protocols/protocolConfig.cpp | 11 +- .../protocols/shadowsocksProtocolConfig.cpp | 14 +++ .../protocols/shadowsocksProtocolConfig.h | 3 + .../protocols/wireguardProtocolConfig.cpp | 14 +++ .../protocols/wireguardProtocolConfig.h | 3 + .../models/protocols/xrayProtocolConfig.cpp | 15 +++ .../models/protocols/xrayProtocolConfig.h | 3 + client/ui/controllers/installController.cpp | 7 +- client/ui/models/containers_model.cpp | 12 -- client/ui/models/containers_model.h | 3 - .../ui/models/protocols/cloakConfigModel.cpp | 46 ++++---- client/ui/models/protocols/cloakConfigModel.h | 12 +- .../models/protocols/openvpnConfigModel.cpp | 107 +++++++----------- .../ui/models/protocols/openvpnConfigModel.h | 12 +- .../protocols/shadowsocksConfigModel.cpp | 46 ++++---- .../models/protocols/shadowsocksConfigModel.h | 12 +- .../models/protocols/wireguardConfigModel.cpp | 88 +++----------- .../models/protocols/wireguardConfigModel.h | 24 +--- .../ui/models/protocols/xrayConfigModel.cpp | 42 +++---- client/ui/models/protocols/xrayConfigModel.h | 12 +- client/ui/models/protocols_model.cpp | 36 +++--- 25 files changed, 301 insertions(+), 295 deletions(-) diff --git a/client/core/models/protocols/cloakProtocolConfig.cpp b/client/core/models/protocols/cloakProtocolConfig.cpp index b32e652e..c5dd916a 100644 --- a/client/core/models/protocols/cloakProtocolConfig.cpp +++ b/client/core/models/protocols/cloakProtocolConfig.cpp @@ -40,4 +40,19 @@ QJsonObject CloakProtocolConfig::toJson() const } return json; +} + +bool CloakProtocolConfig::hasEqualServerSettings(const CloakProtocolConfig &other) const +{ + if (serverProtocolConfig.port != other.serverProtocolConfig.port || + serverProtocolConfig.cipher != other.serverProtocolConfig.cipher || + serverProtocolConfig.site != other.serverProtocolConfig.site) { + return false; + } + return true; +} + +void CloakProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = cloak::ClientProtocolConfig(); } diff --git a/client/core/models/protocols/cloakProtocolConfig.h b/client/core/models/protocols/cloakProtocolConfig.h index 191e3f2d..f82dc34e 100644 --- a/client/core/models/protocols/cloakProtocolConfig.h +++ b/client/core/models/protocols/cloakProtocolConfig.h @@ -28,6 +28,9 @@ public: QJsonObject toJson() const override; + bool hasEqualServerSettings(const CloakProtocolConfig &other) const; + void clearClientSettings(); + cloak::ServerProtocolConfig serverProtocolConfig; cloak::ClientProtocolConfig clientProtocolConfig; }; diff --git a/client/core/models/protocols/openvpnProtocolConfig.cpp b/client/core/models/protocols/openvpnProtocolConfig.cpp index cf994566..4b4c8e85 100644 --- a/client/core/models/protocols/openvpnProtocolConfig.cpp +++ b/client/core/models/protocols/openvpnProtocolConfig.cpp @@ -1,20 +1,22 @@ #include "openvpnProtocolConfig.h" -#include #include "protocols/protocols_defs.h" +#include using namespace amnezia; -OpenVpnProtocolConfig::OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) : ProtocolConfig(protocolName) +OpenVpnProtocolConfig::OpenVpnProtocolConfig(const QJsonObject &protocolConfigObject, const QString &protocolName) + : ProtocolConfig(protocolName) { serverProtocolConfig.subnetAddress = protocolConfigObject.value(config_key::subnet_address).toString(); serverProtocolConfig.transportProto = protocolConfigObject.value(config_key::transport_proto).toString(); serverProtocolConfig.port = protocolConfigObject.value(config_key::port).toString(); - serverProtocolConfig.ncpDisable = protocolConfigObject.value(config_key::ncp_disable).toString(); + serverProtocolConfig.ncpDisable = protocolConfigObject.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable); serverProtocolConfig.hash = protocolConfigObject.value(config_key::hash).toString(); serverProtocolConfig.cipher = protocolConfigObject.value(config_key::cipher).toString(); - serverProtocolConfig.tlsAuth = protocolConfigObject.value(config_key::tls_auth).toString(); - serverProtocolConfig.blockOutsideDns = protocolConfigObject.value(config_key::block_outside_dns).toString(); + serverProtocolConfig.tlsAuth = protocolConfigObject.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth); + serverProtocolConfig.blockOutsideDns = + protocolConfigObject.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns); serverProtocolConfig.additionalClientConfig = protocolConfigObject.value(config_key::additional_client_config).toString(); serverProtocolConfig.additionalServerConfig = protocolConfigObject.value(config_key::additional_server_config).toString(); @@ -42,21 +44,15 @@ QJsonObject OpenVpnProtocolConfig::toJson() const if (!serverProtocolConfig.port.isEmpty()) { json[config_key::port] = serverProtocolConfig.port; } - if (!serverProtocolConfig.ncpDisable.isEmpty()) { - json[config_key::ncp_disable] = serverProtocolConfig.ncpDisable; - } + json[config_key::ncp_disable] = serverProtocolConfig.ncpDisable; if (!serverProtocolConfig.hash.isEmpty()) { json[config_key::hash] = serverProtocolConfig.hash; } if (!serverProtocolConfig.cipher.isEmpty()) { json[config_key::cipher] = serverProtocolConfig.cipher; } - if (!serverProtocolConfig.tlsAuth.isEmpty()) { - json[config_key::tls_auth] = serverProtocolConfig.tlsAuth; - } - if (!serverProtocolConfig.blockOutsideDns.isEmpty()) { - json[config_key::block_outside_dns] = serverProtocolConfig.blockOutsideDns; - } + json[config_key::tls_auth] = serverProtocolConfig.tlsAuth; + json[config_key::block_outside_dns] = serverProtocolConfig.blockOutsideDns; if (!serverProtocolConfig.additionalClientConfig.isEmpty()) { json[config_key::additional_client_config] = serverProtocolConfig.additionalClientConfig; } @@ -80,4 +76,25 @@ QJsonObject OpenVpnProtocolConfig::toJson() const } return json; -} +} + +bool OpenVpnProtocolConfig::hasEqualServerSettings(const OpenVpnProtocolConfig &other) const +{ + if (serverProtocolConfig.subnetAddress != other.serverProtocolConfig.subnetAddress + || serverProtocolConfig.transportProto != other.serverProtocolConfig.transportProto + || serverProtocolConfig.port != other.serverProtocolConfig.port + || serverProtocolConfig.ncpDisable != other.serverProtocolConfig.ncpDisable + || serverProtocolConfig.hash != other.serverProtocolConfig.hash || serverProtocolConfig.cipher != other.serverProtocolConfig.cipher + || serverProtocolConfig.tlsAuth != other.serverProtocolConfig.tlsAuth + || serverProtocolConfig.blockOutsideDns != other.serverProtocolConfig.blockOutsideDns + || serverProtocolConfig.additionalClientConfig != other.serverProtocolConfig.additionalClientConfig + || serverProtocolConfig.additionalServerConfig != other.serverProtocolConfig.additionalServerConfig) { + return false; + } + return true; +} + +void OpenVpnProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = openvpn::ClientProtocolConfig(); +} diff --git a/client/core/models/protocols/openvpnProtocolConfig.h b/client/core/models/protocols/openvpnProtocolConfig.h index 0e6d4e6a..89d44754 100644 --- a/client/core/models/protocols/openvpnProtocolConfig.h +++ b/client/core/models/protocols/openvpnProtocolConfig.h @@ -13,11 +13,11 @@ namespace openvpn QString subnetAddress; QString transportProto; QString port; - QString ncpDisable; + bool ncpDisable; QString hash; QString cipher; - QString tlsAuth; - QString blockOutsideDns; + bool tlsAuth; + bool blockOutsideDns; QString additionalClientConfig; QString additionalServerConfig; }; @@ -39,6 +39,9 @@ public: QJsonObject toJson() const override; + bool hasEqualServerSettings(const OpenVpnProtocolConfig &other) const; + void clearClientSettings(); + openvpn::ServerProtocolConfig serverProtocolConfig; openvpn::ClientProtocolConfig clientProtocolConfig; }; diff --git a/client/core/models/protocols/protocolConfig.cpp b/client/core/models/protocols/protocolConfig.cpp index 16e3ea9f..eb96c936 100644 --- a/client/core/models/protocols/protocolConfig.cpp +++ b/client/core/models/protocols/protocolConfig.cpp @@ -5,6 +5,7 @@ #include "core/models/protocols/openvpnProtocolConfig.h" #include "core/models/protocols/protocolConfig.h" #include "core/models/protocols/shadowsocksProtocolConfig.h" +#include "core/models/protocols/wireguardProtocolConfig.h" #include "core/models/protocols/xrayProtocolConfig.h" #include "protocols/protocols_defs.h" @@ -38,27 +39,27 @@ bool ProtocolConfig::isServerSettingsEqual(const QSharedPointer case Proto::OpenVpn: { auto thisConfig = qSharedPointerCast(QSharedPointer(this)); auto otherConfig = qSharedPointerCast(other); - return false; + return thisConfig->hasEqualServerSettings(*otherConfig.data()); } case Proto::WireGuard: { auto thisConfig = qSharedPointerCast(QSharedPointer(this)); auto otherConfig = qSharedPointerCast(other); - return false; + return thisConfig->hasEqualServerSettings(*otherConfig.data()); } case Proto::ShadowSocks: { auto thisConfig = qSharedPointerCast(QSharedPointer(this)); auto otherConfig = qSharedPointerCast(other); - return false; + return thisConfig->hasEqualServerSettings(*otherConfig.data()); } case Proto::Cloak: { auto thisConfig = qSharedPointerCast(QSharedPointer(this)); auto otherConfig = qSharedPointerCast(other); - return false; + return thisConfig->hasEqualServerSettings(*otherConfig.data()); } case Proto::Xray: { auto thisConfig = qSharedPointerCast(QSharedPointer(this)); auto otherConfig = qSharedPointerCast(other); - return false; + return thisConfig->hasEqualServerSettings(*otherConfig.data()); } case Proto::Awg: { auto thisConfig = qSharedPointerCast(QSharedPointer(this)); diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.cpp b/client/core/models/protocols/shadowsocksProtocolConfig.cpp index e5f9b978..30539a9b 100644 --- a/client/core/models/protocols/shadowsocksProtocolConfig.cpp +++ b/client/core/models/protocols/shadowsocksProtocolConfig.cpp @@ -36,4 +36,18 @@ QJsonObject ShadowsocksProtocolConfig::toJson() const } return json; +} + +bool ShadowsocksProtocolConfig::hasEqualServerSettings(const ShadowsocksProtocolConfig &other) const +{ + if (serverProtocolConfig.port != other.serverProtocolConfig.port || + serverProtocolConfig.cipher != other.serverProtocolConfig.cipher) { + return false; + } + return true; +} + +void ShadowsocksProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = shadowsocks::ClientProtocolConfig(); } diff --git a/client/core/models/protocols/shadowsocksProtocolConfig.h b/client/core/models/protocols/shadowsocksProtocolConfig.h index 3c615f8a..1b7480f8 100644 --- a/client/core/models/protocols/shadowsocksProtocolConfig.h +++ b/client/core/models/protocols/shadowsocksProtocolConfig.h @@ -27,6 +27,9 @@ public: QJsonObject toJson() const override; + bool hasEqualServerSettings(const ShadowsocksProtocolConfig &other) const; + void clearClientSettings(); + shadowsocks::ServerProtocolConfig serverProtocolConfig; shadowsocks::ClientProtocolConfig clientProtocolConfig; }; diff --git a/client/core/models/protocols/wireguardProtocolConfig.cpp b/client/core/models/protocols/wireguardProtocolConfig.cpp index 602cbce5..c44173d2 100644 --- a/client/core/models/protocols/wireguardProtocolConfig.cpp +++ b/client/core/models/protocols/wireguardProtocolConfig.cpp @@ -118,3 +118,17 @@ QJsonObject WireGuardProtocolConfig::toJson() const return json; } + +bool WireGuardProtocolConfig::hasEqualServerSettings(const WireGuardProtocolConfig &other) const +{ + if (serverProtocolConfig.subnetAddress != other.serverProtocolConfig.subnetAddress || + serverProtocolConfig.port != other.serverProtocolConfig.port) { + return false; + } + return true; +} + +void WireGuardProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = wireguard::ClientProtocolConfig(); +} diff --git a/client/core/models/protocols/wireguardProtocolConfig.h b/client/core/models/protocols/wireguardProtocolConfig.h index acefafe2..7d3f6620 100644 --- a/client/core/models/protocols/wireguardProtocolConfig.h +++ b/client/core/models/protocols/wireguardProtocolConfig.h @@ -51,6 +51,9 @@ public: QJsonObject toJson() const override; + bool hasEqualServerSettings(const WireGuardProtocolConfig &other) const; + void clearClientSettings(); + wireguard::ServerProtocolConfig serverProtocolConfig; wireguard::ClientProtocolConfig clientProtocolConfig; }; diff --git a/client/core/models/protocols/xrayProtocolConfig.cpp b/client/core/models/protocols/xrayProtocolConfig.cpp index 32ad108a..00127031 100644 --- a/client/core/models/protocols/xrayProtocolConfig.cpp +++ b/client/core/models/protocols/xrayProtocolConfig.cpp @@ -40,4 +40,19 @@ QJsonObject XrayProtocolConfig::toJson() const } return json; +} + +bool XrayProtocolConfig::hasEqualServerSettings(const XrayProtocolConfig &other) const +{ + if (serverProtocolConfig.site != other.serverProtocolConfig.site || + serverProtocolConfig.port != other.serverProtocolConfig.port || + serverProtocolConfig.transportProto != other.serverProtocolConfig.transportProto) { + return false; + } + return true; +} + +void XrayProtocolConfig::clearClientSettings() +{ + clientProtocolConfig = xray::ClientProtocolConfig(); } diff --git a/client/core/models/protocols/xrayProtocolConfig.h b/client/core/models/protocols/xrayProtocolConfig.h index 87023954..941816fe 100644 --- a/client/core/models/protocols/xrayProtocolConfig.h +++ b/client/core/models/protocols/xrayProtocolConfig.h @@ -28,6 +28,9 @@ public: QJsonObject toJson() const override; + bool hasEqualServerSettings(const XrayProtocolConfig &other) const; + void clearClientSettings(); + xray::ServerProtocolConfig serverProtocolConfig; xray::ClientProtocolConfig clientProtocolConfig; }; diff --git a/client/ui/controllers/installController.cpp b/client/ui/controllers/installController.cpp index 80ef5090..c12beb2d 100755 --- a/client/ui/controllers/installController.cpp +++ b/client/ui/controllers/installController.cpp @@ -80,7 +80,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr int s1 = QRandomGenerator::global()->bounded(15, 150); int s2 = QRandomGenerator::global()->bounded(15, 150); - while (s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) { + while (s1 + awg::messageInitiationSize == s2 + awg::messageResponseSize) { s2 = QRandomGenerator::global()->bounded(15, 150); } @@ -935,6 +935,11 @@ bool InstallController::isUpdateDockerContainerRequired(const DockerContainer co auto oldConfig = qSharedPointerCast(newProtoConfig); return !newConfig->hasEqualServerSettings(*oldConfig.data()); } + case Proto::WireGuard: { + auto newConfig = qSharedPointerCast(oldProtoConfig); + auto oldConfig = qSharedPointerCast(newProtoConfig); + return !newConfig->hasEqualServerSettings(*oldConfig.data()); + } default: return true; } } diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 817004ae..fa92088d 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -24,12 +24,6 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const case NameRole: return ContainerProps::containerHumanNames().value(container); case DescriptionRole: return ContainerProps::containerDescriptions().value(container); case DetailedDescriptionRole: return ContainerProps::containerDetailedDescriptions().value(container); - case ConfigRole: { - if (container == DockerContainer::None) { - return QJsonObject(); - } - return m_containers.value(container); - } case ServiceTypeRole: return ContainerProps::containerService(container); case DockerContainerRole: return container; case IsEasySetupContainerRole: return ContainerProps::isEasySetupContainer(container); @@ -74,11 +68,6 @@ QString ContainersModel::getProcessedContainerName() return ContainerProps::containerHumanNames().value(static_cast(m_processedContainerIndex)); } -QJsonObject ContainersModel::getContainerConfig(const int containerIndex) -{ - return qvariant_cast(data(index(containerIndex), ConfigRole)); -} - bool ContainersModel::isSupportedByCurrentPlatform(const int containerIndex) { return qvariant_cast(data(index(containerIndex), IsSupportedRole)); @@ -117,7 +106,6 @@ QHash ContainersModel::roleNames() const roles[DetailedDescriptionRole] = "detailedDescription"; roles[ServiceTypeRole] = "serviceType"; roles[DockerContainerRole] = "dockerContainer"; - roles[ConfigRole] = "config"; roles[IsEasySetupContainerRole] = "isEasySetupContainer"; roles[EasySetupHeaderRole] = "easySetupHeader"; diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 9d1407a1..d471c58a 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -18,7 +18,6 @@ public: DescriptionRole, DetailedDescriptionRole, ServiceTypeRole, - ConfigRole, DockerContainerRole, IsEasySetupContainerRole, @@ -48,8 +47,6 @@ public slots: QString getProcessedContainerName(); - QJsonObject getContainerConfig(const int containerIndex); - bool isSupportedByCurrentPlatform(const int containerIndex); bool isServiceContainer(const int containerIndex); diff --git a/client/ui/models/protocols/cloakConfigModel.cpp b/client/ui/models/protocols/cloakConfigModel.cpp index a9f06f4d..321ec9e6 100644 --- a/client/ui/models/protocols/cloakConfigModel.cpp +++ b/client/ui/models/protocols/cloakConfigModel.cpp @@ -2,7 +2,10 @@ #include "protocols/protocols_defs.h" -CloakConfigModel::CloakConfigModel(QObject *parent) : QAbstractListModel(parent) +CloakConfigModel::CloakConfigModel(QObject *parent) + : QAbstractListModel(parent), + m_newCloakProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::Cloak)), + m_oldCloakProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::Cloak)) { } @@ -19,9 +22,9 @@ bool CloakConfigModel::setData(const QModelIndex &index, const QVariant &value, } switch (role) { - case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; - case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break; - case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break; + case Roles::PortRole: m_newCloakProtocolConfig.serverProtocolConfig.port = value.toString(); break; + case Roles::CipherRole: m_newCloakProtocolConfig.serverProtocolConfig.cipher = value.toString(); break; + case Roles::SiteRole: m_newCloakProtocolConfig.serverProtocolConfig.site = value.toString(); break; } emit dataChanged(index, index, QList { role }); @@ -35,35 +38,33 @@ QVariant CloakConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::cloak::defaultPort); - case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::cloak::defaultCipher); - case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite); + case Roles::PortRole: return m_newCloakProtocolConfig.serverProtocolConfig.port; + case Roles::CipherRole: return m_newCloakProtocolConfig.serverProtocolConfig.cipher; + case Roles::SiteRole: return m_newCloakProtocolConfig.serverProtocolConfig.site; } return QVariant(); } -void CloakConfigModel::updateModel(const QJsonObject &config) +void CloakConfigModel::updateModel(const CloakProtocolConfig cloakProtocolConfig) { beginResetModel(); - m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - - m_fullConfig = config; - QJsonObject protocolConfig = config.value(config_key::cloak).toObject(); - - auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Cloak), Proto::Cloak); - m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::cloak::defaultCipher)); - m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::cloak::defaultPort)); - m_protocolConfig.insert(config_key::site, protocolConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite)); - + m_newCloakProtocolConfig = cloakProtocolConfig; + m_oldCloakProtocolConfig = cloakProtocolConfig; endResetModel(); } -QJsonObject CloakConfigModel::getConfig() +QSharedPointer CloakConfigModel::getConfig() { - m_fullConfig.insert(config_key::cloak, m_protocolConfig); - return m_fullConfig; + if (m_oldCloakProtocolConfig.hasEqualServerSettings(m_newCloakProtocolConfig)) { + m_newCloakProtocolConfig.clearClientSettings(); + } + return QSharedPointer::create(m_newCloakProtocolConfig); +} + +bool CloakConfigModel::isServerSettingsEqual() +{ + return m_oldCloakProtocolConfig.hasEqualServerSettings(m_newCloakProtocolConfig); } QHash CloakConfigModel::roleNames() const @@ -76,3 +77,4 @@ QHash CloakConfigModel::roleNames() const return roles; } + diff --git a/client/ui/models/protocols/cloakConfigModel.h b/client/ui/models/protocols/cloakConfigModel.h index 31ff8c53..8de8d305 100644 --- a/client/ui/models/protocols/cloakConfigModel.h +++ b/client/ui/models/protocols/cloakConfigModel.h @@ -5,6 +5,7 @@ #include #include "containers/containers_defs.h" +#include "core/models/protocols/cloakProtocolConfig.h" class CloakConfigModel : public QAbstractListModel { @@ -25,16 +26,17 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &config); - QJsonObject getConfig(); + void updateModel(const CloakProtocolConfig cloakProtocolConfig); + QSharedPointer getConfig(); + + bool isServerSettingsEqual(); protected: QHash roleNames() const override; private: - DockerContainer m_container; - QJsonObject m_protocolConfig; - QJsonObject m_fullConfig; + CloakProtocolConfig m_newCloakProtocolConfig; + CloakProtocolConfig m_oldCloakProtocolConfig; }; #endif // CLOAKCONFIGMODEL_H diff --git a/client/ui/models/protocols/openvpnConfigModel.cpp b/client/ui/models/protocols/openvpnConfigModel.cpp index a04c2b1a..96f46ba0 100644 --- a/client/ui/models/protocols/openvpnConfigModel.cpp +++ b/client/ui/models/protocols/openvpnConfigModel.cpp @@ -2,7 +2,10 @@ #include "protocols/protocols_defs.h" -OpenVpnConfigModel::OpenVpnConfigModel(QObject *parent) : QAbstractListModel(parent) +OpenVpnConfigModel::OpenVpnConfigModel(QObject *parent) + : QAbstractListModel(parent), + m_newOpenVpnProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::OpenVpn)), + m_oldOpenVpnProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::OpenVpn)) { } @@ -19,16 +22,16 @@ bool OpenVpnConfigModel::setData(const QModelIndex &index, const QVariant &value } switch (role) { - case Roles::SubnetAddressRole: m_protocolConfig.insert(amnezia::config_key::subnet_address, value.toString()); break; - case Roles::TransportProtoRole: m_protocolConfig.insert(config_key::transport_proto, value.toString()); break; - case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; - case Roles::AutoNegotiateEncryprionRole: m_protocolConfig.insert(config_key::ncp_disable, !value.toBool()); break; - case Roles::HashRole: m_protocolConfig.insert(config_key::hash, value.toString()); break; - case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break; - case Roles::TlsAuthRole: m_protocolConfig.insert(config_key::tls_auth, value.toBool()); break; - case Roles::BlockDnsRole: m_protocolConfig.insert(config_key::block_outside_dns, value.toBool()); break; - case Roles::AdditionalClientCommandsRole: m_protocolConfig.insert(config_key::additional_client_config, value.toString()); break; - case Roles::AdditionalServerCommandsRole: m_protocolConfig.insert(config_key::additional_server_config, value.toString()); break; + case Roles::SubnetAddressRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.subnetAddress = value.toString(); break; + case Roles::TransportProtoRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.transportProto = value.toString(); break; + case Roles::PortRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.port = value.toString(); break; + case Roles::AutoNegotiateEncryprionRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.ncpDisable = !value.toBool(); break; + case Roles::HashRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.hash = value.toString(); break; + case Roles::CipherRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.cipher = value.toString(); break; + case Roles::TlsAuthRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.tlsAuth = value.toBool(); break; + case Roles::BlockDnsRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.blockOutsideDns = value.toBool(); break; + case Roles::AdditionalClientCommandsRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.additionalClientConfig = value.toString(); break; + case Roles::AdditionalServerCommandsRole: m_newOpenVpnProtocolConfig.serverProtocolConfig.additionalServerConfig = value.toString(); break; } emit dataChanged(index, index, QList { role }); @@ -42,72 +45,42 @@ QVariant OpenVpnConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::SubnetAddressRole: - return m_protocolConfig.value(amnezia::config_key::subnet_address).toString(amnezia::protocols::openvpn::defaultSubnetAddress); - case Roles::TransportProtoRole: - return m_protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto); - case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort); - case Roles::AutoNegotiateEncryprionRole: - return !m_protocolConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable); - case Roles::HashRole: return m_protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash); - case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher); - case Roles::TlsAuthRole: return m_protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth); - case Roles::BlockDnsRole: - return m_protocolConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns); - case Roles::AdditionalClientCommandsRole: - return m_protocolConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig); - case Roles::AdditionalServerCommandsRole: - return m_protocolConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig); - case Roles::IsPortEditable: return m_container == DockerContainer::OpenVpn ? true : false; - case Roles::IsTransportProtoEditable: return m_container == DockerContainer::OpenVpn ? true : false; - case Roles::HasRemoveButton: return m_container == DockerContainer::OpenVpn ? true : false; + case Roles::SubnetAddressRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.subnetAddress; + case Roles::TransportProtoRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.transportProto; + case Roles::PortRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.port; + case Roles::AutoNegotiateEncryprionRole: return !m_newOpenVpnProtocolConfig.serverProtocolConfig.ncpDisable; + case Roles::HashRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.hash; + case Roles::CipherRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.cipher; + case Roles::TlsAuthRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.tlsAuth; + case Roles::BlockDnsRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.blockOutsideDns; + case Roles::AdditionalClientCommandsRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.additionalClientConfig; + case Roles::AdditionalServerCommandsRole: return m_newOpenVpnProtocolConfig.serverProtocolConfig.additionalServerConfig; + case Roles::IsPortEditable: return true; // TODO: implement container check if needed + case Roles::IsTransportProtoEditable: return true; // TODO: implement container check if needed + case Roles::HasRemoveButton: return true; // TODO: implement container check if needed } return QVariant(); } -void OpenVpnConfigModel::updateModel(const QJsonObject &config) +void OpenVpnConfigModel::updateModel(const OpenVpnProtocolConfig openVpnProtocolConfig) { beginResetModel(); - m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - - m_fullConfig = config; - QJsonObject protocolConfig = config.value(config_key::openvpn).toObject(); - - m_protocolConfig.insert( - config_key::subnet_address, - protocolConfig.value(amnezia::config_key::subnet_address).toString(amnezia::protocols::openvpn::defaultSubnetAddress)); - - QString transportProto; - if (m_container == DockerContainer::OpenVpn) { - transportProto = protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto); - } else { - transportProto = "tcp"; - } - - m_protocolConfig.insert(config_key::transport_proto, transportProto); - - m_protocolConfig.insert(config_key::ncp_disable, - protocolConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable)); - m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher)); - m_protocolConfig.insert(config_key::hash, protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash)); - m_protocolConfig.insert(config_key::block_outside_dns, - protocolConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns)); - m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort)); - m_protocolConfig.insert(config_key::tls_auth, protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth)); - m_protocolConfig.insert( - config_key::additional_client_config, - protocolConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig)); - m_protocolConfig.insert( - config_key::additional_server_config, - protocolConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig)); - + m_newOpenVpnProtocolConfig = openVpnProtocolConfig; + m_oldOpenVpnProtocolConfig = openVpnProtocolConfig; endResetModel(); } -QJsonObject OpenVpnConfigModel::getConfig() +QSharedPointer OpenVpnConfigModel::getConfig() { - m_fullConfig.insert(config_key::openvpn, m_protocolConfig); - return m_fullConfig; + if (m_oldOpenVpnProtocolConfig.hasEqualServerSettings(m_newOpenVpnProtocolConfig)) { + m_newOpenVpnProtocolConfig.clearClientSettings(); + } + return QSharedPointer::create(m_newOpenVpnProtocolConfig); +} + +bool OpenVpnConfigModel::isServerSettingsEqual() +{ + return m_oldOpenVpnProtocolConfig.hasEqualServerSettings(m_newOpenVpnProtocolConfig); } QHash OpenVpnConfigModel::roleNames() const diff --git a/client/ui/models/protocols/openvpnConfigModel.h b/client/ui/models/protocols/openvpnConfigModel.h index 0357700c..0105c926 100644 --- a/client/ui/models/protocols/openvpnConfigModel.h +++ b/client/ui/models/protocols/openvpnConfigModel.h @@ -5,6 +5,7 @@ #include #include "containers/containers_defs.h" +#include "core/models/protocols/openvpnProtocolConfig.h" class OpenVpnConfigModel : public QAbstractListModel { @@ -37,16 +38,17 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &config); - QJsonObject getConfig(); + void updateModel(const OpenVpnProtocolConfig openVpnProtocolConfig); + QSharedPointer getConfig(); + + bool isServerSettingsEqual(); protected: QHash roleNames() const override; private: - DockerContainer m_container; - QJsonObject m_protocolConfig; - QJsonObject m_fullConfig; + OpenVpnProtocolConfig m_newOpenVpnProtocolConfig; + OpenVpnProtocolConfig m_oldOpenVpnProtocolConfig; }; #endif // OPENVPNCONFIGMODEL_H diff --git a/client/ui/models/protocols/shadowsocksConfigModel.cpp b/client/ui/models/protocols/shadowsocksConfigModel.cpp index 769bef20..064bd070 100644 --- a/client/ui/models/protocols/shadowsocksConfigModel.cpp +++ b/client/ui/models/protocols/shadowsocksConfigModel.cpp @@ -2,7 +2,10 @@ #include "protocols/protocols_defs.h" -ShadowSocksConfigModel::ShadowSocksConfigModel(QObject *parent) : QAbstractListModel(parent) +ShadowSocksConfigModel::ShadowSocksConfigModel(QObject *parent) + : QAbstractListModel(parent), + m_newShadowsocksProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::ShadowSocks)), + m_oldShadowsocksProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::ShadowSocks)) { } @@ -19,8 +22,8 @@ bool ShadowSocksConfigModel::setData(const QModelIndex &index, const QVariant &v } switch (role) { - case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; - case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break; + case Roles::PortRole: m_newShadowsocksProtocolConfig.serverProtocolConfig.port = value.toString(); break; + case Roles::CipherRole: m_newShadowsocksProtocolConfig.serverProtocolConfig.cipher = value.toString(); break; } emit dataChanged(index, index, QList { role }); @@ -34,36 +37,34 @@ QVariant ShadowSocksConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort); - case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher); - case Roles::IsPortEditableRole: return m_container == DockerContainer::ShadowSocks ? true : false; - case Roles::IsCipherEditableRole: return m_container == DockerContainer::ShadowSocks ? true : false; + case Roles::PortRole: return m_newShadowsocksProtocolConfig.serverProtocolConfig.port; + case Roles::CipherRole: return m_newShadowsocksProtocolConfig.serverProtocolConfig.cipher; + case Roles::IsPortEditableRole: return true; // TODO: implement container check if needed + case Roles::IsCipherEditableRole: return true; // TODO: implement container check if needed } return QVariant(); } -void ShadowSocksConfigModel::updateModel(const QJsonObject &config) +void ShadowSocksConfigModel::updateModel(const ShadowsocksProtocolConfig shadowsocksProtocolConfig) { beginResetModel(); - m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - - m_fullConfig = config; - QJsonObject protocolConfig = config.value(config_key::shadowsocks).toObject(); - - auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::ShadowSocks), Proto::ShadowSocks); - m_protocolConfig.insert(config_key::transport_proto, - protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher)); - m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort)); - + m_newShadowsocksProtocolConfig = shadowsocksProtocolConfig; + m_oldShadowsocksProtocolConfig = shadowsocksProtocolConfig; endResetModel(); } -QJsonObject ShadowSocksConfigModel::getConfig() +QSharedPointer ShadowSocksConfigModel::getConfig() { - m_fullConfig.insert(config_key::shadowsocks, m_protocolConfig); - return m_fullConfig; + if (m_oldShadowsocksProtocolConfig.hasEqualServerSettings(m_newShadowsocksProtocolConfig)) { + m_newShadowsocksProtocolConfig.clearClientSettings(); + } + return QSharedPointer::create(m_newShadowsocksProtocolConfig); +} + +bool ShadowSocksConfigModel::isServerSettingsEqual() +{ + return m_oldShadowsocksProtocolConfig.hasEqualServerSettings(m_newShadowsocksProtocolConfig); } QHash ShadowSocksConfigModel::roleNames() const @@ -77,3 +78,4 @@ QHash ShadowSocksConfigModel::roleNames() const return roles; } + diff --git a/client/ui/models/protocols/shadowsocksConfigModel.h b/client/ui/models/protocols/shadowsocksConfigModel.h index 566df768..21b05b31 100644 --- a/client/ui/models/protocols/shadowsocksConfigModel.h +++ b/client/ui/models/protocols/shadowsocksConfigModel.h @@ -5,6 +5,7 @@ #include #include "containers/containers_defs.h" +#include "core/models/protocols/shadowsocksProtocolConfig.h" class ShadowSocksConfigModel : public QAbstractListModel { @@ -26,16 +27,17 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &config); - QJsonObject getConfig(); + void updateModel(const ShadowsocksProtocolConfig shadowsocksProtocolConfig); + QSharedPointer getConfig(); + + bool isServerSettingsEqual(); protected: QHash roleNames() const override; private: - DockerContainer m_container; - QJsonObject m_protocolConfig; - QJsonObject m_fullConfig; + ShadowsocksProtocolConfig m_newShadowsocksProtocolConfig; + ShadowsocksProtocolConfig m_oldShadowsocksProtocolConfig; }; #endif // SHADOWSOCKSCONFIGMODEL_H diff --git a/client/ui/models/protocols/wireguardConfigModel.cpp b/client/ui/models/protocols/wireguardConfigModel.cpp index 1c8e1341..a8b02272 100644 --- a/client/ui/models/protocols/wireguardConfigModel.cpp +++ b/client/ui/models/protocols/wireguardConfigModel.cpp @@ -4,7 +4,10 @@ #include "protocols/protocols_defs.h" -WireGuardConfigModel::WireGuardConfigModel(QObject *parent) : QAbstractListModel(parent) +WireGuardConfigModel::WireGuardConfigModel(QObject *parent) + : QAbstractListModel(parent), + m_newWireGuardProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::WireGuard)), + m_oldWireGuardProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::WireGuard)) { } @@ -21,9 +24,9 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val } switch (role) { - case Roles::SubnetAddressRole: m_serverProtocolConfig.insert(config_key::subnet_address, value.toString()); break; - case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break; - case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break; + case Roles::SubnetAddressRole: m_newWireGuardProtocolConfig.serverProtocolConfig.subnetAddress = value.toString(); break; + case Roles::PortRole: m_newWireGuardProtocolConfig.serverProtocolConfig.port = value.toString(); break; + case Roles::ClientMtuRole: m_newWireGuardProtocolConfig.clientProtocolConfig.wireGuardData.mtu = value.toString(); break; } emit dataChanged(index, index, QList { role }); @@ -37,62 +40,33 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::SubnetAddressRole: return m_serverProtocolConfig.value(config_key::subnet_address).toString(); - case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString(); - case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu); + case Roles::SubnetAddressRole: return m_newWireGuardProtocolConfig.serverProtocolConfig.subnetAddress; + case Roles::PortRole: return m_newWireGuardProtocolConfig.serverProtocolConfig.port; + case Roles::ClientMtuRole: return m_newWireGuardProtocolConfig.clientProtocolConfig.wireGuardData.mtu; } return QVariant(); } -void WireGuardConfigModel::updateModel(const QJsonObject &config) +void WireGuardConfigModel::updateModel(const WireGuardProtocolConfig wireGuardProtocolConfig) { beginResetModel(); - m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - - m_fullConfig = config; - QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject(); - - auto defaultTransportProto = - ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard); - m_serverProtocolConfig.insert(config_key::transport_proto, - serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config); - m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); - m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); - - auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu); - + m_newWireGuardProtocolConfig = wireGuardProtocolConfig; + m_oldWireGuardProtocolConfig = wireGuardProtocolConfig; endResetModel(); } -QJsonObject WireGuardConfigModel::getConfig() +QSharedPointer WireGuardConfigModel::getConfig() { - const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject()); - const WgConfig newConfig(m_serverProtocolConfig); - - if (!oldConfig.hasEqualServerSettings(newConfig)) { - m_serverProtocolConfig.remove(config_key::last_config); - } else { - auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu]; - - m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); + if (m_oldWireGuardProtocolConfig.hasEqualServerSettings(m_newWireGuardProtocolConfig)) { + m_newWireGuardProtocolConfig.clearClientSettings(); } - - m_fullConfig.insert(config_key::wireguard, m_serverProtocolConfig); - return m_fullConfig; + return QSharedPointer::create(m_newWireGuardProtocolConfig); } bool WireGuardConfigModel::isServerSettingsEqual() { - const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject()); - const WgConfig newConfig(m_serverProtocolConfig); - - return oldConfig.hasEqualServerSettings(newConfig); + return m_oldWireGuardProtocolConfig.hasEqualServerSettings(m_newWireGuardProtocolConfig); } QHash WireGuardConfigModel::roleNames() const @@ -105,29 +79,3 @@ QHash WireGuardConfigModel::roleNames() const return roles; } - -WgConfig::WgConfig(const QJsonObject &serverProtocolConfig) -{ - auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString(); - QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu); - - subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress); - port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); -} - -bool WgConfig::hasEqualServerSettings(const WgConfig &other) const -{ - if (subnetAddress != other.subnetAddress || port != other.port) { - return false; - } - return true; -} - -bool WgConfig::hasEqualClientSettings(const WgConfig &other) const -{ - if (clientMtu != other.clientMtu) { - return false; - } - return true; -} diff --git a/client/ui/models/protocols/wireguardConfigModel.h b/client/ui/models/protocols/wireguardConfigModel.h index b1ce2d61..9010d9b4 100644 --- a/client/ui/models/protocols/wireguardConfigModel.h +++ b/client/ui/models/protocols/wireguardConfigModel.h @@ -5,19 +5,7 @@ #include #include "containers/containers_defs.h" - -struct WgConfig -{ - WgConfig(const QJsonObject &jsonConfig); - - QString subnetAddress; - QString port; - QString clientMtu; - - bool hasEqualServerSettings(const WgConfig &other) const; - bool hasEqualClientSettings(const WgConfig &other) const; - -}; +#include "core/models/protocols/wireguardProtocolConfig.h" class WireGuardConfigModel : public QAbstractListModel { @@ -38,8 +26,8 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &config); - QJsonObject getConfig(); + void updateModel(const WireGuardProtocolConfig wireGuardProtocolConfig); + QSharedPointer getConfig(); bool isServerSettingsEqual(); @@ -47,10 +35,8 @@ protected: QHash roleNames() const override; private: - DockerContainer m_container; - QJsonObject m_serverProtocolConfig; - QJsonObject m_clientProtocolConfig; - QJsonObject m_fullConfig; + WireGuardProtocolConfig m_newWireGuardProtocolConfig; + WireGuardProtocolConfig m_oldWireGuardProtocolConfig; }; #endif // WIREGUARDCONFIGMODEL_H diff --git a/client/ui/models/protocols/xrayConfigModel.cpp b/client/ui/models/protocols/xrayConfigModel.cpp index 3917b544..fdcf15e3 100644 --- a/client/ui/models/protocols/xrayConfigModel.cpp +++ b/client/ui/models/protocols/xrayConfigModel.cpp @@ -2,7 +2,10 @@ #include "protocols/protocols_defs.h" -XrayConfigModel::XrayConfigModel(QObject *parent) : QAbstractListModel(parent) +XrayConfigModel::XrayConfigModel(QObject *parent) + : QAbstractListModel(parent), + m_newXrayProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::Xray)), + m_oldXrayProtocolConfig(QJsonObject(), ProtocolProps::protoToString(Proto::Xray)) { } @@ -19,8 +22,8 @@ bool XrayConfigModel::setData(const QModelIndex &index, const QVariant &value, i } switch (role) { - case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break; - case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; + case Roles::SiteRole: m_newXrayProtocolConfig.serverProtocolConfig.site = value.toString(); break; + case Roles::PortRole: m_newXrayProtocolConfig.serverProtocolConfig.port = value.toString(); break; } emit dataChanged(index, index, QList { role }); @@ -34,34 +37,32 @@ QVariant XrayConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite); - case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::xray::defaultPort); + case Roles::SiteRole: return m_newXrayProtocolConfig.serverProtocolConfig.site; + case Roles::PortRole: return m_newXrayProtocolConfig.serverProtocolConfig.port; } return QVariant(); } -void XrayConfigModel::updateModel(const QJsonObject &config) +void XrayConfigModel::updateModel(const XrayProtocolConfig xrayProtocolConfig) { beginResetModel(); - m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); - - m_fullConfig = config; - QJsonObject protocolConfig = config.value(config_key::xray).toObject(); - - auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Xray), Proto::Xray); - m_protocolConfig.insert(config_key::transport_proto, - protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::xray::defaultPort)); - m_protocolConfig.insert(config_key::site, protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite)); - + m_newXrayProtocolConfig = xrayProtocolConfig; + m_oldXrayProtocolConfig = xrayProtocolConfig; endResetModel(); } -QJsonObject XrayConfigModel::getConfig() +QSharedPointer XrayConfigModel::getConfig() { - m_fullConfig.insert(config_key::xray, m_protocolConfig); - return m_fullConfig; + if (m_oldXrayProtocolConfig.hasEqualServerSettings(m_newXrayProtocolConfig)) { + m_newXrayProtocolConfig.clearClientSettings(); + } + return QSharedPointer::create(m_newXrayProtocolConfig); +} + +bool XrayConfigModel::isServerSettingsEqual() +{ + return m_oldXrayProtocolConfig.hasEqualServerSettings(m_newXrayProtocolConfig); } QHash XrayConfigModel::roleNames() const @@ -73,3 +74,4 @@ QHash XrayConfigModel::roleNames() const return roles; } + diff --git a/client/ui/models/protocols/xrayConfigModel.h b/client/ui/models/protocols/xrayConfigModel.h index 41aac589..519d7fb4 100644 --- a/client/ui/models/protocols/xrayConfigModel.h +++ b/client/ui/models/protocols/xrayConfigModel.h @@ -5,6 +5,7 @@ #include #include "containers/containers_defs.h" +#include "core/models/protocols/xrayProtocolConfig.h" class XrayConfigModel : public QAbstractListModel { @@ -24,16 +25,17 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: - void updateModel(const QJsonObject &config); - QJsonObject getConfig(); + void updateModel(const XrayProtocolConfig xrayProtocolConfig); + QSharedPointer getConfig(); + + bool isServerSettingsEqual(); protected: QHash roleNames() const override; private: - DockerContainer m_container; - QJsonObject m_protocolConfig; - QJsonObject m_fullConfig; + XrayProtocolConfig m_newXrayProtocolConfig; + XrayProtocolConfig m_oldXrayProtocolConfig; }; #endif // XRAYCONFIGMODEL_H diff --git a/client/ui/models/protocols_model.cpp b/client/ui/models/protocols_model.cpp index 6a996ec0..add32488 100644 --- a/client/ui/models/protocols_model.cpp +++ b/client/ui/models/protocols_model.cpp @@ -16,7 +16,9 @@ ProtocolsModel::ProtocolsModel(const QSharedPointer &openVpn const QSharedPointer &cloakConfigModel, const QSharedPointer &wireGuardConfigModel, const QSharedPointer &awgConfigModel, const QSharedPointer &xrayConfigModel, +#ifdef Q_OS_WINDOWS const QSharedPointer &ikev2ConfigModel, +#endif const QSharedPointer &sftpConfigModel, const QSharedPointer &socks5ProxyConfigModel, QObject *parent) : QAbstractListModel(parent), @@ -26,7 +28,9 @@ ProtocolsModel::ProtocolsModel(const QSharedPointer &openVpn m_wireGuardConfigModel(wireGuardConfigModel), m_awgConfigModel(awgConfigModel), m_xrayConfigModel(xrayConfigModel), +#ifdef Q_OS_WINDOWS m_ikev2ConfigModel(ikev2ConfigModel), +#endif m_sftpConfigModel(sftpConfigModel), m_socks5ProxyConfigModel(socks5ProxyConfigModel) { @@ -111,18 +115,18 @@ void ProtocolsModel::updateProtocolModel(amnezia::Proto protocol) } switch (protocol) { - case Proto::OpenVpn: m_openVpnConfigModel->updateModel(config); break; - case Proto::ShadowSocks: m_shadowSocksConfigModel->updateModel(config); break; - case Proto::Cloak: m_cloakConfigModel->updateModel(config); break; - case Proto::WireGuard: m_wireGuardConfigModel->updateModel(config); break; - case Proto::Awg: m_awgConfigModel->updateModel(config); break; - case Proto::Xray: m_xrayConfigModel->updateModel(config); break; + case Proto::OpenVpn: m_openVpnConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; + case Proto::ShadowSocks: m_shadowSocksConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; + case Proto::Cloak: m_cloakConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; + case Proto::WireGuard: m_wireGuardConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; + case Proto::Awg: m_awgConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; + case Proto::Xray: m_xrayConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; #ifdef Q_OS_WINDOWS case Proto::Ikev2: - case Proto::L2tp: m_ikev2ConfigModel->updateModel(config); break; + case Proto::L2tp: m_ikev2ConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; #endif - case Proto::Sftp: m_sftpConfigModel->updateModel(config); break; - case Proto::Socks5Proxy: m_socks5ProxyConfigModel->updateModel(config); break; + // case Proto::Sftp: m_sftpConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; + // case Proto::Socks5Proxy: m_socks5ProxyConfigModel->updateModel(*qSharedPointerCast(protocolConfig).data()); break; default: break; } } @@ -134,17 +138,17 @@ QMap> ProtocolsModel::getProtocolConfigs for (const auto &config : m_protocolConfigs) { switch (ProtocolProps::protoFromString(config->protocolName)) { case Proto::OpenVpn: protocolConfigs.insert(config->protocolName, m_openVpnConfigModel->getConfig()); break; - case Proto::ShadowSocks: m_shadowSocksConfigModel->updateModel(config); break; - case Proto::Cloak: m_cloakConfigModel->updateModel(config); break; - case Proto::WireGuard: m_wireGuardConfigModel->updateModel(config); break; + case Proto::ShadowSocks: protocolConfigs.insert(config->protocolName, m_shadowSocksConfigModel->getConfig()); break; + case Proto::Cloak: protocolConfigs.insert(config->protocolName, m_cloakConfigModel->getConfig()); break; + case Proto::WireGuard: protocolConfigs.insert(config->protocolName, m_wireGuardConfigModel->getConfig()); break; case Proto::Awg: protocolConfigs.insert(config->protocolName, m_awgConfigModel->getConfig()); break; - case Proto::Xray: m_xrayConfigModel->updateModel(config); break; + case Proto::Xray: protocolConfigs.insert(config->protocolName, m_xrayConfigModel->getConfig()); break; #ifdef Q_OS_WINDOWS case Proto::Ikev2: - case Proto::L2tp: m_ikev2ConfigModel->updateModel(config); break; + case Proto::L2tp: protocolConfigs.insert(config->protocolName, m_awgConfigModel->getConfig()); break; #endif - case Proto::Sftp: m_sftpConfigModel->updateModel(config); break; - case Proto::Socks5Proxy: m_socks5ProxyConfigModel->updateModel(config); break; + // case Proto::Sftp: protocolConfigs.insert(config->protocolName, m_awgConfigModel->getConfig()); break; + // case Proto::Socks5Proxy: protocolConfigs.insert(config->protocolName, m_awgConfigModel->getConfig()); break; default: break; } }