From 96566f04ee8e8df05ce8148940a0a0d5810b70bf Mon Sep 17 00:00:00 2001 From: Nethius Date: Fri, 13 Sep 2024 12:38:48 +0400 Subject: [PATCH] feature/mtu connection config (#833) * added the ability to change mtu for connection-only configs * added replacing MTU with default when importing awg/wg configs in amnezia --- .../vpnConfigurationController.cpp | 8 + client/resources.qrc | 2 + client/ui/controllers/importController.cpp | 36 +- client/ui/controllers/importController.h | 2 + client/ui/controllers/pageController.h | 3 + client/ui/models/protocols/awgConfigModel.cpp | 218 +++++++----- client/ui/models/protocols/awgConfigModel.h | 55 +-- .../models/protocols/wireguardConfigModel.cpp | 60 ++-- .../models/protocols/wireguardConfigModel.h | 9 +- client/ui/models/protocols_model.cpp | 30 +- client/ui/models/protocols_model.h | 9 +- .../Pages2/PageProtocolAwgClientSettings.qml | 312 ++++++++++++++++++ .../ui/qml/Pages2/PageProtocolAwgSettings.qml | 113 +++---- .../PageProtocolWireGuardClientSettings.qml | 179 ++++++++++ .../Pages2/PageProtocolWireGuardSettings.qml | 60 ++-- .../qml/Pages2/PageSettingsServerProtocol.qml | 56 +++- 16 files changed, 903 insertions(+), 249 deletions(-) create mode 100644 client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml create mode 100644 client/ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml diff --git a/client/core/controllers/vpnConfigurationController.cpp b/client/core/controllers/vpnConfigurationController.cpp index 818cf57e..291c429c 100644 --- a/client/core/controllers/vpnConfigurationController.cpp +++ b/client/core/controllers/vpnConfigurationController.cpp @@ -101,6 +101,14 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPairserver_scripts/socks5_proxy/Dockerfile server_scripts/socks5_proxy/configure_container.sh server_scripts/socks5_proxy/start.sh + ui/qml/Pages2/PageProtocolAwgClientSettings.qml + ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml ui/qml/Pages2/PageSetupWizardApiServicesList.qml ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml ui/qml/Controls2/CardWithIconsType.qml diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index 7ffcedd7..a50e793f 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -173,6 +173,7 @@ bool ImportController::extractConfigFromData(QString data) } case ConfigTypes::Amnezia: { m_config = QJsonDocument::fromJson(config.toUtf8()).object(); + processAmneziaConfig(m_config); if (!m_config.empty()) { checkForMaliciousStrings(m_config); return true; @@ -391,10 +392,6 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) return QJsonObject(); } - if (!configMap.value("MTU").isEmpty()) { - lastConfig[config_key::mtu] = configMap.value("MTU"); - } - QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(",")); lastConfig[config_key::allowed_ips] = allowedIpsJsonArray; @@ -419,6 +416,12 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data) m_configType = ConfigTypes::Awg; } + if (!configMap.value("MTU").isEmpty()) { + lastConfig[config_key::mtu] = configMap.value("MTU"); + } else { + lastConfig[config_key::mtu] = protocolName == "awg" ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu; + } + QJsonObject wireguardConfig; wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson()); wireguardConfig[config_key::isThirdPartyConfig] = true; @@ -646,3 +649,28 @@ void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig) } } } + +void ImportController::processAmneziaConfig(QJsonObject &config) +{ + auto containers = config.value(config_key::containers).toArray(); + for (auto i = 0; i < containers.size(); i++) { + auto container = containers.at(i).toObject(); + auto dockerContainer = ContainerProps::containerFromString(container.value(config_key::container).toString()); + if (dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::WireGuard) { + auto containerConfig = container.value(ContainerProps::containerTypeToString(dockerContainer)).toObject(); + auto protocolConfig = containerConfig.value(config_key::last_config).toString(); + if (protocolConfig.isEmpty()) { + return; + } + + QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object(); + jsonConfig[config_key::mtu] = dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu; + + containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); + + container[ContainerProps::containerTypeToString(dockerContainer)] = containerConfig; + containers.replace(i, container); + config.insert(config_key::containers, containers); + } + } +} diff --git a/client/ui/controllers/importController.h b/client/ui/controllers/importController.h index ea1ba6b0..61205253 100644 --- a/client/ui/controllers/importController.h +++ b/client/ui/controllers/importController.h @@ -68,6 +68,8 @@ private: void checkForMaliciousStrings(const QJsonObject &protocolConfig); + void processAmneziaConfig(QJsonObject &config); + #if defined Q_OS_ANDROID || defined Q_OS_IOS void stopDecodingQr(); #endif diff --git a/client/ui/controllers/pageController.h b/client/ui/controllers/pageController.h index 2cc2d983..f89d39a1 100644 --- a/client/ui/controllers/pageController.h +++ b/client/ui/controllers/pageController.h @@ -59,6 +59,9 @@ namespace PageLoader PageProtocolIKev2Settings, PageProtocolRaw, + PageProtocolWireGuardClientSettings, + PageProtocolAwgClientSettings, + PageShareFullAccess, PageDevMenu diff --git a/client/ui/models/protocols/awgConfigModel.cpp b/client/ui/models/protocols/awgConfigModel.cpp index 658658df..3a245ebe 100644 --- a/client/ui/models/protocols/awgConfigModel.cpp +++ b/client/ui/models/protocols/awgConfigModel.cpp @@ -21,17 +21,30 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in } switch (role) { - case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; - case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break; - case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break; - case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break; - case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break; - case Roles::InitPacketJunkSizeRole: m_protocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break; - case Roles::ResponsePacketJunkSizeRole: m_protocolConfig.insert(config_key::responsePacketJunkSize, value.toString()); break; - case Roles::InitPacketMagicHeaderRole: m_protocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break; - case Roles::ResponsePacketMagicHeaderRole: m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); break; - case Roles::UnderloadPacketMagicHeaderRole: m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); break; - case Roles::TransportPacketMagicHeaderRole: m_protocolConfig.insert(config_key::transportPacketMagicHeader, 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::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()); + break; + case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break; + case Roles::ServerResponsePacketMagicHeaderRole: + m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); + break; + case Roles::ServerUnderloadPacketMagicHeaderRole: + m_serverProtocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); + break; + case Roles::ServerTransportPacketMagicHeaderRole: + m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); + break; } emit dataChanged(index, index, QList { role }); @@ -45,17 +58,22 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(); - case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString(); - case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount); - case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize); - case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize); - case Roles::InitPacketJunkSizeRole: return m_protocolConfig.value(config_key::initPacketJunkSize); - case Roles::ResponsePacketJunkSizeRole: return m_protocolConfig.value(config_key::responsePacketJunkSize); - case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader); - case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader); - case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader); - case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader); + case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString(); + + 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::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); } return QVariant(); @@ -68,51 +86,63 @@ void AwgConfigModel::updateModel(const QJsonObject &config) m_fullConfig = config; - QJsonObject protocolConfig = config.value(config_key::awg).toObject(); + QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject(); auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg); - m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config); - m_protocolConfig[config_key::port] = protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort); - m_protocolConfig[config_key::mtu] = protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu); - m_protocolConfig[config_key::junkPacketCount] = - protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); - m_protocolConfig[config_key::junkPacketMinSize] = - protocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); - m_protocolConfig[config_key::junkPacketMaxSize] = - protocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); - m_protocolConfig[config_key::initPacketJunkSize] = - protocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); - m_protocolConfig[config_key::responsePacketJunkSize] = - protocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); - m_protocolConfig[config_key::initPacketMagicHeader] = - protocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); - m_protocolConfig[config_key::responsePacketMagicHeader] = - protocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); - m_protocolConfig[config_key::underloadPacketMagicHeader] = - protocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); - m_protocolConfig[config_key::transportPacketMagicHeader] = - protocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); + 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::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()); endResetModel(); } QJsonObject AwgConfigModel::getConfig() { const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); - const AwgConfig newConfig(m_protocolConfig); + const AwgConfig newConfig(m_serverProtocolConfig); if (!oldConfig.hasEqualServerSettings(newConfig)) { - m_protocolConfig.remove(config_key::last_config); + m_serverProtocolConfig.remove(config_key::last_config); } else { - auto lastConfig = m_protocolConfig.value(config_key::last_config).toString(); + auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - jsonConfig[config_key::mtu] = newConfig.mtu; + 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_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); + m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); } - m_fullConfig.insert(config_key::awg, m_protocolConfig); + m_fullConfig.insert(config_key::awg, m_serverProtocolConfig); return m_fullConfig; } @@ -126,50 +156,73 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2) return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2); } +bool AwgConfigModel::isServerSettingsEqual() +{ + const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject()); + const AwgConfig newConfig(m_serverProtocolConfig); + + return oldConfig.hasEqualServerSettings(newConfig); +} + QHash AwgConfigModel::roleNames() const { QHash roles; roles[PortRole] = "port"; - roles[MtuRole] = "mtu"; - roles[JunkPacketCountRole] = "junkPacketCount"; - roles[JunkPacketMinSizeRole] = "junkPacketMinSize"; - roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize"; - roles[InitPacketJunkSizeRole] = "initPacketJunkSize"; - roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize"; - roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader"; - roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader"; - roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader"; - roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader"; + + roles[ClientMtuRole] = "clientMtu"; + roles[ClientJunkPacketCountRole] = "clientJunkPacketCount"; + roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize"; + roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize"; + + roles[ServerJunkPacketCountRole] = "serverJunkPacketCount"; + roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize"; + roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize"; + roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize"; + roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize"; + roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader"; + roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader"; + roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader"; + roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader"; return roles; } -AwgConfig::AwgConfig(const QJsonObject &jsonConfig) +AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig) { - port = jsonConfig.value(config_key::port).toString(protocols::awg::defaultPort); - mtu = jsonConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu); - junkPacketCount = jsonConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount); - junkPacketMinSize = jsonConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize); - junkPacketMaxSize = jsonConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize); - initPacketJunkSize = jsonConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize); - responsePacketJunkSize = jsonConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize); - initPacketMagicHeader = jsonConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader); - responsePacketMagicHeader = - jsonConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader); - underloadPacketMagicHeader = - jsonConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader); - transportPacketMagicHeader = - jsonConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader); + 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); + + 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 (port != other.port || junkPacketCount != other.junkPacketCount || junkPacketMinSize != other.junkPacketMinSize - || junkPacketMaxSize != other.junkPacketMaxSize || initPacketJunkSize != other.initPacketJunkSize - || responsePacketJunkSize != other.responsePacketJunkSize || initPacketMagicHeader != other.initPacketMagicHeader - || responsePacketMagicHeader != other.responsePacketMagicHeader || underloadPacketMagicHeader != other.underloadPacketMagicHeader - || transportPacketMagicHeader != other.transportPacketMagicHeader) { + if (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; @@ -177,7 +230,8 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const { - if (mtu != other.mtu) { + 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 80375d38..06475bf5 100644 --- a/client/ui/models/protocols/awgConfigModel.h +++ b/client/ui/models/protocols/awgConfigModel.h @@ -16,16 +16,21 @@ struct AwgConfig AwgConfig(const QJsonObject &jsonConfig); QString port; - QString mtu; - QString junkPacketCount; - QString junkPacketMinSize; - QString junkPacketMaxSize; - QString initPacketJunkSize; - QString responsePacketJunkSize; - QString initPacketMagicHeader; - QString responsePacketMagicHeader; - QString underloadPacketMagicHeader; - QString transportPacketMagicHeader; + + 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; @@ -39,16 +44,21 @@ class AwgConfigModel : public QAbstractListModel public: enum Roles { PortRole = Qt::UserRole + 1, - MtuRole, - JunkPacketCountRole, - JunkPacketMinSizeRole, - JunkPacketMaxSizeRole, - InitPacketJunkSizeRole, - ResponsePacketJunkSizeRole, - InitPacketMagicHeaderRole, - ResponsePacketMagicHeaderRole, - UnderloadPacketMagicHeaderRole, - TransportPacketMagicHeaderRole + + ClientMtuRole, + ClientJunkPacketCountRole, + ClientJunkPacketMinSizeRole, + ClientJunkPacketMaxSizeRole, + + ServerJunkPacketCountRole, + ServerJunkPacketMinSizeRole, + ServerJunkPacketMaxSizeRole, + ServerInitPacketJunkSizeRole, + ServerResponsePacketJunkSizeRole, + ServerInitPacketMagicHeaderRole, + ServerResponsePacketMagicHeaderRole, + ServerUnderloadPacketMagicHeaderRole, + ServerTransportPacketMagicHeaderRole }; explicit AwgConfigModel(QObject *parent = nullptr); @@ -65,12 +75,15 @@ public slots: bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4); bool isPacketSizeEqual(const int s1, const int s2); + bool isServerSettingsEqual(); + protected: QHash roleNames() const override; private: DockerContainer m_container; - QJsonObject m_protocolConfig; + QJsonObject m_serverProtocolConfig; + QJsonObject m_clientProtocolConfig; QJsonObject m_fullConfig; }; diff --git a/client/ui/models/protocols/wireguardConfigModel.cpp b/client/ui/models/protocols/wireguardConfigModel.cpp index 65bf2bb3..555915de 100644 --- a/client/ui/models/protocols/wireguardConfigModel.cpp +++ b/client/ui/models/protocols/wireguardConfigModel.cpp @@ -21,8 +21,8 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val } switch (role) { - case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break; - case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, 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; } emit dataChanged(index, index, QList { role }); @@ -36,8 +36,8 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const } switch (role) { - case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(); - case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString(); + case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString(); + case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu); } return QVariant(); @@ -49,17 +49,18 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config) m_container = ContainerProps::containerFromString(config.value(config_key::container).toString()); m_fullConfig = config; - QJsonObject protocolConfig = config.value(config_key::wireguard).toObject(); + QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject(); - auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard); - m_protocolConfig.insert(config_key::transport_proto, - protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto)); - m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config); - m_protocolConfig[config_key::port] = - protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); + 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::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); - m_protocolConfig[config_key::mtu] = - protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); + 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); endResetModel(); } @@ -67,36 +68,47 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config) QJsonObject WireGuardConfigModel::getConfig() { const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject()); - const WgConfig newConfig(m_protocolConfig); + const WgConfig newConfig(m_serverProtocolConfig); if (!oldConfig.hasEqualServerSettings(newConfig)) { - m_protocolConfig.remove(config_key::last_config); + m_serverProtocolConfig.remove(config_key::last_config); } else { - auto lastConfig = m_protocolConfig.value(config_key::last_config).toString(); + auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString(); QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object(); - jsonConfig[config_key::mtu] = newConfig.mtu; + jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu]; - m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); + m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson()); } - m_fullConfig.insert(config_key::wireguard, m_protocolConfig); + m_fullConfig.insert(config_key::wireguard, m_serverProtocolConfig); return m_fullConfig; } +bool WireGuardConfigModel::isServerSettingsEqual() +{ + const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject()); + const WgConfig newConfig(m_serverProtocolConfig); + + return oldConfig.hasEqualServerSettings(newConfig); +} + QHash WireGuardConfigModel::roleNames() const { QHash roles; roles[PortRole] = "port"; - roles[MtuRole] = "mtu"; + roles[ClientMtuRole] = "clientMtu"; return roles; } -WgConfig::WgConfig(const QJsonObject &jsonConfig) +WgConfig::WgConfig(const QJsonObject &serverProtocolConfig) { - port = jsonConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); - mtu = jsonConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu); + 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); + + port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort); } bool WgConfig::hasEqualServerSettings(const WgConfig &other) const @@ -109,7 +121,7 @@ bool WgConfig::hasEqualServerSettings(const WgConfig &other) const bool WgConfig::hasEqualClientSettings(const WgConfig &other) const { - if (mtu != other.mtu) { + 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 6cec76dd..a02bea5a 100644 --- a/client/ui/models/protocols/wireguardConfigModel.h +++ b/client/ui/models/protocols/wireguardConfigModel.h @@ -11,7 +11,7 @@ struct WgConfig WgConfig(const QJsonObject &jsonConfig); QString port; - QString mtu; + QString clientMtu; bool hasEqualServerSettings(const WgConfig &other) const; bool hasEqualClientSettings(const WgConfig &other) const; @@ -25,7 +25,7 @@ class WireGuardConfigModel : public QAbstractListModel public: enum Roles { PortRole = Qt::UserRole + 1, - MtuRole + ClientMtuRole }; explicit WireGuardConfigModel(QObject *parent = nullptr); @@ -39,12 +39,15 @@ public slots: void updateModel(const QJsonObject &config); QJsonObject getConfig(); + bool isServerSettingsEqual(); + protected: QHash roleNames() const override; private: DockerContainer m_container; - QJsonObject m_protocolConfig; + QJsonObject m_serverProtocolConfig; + QJsonObject m_clientProtocolConfig; QJsonObject m_fullConfig; }; diff --git a/client/ui/models/protocols_model.cpp b/client/ui/models/protocols_model.cpp index 32447cd4..019b2d2f 100644 --- a/client/ui/models/protocols_model.cpp +++ b/client/ui/models/protocols_model.cpp @@ -16,9 +16,11 @@ QHash ProtocolsModel::roleNames() const QHash roles; roles[ProtocolNameRole] = "protocolName"; - roles[ProtocolPageRole] = "protocolPage"; + roles[ServerProtocolPageRole] = "serverProtocolPage"; + roles[ClientProtocolPageRole] = "clientProtocolPage"; roles[ProtocolIndexRole] = "protocolIndex"; roles[RawConfigRole] = "rawConfig"; + roles[IsClientProtocolExistsRole] = "isClientProtocolExists"; return roles; } @@ -34,8 +36,10 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row())); return ProtocolProps::protocolHumanNames().value(proto); } - case ProtocolPageRole: - return static_cast(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row())))); + 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(); @@ -50,6 +54,15 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const } 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(); + } } return QVariant(); @@ -70,7 +83,7 @@ QJsonObject ProtocolsModel::getConfig() return config; } -PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const +PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const { switch (protocol) { case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings; @@ -90,3 +103,12 @@ PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings; } } + +PageLoader::PageEnum ProtocolsModel::clientProtocolPage(Proto protocol) const +{ + switch (protocol) { + case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardClientSettings; + case Proto::Awg: return PageLoader::PageEnum::PageProtocolAwgClientSettings; + default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings; + } +} diff --git a/client/ui/models/protocols_model.h b/client/ui/models/protocols_model.h index 5ee8a3dd..5c52ee86 100644 --- a/client/ui/models/protocols_model.h +++ b/client/ui/models/protocols_model.h @@ -13,9 +13,11 @@ class ProtocolsModel : public QAbstractListModel public: enum Roles { ProtocolNameRole = Qt::UserRole + 1, - ProtocolPageRole, + ServerProtocolPageRole, + ClientProtocolPageRole, ProtocolIndexRole, - RawConfigRole + RawConfigRole, + IsClientProtocolExistsRole }; ProtocolsModel(std::shared_ptr settings, QObject *parent = nullptr); @@ -33,7 +35,8 @@ protected: QHash roleNames() const override; private: - PageLoader::PageEnum protocolPage(Proto protocol) const; + PageLoader::PageEnum serverProtocolPage(Proto protocol) const; + PageLoader::PageEnum clientProtocolPage(Proto protocol) const; std::shared_ptr m_settings; diff --git a/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml b/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml new file mode 100644 index 00000000..2b912f18 --- /dev/null +++ b/client/ui/qml/Pages2/PageProtocolAwgClientSettings.qml @@ -0,0 +1,312 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import SortFilterProxyModel 0.2 + +import PageEnum 1.0 + +import "./" +import "../Controls2" +import "../Controls2/TextTypes" +import "../Config" +import "../Components" + + +PageType { + id: root + + defaultActiveFocusItem: listview.currentItem.mtuTextField.textField + + Item { + id: focusItem + onFocusChanged: { + if (activeFocus) { + fl.ensureVisible(focusItem) + } + } + KeyNavigation.tab: backButton + } + + ColumnLayout { + id: backButtonLayout + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + anchors.topMargin: 20 + + BackButtonType { + id: backButton + KeyNavigation.tab: listview.currentItem.mtuTextField.textField + } + } + + FlickableType { + id: fl + anchors.top: backButtonLayout.bottom + anchors.bottom: parent.bottom + contentHeight: content.implicitHeight + saveButton.implicitHeight + saveButton.anchors.bottomMargin + saveButton.anchors.topMargin + + Column { + id: content + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + ListView { + id: listview + + width: parent.width + height: listview.contentItem.height + + clip: true + interactive: false + + model: AwgConfigModel + + delegate: Item { + id: delegateItem + implicitWidth: listview.width + implicitHeight: col.implicitHeight + + property alias mtuTextField: mtuTextField + property bool isSaveButtonEnabled: mtuTextField.errorText === "" && + junkPacketMaxSizeTextField.errorText === "" && + junkPacketMinSizeTextField.errorText === "" && + junkPacketCountTextField.errorText === "" + + ColumnLayout { + id: col + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + anchors.leftMargin: 16 + anchors.rightMargin: 16 + + spacing: 0 + + HeaderType { + Layout.fillWidth: true + + headerText: qsTr("AmneziaWG settings") + } + + TextFieldWithHeaderType { + id: mtuTextField + Layout.fillWidth: true + Layout.topMargin: 40 + + headerText: qsTr("MTU") + textFieldText: clientMtu + textField.validator: IntValidator { bottom: 576; top: 65535 } + + textField.onEditingFinished: { + if (textFieldText !== clientMtu) { + clientMtu = textFieldText + } + } + checkEmptyText: true + KeyNavigation.tab: junkPacketCountTextField.textField + } + + TextFieldWithHeaderType { + id: junkPacketCountTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + headerText: "Jc - Junk packet count" + textFieldText: clientJunkPacketCount + textField.validator: IntValidator { bottom: 0 } + parentFlickable: fl + + textField.onEditingFinished: { + if (textFieldText !== clientJunkPacketCount) { + clientJunkPacketCount = textFieldText + } + } + + checkEmptyText: true + + KeyNavigation.tab: junkPacketMinSizeTextField.textField + } + + TextFieldWithHeaderType { + id: junkPacketMinSizeTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + headerText: "Jmin - Junk packet minimum size" + textFieldText: clientJunkPacketMinSize + textField.validator: IntValidator { bottom: 0 } + parentFlickable: fl + + textField.onEditingFinished: { + if (textFieldText !== clientJunkPacketMinSize) { + clientJunkPacketMinSize = textFieldText + } + } + + checkEmptyText: true + + KeyNavigation.tab: junkPacketMaxSizeTextField.textField + } + + TextFieldWithHeaderType { + id: junkPacketMaxSizeTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + headerText: "Jmax - Junk packet maximum size" + textFieldText: clientJunkPacketMaxSize + textField.validator: IntValidator { bottom: 0 } + parentFlickable: fl + + textField.onEditingFinished: { + if (textFieldText !== clientJunkPacketMaxSize) { + clientJunkPacketMaxSize = textFieldText + } + } + + checkEmptyText: true + + Keys.onTabPressed: saveButton.forceActiveFocus() + } + + Header2TextType { + Layout.fillWidth: true + Layout.topMargin: 16 + + text: qsTr("Server settings") + } + + TextFieldWithHeaderType { + id: portTextField + Layout.fillWidth: true + Layout.topMargin: 8 + + enabled: false + + headerText: qsTr("Port") + textFieldText: port + } + + TextFieldWithHeaderType { + id: initPacketJunkSizeTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + enabled: false + + headerText: "S1 - Init packet junk size" + textFieldText: serverInitPacketJunkSize + } + + TextFieldWithHeaderType { + id: responsePacketJunkSizeTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + enabled: false + + headerText: "S2 - Response packet junk size" + textFieldText: serverResponsePacketJunkSize + } + + TextFieldWithHeaderType { + id: initPacketMagicHeaderTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + enabled: false + + headerText: "H1 - Init packet magic header" + textFieldText: serverInitPacketMagicHeader + } + + TextFieldWithHeaderType { + id: responsePacketMagicHeaderTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + enabled: false + + headerText: "H2 - Response packet magic header" + textFieldText: serverResponsePacketMagicHeader + } + + TextFieldWithHeaderType { + id: underloadPacketMagicHeaderTextField + Layout.fillWidth: true + Layout.topMargin: 16 + parentFlickable: fl + + enabled: false + + headerText: "H3 - Underload packet magic header" + textFieldText: serverUnderloadPacketMagicHeader + } + + TextFieldWithHeaderType { + id: transportPacketMagicHeaderTextField + Layout.fillWidth: true + Layout.topMargin: 16 + + enabled: false + + headerText: "H4 - Transport packet magic header" + textFieldText: serverTransportPacketMagicHeader + } + } + } + } + } + } + + BasicButtonType { + id: saveButton + + anchors.right: root.right + anchors.left: root.left + anchors.bottom: root.bottom + + anchors.topMargin: 24 + anchors.bottomMargin: 24 + anchors.rightMargin: 16 + anchors.leftMargin: 16 + + enabled: listview.currentItem.isSaveButtonEnabled + + text: qsTr("Save") + + Keys.onTabPressed: lastItemTabClicked(focusItem) + + clickedFunc: function() { + forceActiveFocus() + var headerText = qsTr("Save settings?") + var descriptionText = qsTr("Only the settings for this device will be changed") + var yesButtonText = qsTr("Continue") + var noButtonText = qsTr("Cancel") + + var yesButtonFunction = function() { + if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { + PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) + return + } + + PageController.goToPage(PageEnum.PageSetupWizardInstalling); + InstallController.updateContainer(AwgConfigModel.getConfig()) + } + var noButtonFunction = function() { + if (!GC.isMobile()) { + saveButton.forceActiveFocus() + } + } + showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) + } + } +} diff --git a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml index 8651fa27..27ea66f9 100644 --- a/client/ui/qml/Pages2/PageProtocolAwgSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolAwgSettings.qml @@ -57,8 +57,6 @@ PageType { anchors.left: parent.left anchors.right: parent.right - enabled: ServersModel.isProcessedServerHasWriteAccess() - ListView { id: listview @@ -71,12 +69,12 @@ PageType { model: AwgConfigModel delegate: Item { - id: _delegate - + id: delegateItem implicitWidth: listview.width implicitHeight: col.implicitHeight - property alias portTextField:portTextField + property alias portTextField: portTextField + property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess() ColumnLayout { id: col @@ -101,6 +99,8 @@ PageType { Layout.fillWidth: true Layout.topMargin: 40 + enabled: delegateItem.isEnabled + headerText: qsTr("Port") textFieldText: port textField.maximumLength: 5 @@ -115,27 +115,6 @@ PageType { checkEmptyText: true - KeyNavigation.tab: mtuTextField.textField - } - - TextFieldWithHeaderType { - id: mtuTextField - Layout.fillWidth: true - Layout.topMargin: 16 - - headerText: qsTr("MTU") - textFieldText: mtu - textField.validator: IntValidator { bottom: 576; top: 65535 } - - textField.onEditingFinished: { - if (textFieldText === "") { - textFieldText = "0" - } - if (textFieldText !== mtu) { - mtu = textFieldText - } - } - checkEmptyText: true KeyNavigation.tab: junkPacketCountTextField.textField } @@ -145,7 +124,7 @@ PageType { Layout.topMargin: 16 headerText: qsTr("Jc - Junk packet count") - textFieldText: junkPacketCount + textFieldText: serverJunkPacketCount textField.validator: IntValidator { bottom: 0 } parentFlickable: fl @@ -154,8 +133,8 @@ PageType { textFieldText = "0" } - if (textFieldText !== junkPacketCount) { - junkPacketCount = textFieldText + if (textFieldText !== serverJunkPacketCount) { + serverJunkPacketCount = textFieldText } } @@ -170,13 +149,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("Jmin - Junk packet minimum size") - textFieldText: junkPacketMinSize + textFieldText: serverJunkPacketMinSize textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== junkPacketMinSize) { - junkPacketMinSize = textFieldText + if (textFieldText !== serverJunkPacketMinSize) { + serverJunkPacketMinSize = textFieldText } } @@ -191,13 +170,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("Jmax - Junk packet maximum size") - textFieldText: junkPacketMaxSize + textFieldText: serverJunkPacketMaxSize textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== junkPacketMaxSize) { - junkPacketMaxSize = textFieldText + if (textFieldText !== serverJunkPacketMaxSize) { + serverJunkPacketMaxSize = textFieldText } } @@ -212,13 +191,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("S1 - Init packet junk size") - textFieldText: initPacketJunkSize + textFieldText: serverInitPacketJunkSize textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== initPacketJunkSize) { - initPacketJunkSize = textFieldText + if (textFieldText !== serverInitPacketJunkSize) { + serverInitPacketJunkSize = textFieldText } } @@ -233,13 +212,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("S2 - Response packet junk size") - textFieldText: responsePacketJunkSize + textFieldText: serverResponsePacketJunkSize textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== responsePacketJunkSize) { - responsePacketJunkSize = textFieldText + if (textFieldText !== serverResponsePacketJunkSize) { + serverResponsePacketJunkSize = textFieldText } } @@ -254,13 +233,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("H1 - Init packet magic header") - textFieldText: initPacketMagicHeader + textFieldText: serverInitPacketMagicHeader textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== initPacketMagicHeader) { - initPacketMagicHeader = textFieldText + if (textFieldText !== serverInitPacketMagicHeader) { + serverInitPacketMagicHeader = textFieldText } } @@ -275,13 +254,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("H2 - Response packet magic header") - textFieldText: responsePacketMagicHeader + textFieldText: serverResponsePacketMagicHeader textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== responsePacketMagicHeader) { - responsePacketMagicHeader = textFieldText + if (textFieldText !== serverResponsePacketMagicHeader) { + serverResponsePacketMagicHeader = textFieldText } } @@ -296,13 +275,13 @@ PageType { Layout.topMargin: 16 headerText: qsTr("H4 - Transport packet magic header") - textFieldText: transportPacketMagicHeader + textFieldText: serverTransportPacketMagicHeader textField.validator: IntValidator { bottom: 0 } parentFlickable: fl textField.onEditingFinished: { - if (textFieldText !== transportPacketMagicHeader) { - transportPacketMagicHeader = textFieldText + if (textFieldText !== serverTransportPacketMagicHeader) { + serverTransportPacketMagicHeader = textFieldText } } @@ -318,12 +297,12 @@ PageType { parentFlickable: fl headerText: qsTr("H3 - Underload packet magic header") - textFieldText: underloadPacketMagicHeader + textFieldText: serverUnderloadPacketMagicHeader textField.validator: IntValidator { bottom: 0 } textField.onEditingFinished: { - if (textFieldText !== underloadPacketMagicHeader) { - underloadPacketMagicHeader = textFieldText + if (textFieldText !== serverUnderloadPacketMagicHeader) { + serverUnderloadPacketMagicHeader = textFieldText } } @@ -356,18 +335,22 @@ PageType { Keys.onTabPressed: lastItemTabClicked(focusItem) clickedFunc: function() { - if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text, - transportPacketMagicHeaderTextField.textField.text, - responsePacketMagicHeaderTextField.textField.text, - initPacketMagicHeaderTextField.textField.text)) { - PageController.showErrorMessage(qsTr("The values of the H1-H4 fields must be unique")) - return - } + forceActiveFocus() - if (AwgConfigModel.isPacketSizeEqual(parseInt(initPacketJunkSizeTextField.textField.text), - parseInt(responsePacketJunkSizeTextField.textField.text))) { - PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)")) - return + if (delegateItem.isEnabled) { + if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text, + transportPacketMagicHeaderTextField.textField.text, + responsePacketMagicHeaderTextField.textField.text, + initPacketMagicHeaderTextField.textField.text)) { + PageController.showErrorMessage(qsTr("The values of the H1-H4 fields must be unique")) + return + } + + if (AwgConfigModel.isPacketSizeEqual(parseInt(initPacketJunkSizeTextField.textField.text), + parseInt(responsePacketJunkSizeTextField.textField.text))) { + PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)")) + return + } } var headerText = qsTr("Save settings?") @@ -376,8 +359,6 @@ PageType { var noButtonText = qsTr("Cancel") var yesButtonFunction = function() { - forceActiveFocus() - if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) return diff --git a/client/ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml b/client/ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml new file mode 100644 index 00000000..007de5ca --- /dev/null +++ b/client/ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml @@ -0,0 +1,179 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import SortFilterProxyModel 0.2 + +import PageEnum 1.0 + +import "./" +import "../Controls2" +import "../Controls2/TextTypes" +import "../Config" +import "../Components" + + +PageType { + id: root + + defaultActiveFocusItem: listview.currentItem.mtuTextField.textField + + Item { + id: focusItem + onFocusChanged: { + if (activeFocus) { + fl.ensureVisible(focusItem) + } + } + KeyNavigation.tab: backButton + } + + ColumnLayout { + id: backButtonLayout + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + anchors.topMargin: 20 + + BackButtonType { + id: backButton + KeyNavigation.tab: listview.currentItem.mtuTextField.textField + } + } + + FlickableType { + id: fl + anchors.top: backButtonLayout.bottom + anchors.bottom: parent.bottom + contentHeight: content.implicitHeight + saveButton.implicitHeight + saveButton.anchors.bottomMargin + saveButton.anchors.topMargin + + Column { + id: content + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + ListView { + id: listview + + width: parent.width + height: listview.contentItem.height + + clip: true + interactive: false + + model: WireGuardConfigModel + + delegate: Item { + id: delegateItem + implicitWidth: listview.width + implicitHeight: col.implicitHeight + + property alias mtuTextField: mtuTextField + property bool isSaveButtonEnabled: mtuTextField.errorText === "" + + ColumnLayout { + id: col + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + anchors.leftMargin: 16 + anchors.rightMargin: 16 + + spacing: 0 + + HeaderType { + Layout.fillWidth: true + + headerText: qsTr("WG settings") + } + + TextFieldWithHeaderType { + id: mtuTextField + Layout.fillWidth: true + Layout.topMargin: 40 + + headerText: qsTr("MTU") + textFieldText: clientMtu + textField.validator: IntValidator { bottom: 576; top: 65535 } + + textField.onEditingFinished: { + if (textFieldText !== clientMtu) { + clientMtu = textFieldText + } + } + checkEmptyText: true + KeyNavigation.tab: saveButton + } + + Header2TextType { + Layout.fillWidth: true + Layout.topMargin: 16 + + text: qsTr("Server settings") + } + + TextFieldWithHeaderType { + id: portTextField + Layout.fillWidth: true + Layout.topMargin: 8 + + enabled: false + + headerText: qsTr("Port") + textFieldText: port + } + } + } + } + } + } + + BasicButtonType { + id: saveButton + + anchors.right: root.right + anchors.left: root.left + anchors.bottom: root.bottom + + anchors.topMargin: 24 + anchors.bottomMargin: 24 + anchors.rightMargin: 16 + anchors.leftMargin: 16 + + enabled: listview.currentItem.isSaveButtonEnabled + + text: qsTr("Save") + + Keys.onTabPressed: lastItemTabClicked(focusItem) + + clickedFunc: function() { + forceActiveFocus() + var headerText = qsTr("Save settings?") + var descriptionText = qsTr("Only the settings for this device will be changed") + var yesButtonText = qsTr("Continue") + var noButtonText = qsTr("Cancel") + + var yesButtonFunction = function() { + if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { + PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) + return + } + + PageController.goToPage(PageEnum.PageSetupWizardInstalling); + InstallController.updateContainer(WireGuardConfigModel.getConfig()) + } + var noButtonFunction = function() { + if (!GC.isMobile()) { + saveButton.forceActiveFocus() + } + } + showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) + } + } +} diff --git a/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml b/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml index 758375b1..b5d08132 100644 --- a/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml @@ -72,7 +72,10 @@ PageType { } delegate: Item { + id: delegateItem + property alias focusItemId: portTextField.textField + property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess() implicitWidth: listview.width implicitHeight: col.implicitHeight @@ -99,12 +102,14 @@ PageType { Layout.fillWidth: true Layout.topMargin: 40 + enabled: delegateItem.isEnabled + headerText: qsTr("Port") textFieldText: port textField.maximumLength: 5 textField.validator: IntValidator { bottom: 1; top: 65535 } - KeyNavigation.tab: mtuTextField.textField + KeyNavigation.tab: saveButton textField.onEditingFinished: { if (textFieldText !== port) { @@ -115,52 +120,41 @@ PageType { checkEmptyText: true } - TextFieldWithHeaderType { - id: mtuTextField - Layout.fillWidth: true - Layout.topMargin: 16 - - headerText: qsTr("MTU") - textFieldText: mtu - textField.validator: IntValidator { bottom: 576; top: 65535 } - - KeyNavigation.tab: saveButton - - textField.onEditingFinished: { - if (textFieldText === "") { - textFieldText = "0" - } - if (textFieldText !== mtu) { - mtu = textFieldText - } - } - checkEmptyText: true - } - BasicButtonType { id: saveButton Layout.fillWidth: true Layout.topMargin: 24 Layout.bottomMargin: 24 - enabled: mtuTextField.errorText === "" && - portTextField.errorText === "" + enabled: portTextField.errorText === "" text: qsTr("Save") Keys.onTabPressed: lastItemTabClicked(focusItem) - onClicked: { + onClicked: function() { forceActiveFocus() - if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { - PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) - return - } + var headerText = qsTr("Save settings?") + var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.") + var yesButtonText = qsTr("Continue") + var noButtonText = qsTr("Cancel") - PageController.goToPage(PageEnum.PageSetupWizardInstalling); - InstallController.updateContainer(WireGuardConfigModel.getConfig()) - focusItem.forceActiveFocus() + var yesButtonFunction = function() { + if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) { + PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection")) + return + } + + PageController.goToPage(PageEnum.PageSetupWizardInstalling); + InstallController.updateContainer(WireGuardConfigModel.getConfig()) + } + var noButtonFunction = function() { + if (!GC.isMobile()) { + saveRestartButton.forceActiveFocus() + } + } + showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) } Keys.onEnterPressed: saveButton.clicked() diff --git a/client/ui/qml/Pages2/PageSettingsServerProtocol.qml b/client/ui/qml/Pages2/PageSettingsServerProtocol.qml index 6410156d..dcdf01af 100644 --- a/client/ui/qml/Pages2/PageSettingsServerProtocol.qml +++ b/client/ui/qml/Pages2/PageSettingsServerProtocol.qml @@ -79,7 +79,7 @@ PageType { } delegate: Item { - property var focusItem: button.rightButton + property var focusItem: clientSettings.rightButton implicitWidth: protocols.width implicitHeight: delegateContent.implicitHeight @@ -89,13 +89,49 @@ PageType { anchors.fill: parent + property bool isClientSettingsVisible: protocolIndex === ProtocolEnum.WireGuard || protocolIndex === ProtocolEnum.Awg + property bool isServerSettingsVisible: ServersModel.isProcessedServerHasWriteAccess() + LabelWithButtonType { - id: button + id: clientSettings Layout.fillWidth: true - text: protocolName + text: protocolName + qsTr(" connection settings") rightImageSource: "qrc:/images/controls/chevron-right.svg" + visible: delegateContent.isClientSettingsVisible + + clickedFunction: function() { + if (isClientProtocolExists) { + switch (protocolIndex) { + case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break; + case ProtocolEnum.Awg: AwgConfigModel.updateModel(ProtocolsModel.getConfig()); break; + } + PageController.goToPage(clientProtocolPage); + } else { + PageController.showNotificationMessage(qsTr("Click the \"connect\" button to create a connection configuration")) + } + } + + MouseArea { + anchors.fill: clientSettings + cursorShape: Qt.PointingHandCursor + enabled: false + } + } + + DividerType { + visible: delegateContent.isClientSettingsVisible + } + + LabelWithButtonType { + id: serverSettings + + Layout.fillWidth: true + + text: protocolName + qsTr(" server settings") + rightImageSource: "qrc:/images/controls/chevron-right.svg" + visible: delegateContent.isServerSettingsVisible clickedFunction: function() { switch (protocolIndex) { @@ -109,17 +145,19 @@ PageType { case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break; case ProtocolEnum.Socks5Proxy: Socks5ProxyConfigModel.updateModel(ProtocolsModel.getConfig()); break; } - PageController.goToPage(protocolPage); + PageController.goToPage(serverProtocolPage); } MouseArea { - anchors.fill: button + anchors.fill: serverSettings cursorShape: Qt.PointingHandCursor enabled: false } } - DividerType {} + DividerType { + visible: delegateContent.isServerSettingsVisible + } } } } @@ -132,11 +170,11 @@ PageType { visible: root.isClearCacheVisible KeyNavigation.tab: removeButton - text: qsTr("Clear %1 profile").arg(ContainersModel.getProcessedContainerName()) + text: qsTr("Clear profile") clickedFunction: function() { var headerText = qsTr("Clear %1 profile?").arg(ContainersModel.getProcessedContainerName()) - var descriptionText = qsTr("") + var descriptionText = qsTr("The connection configuration will be deleted for this device only") var yesButtonText = qsTr("Continue") var noButtonText = qsTr("Cancel") @@ -183,7 +221,7 @@ PageType { visible: ServersModel.isProcessedServerHasWriteAccess() Keys.onTabPressed: lastItemTabClicked(focusItem) - text: qsTr("Remove ") + ContainersModel.getProcessedContainerName() + text: qsTr("Remove ") textColor: AmneziaStyle.color.vibrantRed clickedFunction: function() {