Compare commits

..

32 Commits

Author SHA1 Message Date
vladimir.kuznetsov
12206cdb52 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/graphview 2024-05-15 12:31:21 +02:00
vladimir.kuznetsov
93aebf5256 enabled drag for graphview area 2024-04-08 21:31:24 +05:00
vladimir.kuznetsov
502e815a9f Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/graphview 2024-04-08 21:30:44 +05:00
vladimir.kuznetsov
8bc69bdc62 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/graphview 2024-04-08 18:52:05 +05:00
vladimir.kuznetsov
b3ae687feb repositioned the graphview 2024-04-01 18:54:42 +05:00
vladimir.kuznetsov
d6d11d6e60 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/graphview 2024-04-01 17:52:08 +05:00
vladimir.kuznetsov
b90bf16945 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/graphview 2024-03-31 15:05:14 +05:00
albexk
b162147a89 Fix app launch on Android, uncomment statistics processing 2024-03-04 15:17:28 +03:00
Nethius
faaf5973b4 Merge pull request #603 from amnezia-vpn/feature/graphview-ios
Feature/graphview (iOS)
2024-02-27 17:23:09 +07:00
vladimir.kuznetsov
aa4bfc70b9 Merge branch 'feature/graphview' of github.com:amnezia-vpn/amnezia-client into feature/graphview-ios 2024-02-27 15:22:06 +05:00
vladimir.kuznetsov
ef674d1e4f add charts to the list of packages for all platforms 2024-02-27 14:53:09 +05:00
Mykola Baibuz
23633e8fa7 Statistic for WG/AWG protocol 2024-02-23 20:31:59 +02:00
agalehaga
3cc846678e merge 2024-02-23 19:15:40 +02:00
agalehaga
84e8667e57 merge 2024-02-19 21:42:27 +02:00
agalehaga
b500a1f09d update translations 2024-02-19 21:38:43 +02:00
agalehaga
2399d45bab fixed can't find Qt6::Charts 2024-02-18 15:10:20 +02:00
agalehaga
77e82fbf40 Merge branch 'feature/graphview' of github.com:amnezia-vpn/amnezia-client into feature/graphview 2024-02-18 12:28:35 +02:00
agalehaga
a6467dd0f0 merge dev 2024-02-18 12:28:02 +02:00
Igor Sorokin
2e11cc56ab Fix chart rendering (wrong SplineSeries.style) 2024-02-17 19:55:14 +03:00
Igor Sorokin
c2d204b362 Merge remote-tracking branch 'refs/remotes/origin/feature/graphview' into feature/graphview 2024-02-14 19:18:52 +03:00
Igor Sorokin
77a83e4fc3 Additional setup for Qt Charts 2024-02-14 17:52:30 +03:00
agalehaga
8617896c7a Merge branch 'dev' into feature/graphview 2024-02-14 13:36:22 +02:00
agalehaga
97c6b217f2 refactoring: changed SystemController.hasFocus to SystemController.appHasFocus 2024-02-14 13:34:35 +02:00
agalehaga
efde0c99a3 Merge branch 'dev' into feature/graphview 2024-02-13 18:46:56 +02:00
agalehaga
2dccfce468 merge 2024-02-12 10:33:33 +02:00
pokamest
eaa603684c Merge branch 'dev' into feature/graphview 2024-02-02 13:24:11 +00:00
pokamest
7ef41bfe75 GraphViewType fixes 2024-01-30 10:02:48 +00:00
pokamest
e5c25e8a0c Merge branch 'dev' into feature/graphview 2024-01-29 23:16:54 +00:00
Victor Corchez
c9af9f34fc fixed CPU consumption and added graph values persistence 2024-01-28 15:50:37 +02:00
Victor Corchez
acfe19b914 cleanup 2024-01-25 14:08:43 +02:00
Victor Corchez
81242b405f Update deploy.yml 2024-01-25 09:00:32 +02:00
Victor Corchez
61092259ba Implemented graphview for down/up traffic 2024-01-24 07:34:40 +02:00
58 changed files with 623 additions and 525 deletions

View File

@@ -25,7 +25,7 @@ jobs:
host: 'linux'
target: 'desktop'
arch: 'gcc_64'
modules: 'qtremoteobjects qt5compat qtshadertools'
modules: 'qtremoteobjects qt5compat qtshadertools qtcharts'
dir: ${{ runner.temp }}
setup-python: 'true'
tools: 'tools_ifw'
@@ -93,7 +93,7 @@ jobs:
host: 'windows'
target: 'desktop'
arch: 'win64_msvc2019_64'
modules: 'qtremoteobjects qt5compat qtshadertools'
modules: 'qtremoteobjects qt5compat qtshadertools qtcharts'
dir: ${{ runner.temp }}
setup-python: 'true'
tools: 'tools_ifw'
@@ -150,7 +150,7 @@ jobs:
version: ${{ env.QT_VERSION }}
host: 'mac'
target: 'desktop'
modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia'
modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia qtcharts'
arch: 'clang_64'
dir: ${{ runner.temp }}
set-env: 'true'
@@ -162,7 +162,7 @@ jobs:
version: ${{ env.QT_VERSION }}
host: 'mac'
target: 'ios'
modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia'
modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia qtcharts'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
@@ -242,7 +242,7 @@ jobs:
host: 'mac'
target: 'desktop'
arch: 'clang_64'
modules: 'qtremoteobjects qt5compat qtshadertools'
modules: 'qtremoteobjects qt5compat qtshadertools qtcharts'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
@@ -292,7 +292,7 @@ jobs:
env:
ANDROID_BUILD_PLATFORM: android-34
QT_VERSION: 6.6.2
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools qtcharts'
steps:
- name: 'Install desktop Qt'

View File

@@ -58,6 +58,7 @@ Check deploy folder for build scripts.
- Qt 5 Compatibility Module
- Qt Shader Tools
- Additional Libraries:
- Qt Charts
- Qt Image Formats
- Qt Multimedia
- Qt Remote Objects

View File

@@ -12,7 +12,7 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "Autogen")
set(PACKAGES
Core Gui Network Xml
RemoteObjects Quick Svg QuickControls2
Core5Compat Concurrent LinguistTools
Core5Compat Concurrent LinguistTools Charts
)
execute_process(
@@ -38,7 +38,7 @@ set(LIBS ${LIBS}
Qt6::Core Qt6::Gui
Qt6::Network Qt6::Xml Qt6::RemoteObjects
Qt6::Quick Qt6::Svg Qt6::QuickControls2
Qt6::Core5Compat Qt6::Concurrent
Qt6::Core5Compat Qt6::Concurrent Qt6::Charts
)
if(IOS)
@@ -151,6 +151,7 @@ include_directories(mozilla/models)
if(NOT IOS)
set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/platforms/ios/MobileUtils.h
${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QRCodeReaderBase.h
)
endif()
@@ -192,6 +193,7 @@ endif()
if(NOT IOS)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/platforms/ios/MobileUtils.cpp
${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QRCodeReaderBase.cpp
)
endif()

View File

@@ -55,7 +55,6 @@ AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecond
#endif
m_settings = std::shared_ptr<Settings>(new Settings);
m_nam = new QNetworkAccessManager(this);
}
AmneziaApplication::~AmneziaApplication()
@@ -151,7 +150,7 @@ void AmneziaApplication::init()
connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(), &PageController::raiseMainWindow);
connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
static_cast<void (ConnectionController::*)()>(&ConnectionController::openConnection));
&ConnectionController::openConnection);
connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
&ConnectionController::closeConnection);
connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated);
@@ -196,8 +195,8 @@ void AmneziaApplication::init()
// /qt/6.6.1/Src/qtbase/src/plugins/platforms/android/androidjniclipboard.cpp:46
// So we catch all the copies to the clipboard and clear them from "text/html"
#ifdef Q_OS_ANDROID
connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, []() {
auto clipboard = QGuiApplication::clipboard();
connect(QApplication::clipboard(), &QClipboard::dataChanged, []() {
auto clipboard = QApplication::clipboard();
if (clipboard->mimeData()->hasHtml()) {
clipboard->setText(clipboard->text());
}
@@ -363,22 +362,16 @@ void AmneziaApplication::initControllers()
new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, m_vpnConnection, m_settings));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
connect(m_connectionController.get(), qOverload<const QString &>(&ConnectionController::connectionErrorOccurred), this, [this](const QString &errorMessage) {
connect(m_connectionController.get(), &ConnectionController::connectionErrorOccurred, this, [this](const QString &errorMessage) {
emit m_pageController->showErrorMessage(errorMessage);
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
});
connect(m_connectionController.get(), qOverload<ErrorCode>(&ConnectionController::connectionErrorOccurred), this, [this](ErrorCode errorCode) {
emit m_pageController->showErrorMessage(errorCode);
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
});
connect(m_connectionController.get(), &ConnectionController::connectButtonClicked, m_connectionController.get(),
&ConnectionController::toggleConnection, Qt::QueuedConnection);
connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated);
m_pageController.reset(new PageController(m_serversModel, m_settings, m_languageModel));
m_pageController.reset(new PageController(m_serversModel, m_settings));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_clientManagementModel, m_settings));

View File

@@ -2,15 +2,10 @@
#define AMNEZIA_APPLICATION_H
#include <QCommandLineParser>
#include <QNetworkAccessManager>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QThread>
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include <QApplication>
#include "settings.h"
#include "vpnconnection.h"
@@ -48,7 +43,7 @@
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#define AMNEZIA_BASE_CLASS QGuiApplication
#define AMNEZIA_BASE_CLASS QApplication
#else
#define AMNEZIA_BASE_CLASS SingleApplication
#define QAPPLICATION_CLASS QApplication
@@ -76,7 +71,6 @@ public:
bool parseCommands();
QQmlApplicationEngine *qmlEngine() const;
QNetworkAccessManager *manager() { return m_nam; }
signals:
void translationsUpdated();
@@ -130,8 +124,6 @@ private:
QScopedPointer<SitesController> m_sitesController;
QScopedPointer<SystemController> m_systemController;
QScopedPointer<AppSplitTunnelingController> m_appSplitTunnelingController;
QNetworkAccessManager *m_nam;
};
#endif // AMNEZIA_APPLICATION_H

View File

@@ -72,7 +72,7 @@ class AmneziaActivity : QtActivity() {
object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
val event = msg.extractIpcMessage<ServiceEvent>()
Log.d(TAG, "Handle event: $event")
if (event != ServiceEvent.STATISTICS_UPDATE) Log.d(TAG, "Handle event: $event")
when (event) {
ServiceEvent.STATUS_CHANGED -> {
msg.data?.getStatus()?.let { (state) ->

View File

@@ -46,6 +46,7 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/iosglue.mm
${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/QRCodeReaderBase.mm
${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/QtAppDelegate.mm
${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/MobileUtils.mm
)

View File

@@ -5,9 +5,7 @@
#include <QNetworkReply>
#include <QtConcurrent>
#include "amnezia_application.h"
#include "configurators/wireguard_configurator.h"
#include "version.h"
namespace
{
@@ -21,10 +19,7 @@ namespace
constexpr char certificate[] = "certificate";
constexpr char publicKey[] = "public_key";
constexpr char protocol[] = "protocol";
constexpr char uuid[] = "installation_uuid";
constexpr char osVersion[] = "os_version";
constexpr char appVersion[] = "app_version";
}
}
@@ -32,7 +27,8 @@ ApiController::ApiController(QObject *parent) : QObject(parent)
{
}
void ApiController::processApiConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, QString &config)
void ApiController::processApiConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData,
QString &config)
{
if (protocol == configKey::cloak) {
config.replace("<key>", "<key>\n");
@@ -65,52 +61,53 @@ QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiCont
} else if (protocol == configKey::awg) {
obj[configKey::publicKey] = apiPayloadData.wireGuardClientPubKey;
}
obj[configKey::osVersion] = QSysInfo::productType();
obj[configKey::appVersion] = QString(APP_VERSION);
return obj;
}
void ApiController::updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig)
ErrorCode ApiController::updateServerConfigFromApi(const QString &installationUuid, QJsonObject &serverConfig)
{
#ifdef Q_OS_IOS
IosController::Instance()->requestInetAccess();
QThread::msleep(10);
#endif
QFutureWatcher<ErrorCode> watcher;
auto containerConfig = serverConfig.value(config_key::containers).toArray();
QFuture<ErrorCode> future = QtConcurrent::run([this, &serverConfig, &installationUuid]() {
auto containerConfig = serverConfig.value(config_key::containers).toArray();
if (serverConfig.value(config_key::configVersion).toInt()) {
QNetworkRequest request;
request.setTransferTimeout(7000);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8());
QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString();
request.setUrl(endpoint);
if (serverConfig.value(config_key::configVersion).toInt()) {
QNetworkAccessManager manager;
QString protocol = serverConfig.value(configKey::protocol).toString();
QNetworkRequest request;
request.setTransferTimeout(7000);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization",
"Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8());
QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString();
request.setUrl(endpoint);
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
QString protocol = serverConfig.value(configKey::protocol).toString();
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
apiPayload[configKey::uuid] = installationUuid;
auto apiPayloadData = generateApiPayloadData(protocol);
QByteArray requestBody = QJsonDocument(apiPayload).toJson();
auto apiPayload = fillApiPayload(protocol, apiPayloadData);
apiPayload[configKey::uuid] = installationUuid;
QNetworkReply *reply = amnApp->manager()->post(request, requestBody); // ??
QByteArray requestBody = QJsonDocument(apiPayload).toJson();
QScopedPointer<QNetworkReply> reply;
reply.reset(manager.post(request, requestBody));
QEventLoop wait;
QObject::connect(reply.get(), &QNetworkReply::finished, &wait, &QEventLoop::quit);
wait.exec();
QObject::connect(reply, &QNetworkReply::finished, [this, reply, protocol, apiPayloadData, serverIndex, serverConfig]() mutable {
if (reply->error() == QNetworkReply::NoError) {
QString contents = QString::fromUtf8(reply->readAll());
QString data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString();
auto data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString();
data.replace("vpn://", "");
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
QByteArray ba = QByteArray::fromBase64(data.toUtf8(),
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
if (ba.isEmpty()) {
emit errorOccurred(ErrorCode::ApiConfigEmptyError);
return;
return ErrorCode::ApiConfigDownloadError;
}
QByteArray ba_uncompressed = qUncompress(ba);
@@ -122,37 +119,30 @@ void ApiController::updateServerConfigFromApi(const QString &installationUuid, c
processApiConfig(protocol, apiPayloadData, configStr);
QJsonObject apiConfig = QJsonDocument::fromJson(configStr.toUtf8()).object();
serverConfig[config_key::dns1] = apiConfig.value(config_key::dns1);
serverConfig[config_key::dns2] = apiConfig.value(config_key::dns2);
serverConfig[config_key::containers] = apiConfig.value(config_key::containers);
serverConfig[config_key::hostName] = apiConfig.value(config_key::hostName);
serverConfig.insert(config_key::dns1, apiConfig.value(config_key::dns1));
serverConfig.insert(config_key::dns2, apiConfig.value(config_key::dns2));
serverConfig.insert(config_key::containers, apiConfig.value(config_key::containers));
serverConfig.insert(config_key::hostName, apiConfig.value(config_key::hostName));
auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString();
serverConfig[config_key::defaultContainer] = defaultContainer;
emit configUpdated(true, serverConfig, serverIndex);
serverConfig.insert(config_key::defaultContainer, defaultContainer);
} else {
if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError
|| reply->error() == QNetworkReply::NetworkError::TimeoutError) {
emit errorOccurred(ErrorCode::ApiConfigTimeoutError);
} else {
QString err = reply->errorString();
qDebug() << QString::fromUtf8(reply->readAll());
qDebug() << reply->error();
qDebug() << err;
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
emit errorOccurred(ErrorCode::ApiConfigDownloadError);
}
QString err = reply->errorString();
qDebug() << QString::fromUtf8(reply->readAll());
qDebug() << reply->error();
qDebug() << err;
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
return ErrorCode::ApiConfigDownloadError;
}
}
return ErrorCode::NoError;
});
reply->deleteLater();
});
QEventLoop wait;
connect(&watcher, &QFutureWatcher<ErrorCode>::finished, &wait, &QEventLoop::quit);
watcher.setFuture(future);
wait.exec();
QObject::connect(reply, &QNetworkReply::errorOccurred,
[this, reply](QNetworkReply::NetworkError error) { qDebug() << reply->errorString() << error; });
connect(reply, &QNetworkReply::sslErrors, [this, reply](const QList<QSslError> &errors) {
qDebug().noquote() << errors;
emit errorOccurred(ErrorCode::ApiConfigSslError);
});
}
return watcher.result();
}

View File

@@ -5,10 +5,6 @@
#include "configurators/openvpn_configurator.h"
#ifdef Q_OS_IOS
#include "platforms/ios/ios_controller.h"
#endif
class ApiController : public QObject
{
Q_OBJECT
@@ -17,15 +13,10 @@ public:
explicit ApiController(QObject *parent = nullptr);
public slots:
void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig);
signals:
void errorOccurred(ErrorCode errorCode);
void configUpdated(const bool updateConfig, const QJsonObject &config, const int serverIndex);
ErrorCode updateServerConfigFromApi(const QString &installationUuid, QJsonObject &serverConfig);
private:
struct ApiPayloadData
{
struct ApiPayloadData {
OpenVpnConfigurator::ConnectionData certRequest;
QString wireGuardClientPrivKey;

View File

@@ -36,11 +36,7 @@ namespace amnezia
}
};
namespace error_code_ns
{
Q_NAMESPACE
// TODO: change to enum class
enum ErrorCode {
enum ErrorCode {
// General error codes
NoError = 0,
UnknownError = 100,
@@ -79,7 +75,7 @@ namespace amnezia
AmneziaServiceConnectionFailed = 603,
ExecutableMissing = 604,
XrayExecutableMissing = 605,
Tun2SockExecutableMissing = 606,
Tun2SockExecutableMissing = 606,
// VPN errors
OpenVpnAdaptersInUseError = 700,
@@ -103,9 +99,6 @@ namespace amnezia
// Api errors
ApiConfigDownloadError = 1100,
ApiConfigAlreadyAdded = 1101,
ApiConfigEmptyError = 1102,
ApiConfigTimeoutError = 1103,
ApiConfigSslError = 1104,
// QFile errors
OpenError = 1200,
@@ -114,11 +107,7 @@ namespace amnezia
UnspecifiedError = 1203,
FatalError = 1204,
AbortError = 1205
};
Q_ENUM_NS(ErrorCode)
}
using ErrorCode = error_code_ns::ErrorCode;
};
} // namespace amnezia

View File

@@ -8,68 +8,65 @@ QString errorString(ErrorCode code) {
switch (code) {
// General error codes
case(ErrorCode::NoError): errorMessage = QObject::tr("No error"); break;
case(ErrorCode::UnknownError): errorMessage = QObject::tr("Unknown Error"); break;
case(ErrorCode::NotImplementedError): errorMessage = QObject::tr("Function not implemented"); break;
case(ErrorCode::AmneziaServiceNotRunning): errorMessage = QObject::tr("Background service is not running"); break;
case(NoError): errorMessage = QObject::tr("No error"); break;
case(UnknownError): errorMessage = QObject::tr("Unknown Error"); break;
case(NotImplementedError): errorMessage = QObject::tr("Function not implemented"); break;
case(AmneziaServiceNotRunning): errorMessage = QObject::tr("Background service is not running"); break;
// Server errors
case(ErrorCode::ServerCheckFailed): errorMessage = QObject::tr("Server check failed"); break;
case(ErrorCode::ServerPortAlreadyAllocatedError): errorMessage = QObject::tr("Server port already used. Check for another software"); break;
case(ErrorCode::ServerContainerMissingError): errorMessage = QObject::tr("Server error: Docker container missing"); break;
case(ErrorCode::ServerDockerFailedError): errorMessage = QObject::tr("Server error: Docker failed"); break;
case(ErrorCode::ServerCancelInstallation): errorMessage = QObject::tr("Installation canceled by user"); break;
case(ErrorCode::ServerUserNotInSudo): errorMessage = QObject::tr("The user does not have permission to use sudo"); break;
case(ErrorCode::ServerPacketManagerError): errorMessage = QObject::tr("Server error: Packet manager error"); break;
case(ServerCheckFailed): errorMessage = QObject::tr("Server check failed"); break;
case(ServerPortAlreadyAllocatedError): errorMessage = QObject::tr("Server port already used. Check for another software"); break;
case(ServerContainerMissingError): errorMessage = QObject::tr("Server error: Docker container missing"); break;
case(ServerDockerFailedError): errorMessage = QObject::tr("Server error: Docker failed"); break;
case(ServerCancelInstallation): errorMessage = QObject::tr("Installation canceled by user"); break;
case(ServerUserNotInSudo): errorMessage = QObject::tr("The user does not have permission to use sudo"); break;
case(ServerPacketManagerError): errorMessage = QObject::tr("Server error: Packet manager error"); break;
// Libssh errors
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("Ssh request was denied"); break;
case(ErrorCode::SshInterruptedError): errorMessage = QObject::tr("Ssh request was interrupted"); break;
case(ErrorCode::SshInternalError): errorMessage = QObject::tr("Ssh internal error"); break;
case(ErrorCode::SshPrivateKeyError): errorMessage = QObject::tr("Invalid private key or invalid passphrase entered"); break;
case(ErrorCode::SshPrivateKeyFormatError): errorMessage = QObject::tr("The selected private key format is not supported, use openssh ED25519 key types or PEM key types"); break;
case(ErrorCode::SshTimeoutError): errorMessage = QObject::tr("Timeout connecting to server"); break;
case(SshRequestDeniedError): errorMessage = QObject::tr("Ssh request was denied"); break;
case(SshInterruptedError): errorMessage = QObject::tr("Ssh request was interrupted"); break;
case(SshInternalError): errorMessage = QObject::tr("Ssh internal error"); break;
case(SshPrivateKeyError): errorMessage = QObject::tr("Invalid private key or invalid passphrase entered"); break;
case(SshPrivateKeyFormatError): errorMessage = QObject::tr("The selected private key format is not supported, use openssh ED25519 key types or PEM key types"); break;
case(SshTimeoutError): errorMessage = QObject::tr("Timeout connecting to server"); break;
// Ssh scp errors
case(ErrorCode::SshScpFailureError): errorMessage = QObject::tr("Scp error: Generic failure"); break;
case(SshScpFailureError): errorMessage = QObject::tr("Scp error: Generic failure"); break;
// Local errors
case (ErrorCode::OpenVpnConfigMissing): errorMessage = QObject::tr("OpenVPN config missing"); break;
case (ErrorCode::OpenVpnManagementServerError): errorMessage = QObject::tr("OpenVPN management server error"); break;
case (OpenVpnConfigMissing): errorMessage = QObject::tr("OpenVPN config missing"); break;
case (OpenVpnManagementServerError): errorMessage = QObject::tr("OpenVPN management server error"); break;
// Distro errors
case (ErrorCode::OpenVpnExecutableMissing): errorMessage = QObject::tr("OpenVPN executable missing"); break;
case (ErrorCode::ShadowSocksExecutableMissing): errorMessage = QObject::tr("ShadowSocks (ss-local) executable missing"); break;
case (ErrorCode::CloakExecutableMissing): errorMessage = QObject::tr("Cloak (ck-client) executable missing"); break;
case (ErrorCode::AmneziaServiceConnectionFailed): errorMessage = QObject::tr("Amnezia helper service error"); break;
case (ErrorCode::OpenSslFailed): errorMessage = QObject::tr("OpenSSL failed"); break;
case (OpenVpnExecutableMissing): errorMessage = QObject::tr("OpenVPN executable missing"); break;
case (ShadowSocksExecutableMissing): errorMessage = QObject::tr("ShadowSocks (ss-local) executable missing"); break;
case (CloakExecutableMissing): errorMessage = QObject::tr("Cloak (ck-client) executable missing"); break;
case (AmneziaServiceConnectionFailed): errorMessage = QObject::tr("Amnezia helper service error"); break;
case (OpenSslFailed): errorMessage = QObject::tr("OpenSSL failed"); break;
// VPN errors
case (ErrorCode::OpenVpnAdaptersInUseError): errorMessage = QObject::tr("Can't connect: another VPN connection is active"); break;
case (ErrorCode::OpenVpnTapAdapterError): errorMessage = QObject::tr("Can't setup OpenVPN TAP network adapter"); break;
case (ErrorCode::AddressPoolError): errorMessage = QObject::tr("VPN pool error: no available addresses"); break;
case (OpenVpnAdaptersInUseError): errorMessage = QObject::tr("Can't connect: another VPN connection is active"); break;
case (OpenVpnTapAdapterError): errorMessage = QObject::tr("Can't setup OpenVPN TAP network adapter"); break;
case (AddressPoolError): errorMessage = QObject::tr("VPN pool error: no available addresses"); break;
case (ErrorCode::ImportInvalidConfigError): errorMessage = QObject::tr("The config does not contain any containers and credentials for connecting to the server"); break;
case (ImportInvalidConfigError): errorMessage = QObject::tr("The config does not contain any containers and credentials for connecting to the server"); break;
// Android errors
case (ErrorCode::AndroidError): errorMessage = QObject::tr("VPN connection error"); break;
case (AndroidError): errorMessage = QObject::tr("VPN connection error"); break;
// Api errors
case (ErrorCode::ApiConfigDownloadError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break;
case (ErrorCode::ApiConfigAlreadyAdded): errorMessage = QObject::tr("This config has already been added to the application"); break;
case (ErrorCode::ApiConfigEmptyError): errorMessage = QObject::tr("In the response from the server, an empty config was received"); break;
case (ErrorCode::ApiConfigSslError): errorMessage = QObject::tr("SSL error occurred"); break;
case (ErrorCode::ApiConfigTimeoutError): errorMessage = QObject::tr("Server response timeout on api request"); break;
// QFile errors
case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break;
case(ErrorCode::ReadError): errorMessage = QObject::tr("QFile error: An error occurred when reading from the file"); break;
case(ErrorCode::PermissionsError): errorMessage = QObject::tr("QFile error: The file could not be accessed"); break;
case(ErrorCode::UnspecifiedError): errorMessage = QObject::tr("QFile error: An unspecified error occurred"); break;
case(ErrorCode::FatalError): errorMessage = QObject::tr("QFile error: A fatal error occurred"); break;
case(ErrorCode::AbortError): errorMessage = QObject::tr("QFile error: The operation was aborted"); break;
case (ApiConfigDownloadError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break;
case (ApiConfigAlreadyAdded): errorMessage = QObject::tr("This config has already been added to the application"); break;
case(ErrorCode::InternalError):
// QFile errors
case(OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break;
case(ReadError): errorMessage = QObject::tr("QFile error: An error occurred when reading from the file"); break;
case(PermissionsError): errorMessage = QObject::tr("QFile error: The file could not be accessed"); break;
case(UnspecifiedError): errorMessage = QObject::tr("QFile error: An unspecified error occurred"); break;
case(FatalError): errorMessage = QObject::tr("QFile error: A fatal error occurred"); break;
case(AbortError): errorMessage = QObject::tr("QFile error: The operation was aborted"); break;
case(InternalError):
default:
errorMessage = QObject::tr("Internal error"); break;
}

View File

@@ -528,7 +528,6 @@ bool Daemon::switchServer(const InterfaceConfig& config) {
QJsonObject Daemon::getStatus() {
Q_ASSERT(wgutils() != nullptr);
QJsonObject json;
logger.debug() << "Status request";
if (!wgutils()->interfaceExists() || m_connections.isEmpty()) {
json.insert("connected", QJsonValue(false));

View File

@@ -46,8 +46,6 @@ DaemonLocalServerConnection::~DaemonLocalServerConnection() {
}
void DaemonLocalServerConnection::readData() {
logger.debug() << "Read Data";
Q_ASSERT(m_socket);
while (true) {
@@ -90,8 +88,6 @@ void DaemonLocalServerConnection::parseCommand(const QByteArray& data) {
}
QString type = typeValue.toString();
logger.debug() << "Command received:" << type;
if (type == "activate") {
InterfaceConfig config;
if (!Daemon::parseConfig(obj, config)) {

View File

@@ -51,13 +51,6 @@
<true/>
<key>NSCameraUsageDescription</key>
<string>Amnezia VPN needs access to the camera for reading QR-codes.</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>

View File

@@ -64,7 +64,6 @@ int main(int argc, char *argv[])
qInfo().noquote() << QString("Started %1 version %2 %3").arg(APPLICATION_NAME, APP_VERSION, GIT_COMMIT_HASH);
qInfo().noquote() << QString("%1 (%2)").arg(QSysInfo::prettyProductName(), QSysInfo::currentCpuArchitecture());
qInfo().noquote() << QString("SSL backend: %1").arg(QSslSocket::sslLibraryVersionString());
return app.exec();
}

View File

@@ -273,8 +273,6 @@ void LocalSocketController::deactivate() {
}
void LocalSocketController::checkStatus() {
logger.debug() << "Check status";
if (m_daemonState == eReady || m_daemonState == eInitializing) {
Q_ASSERT(m_socket);
@@ -324,7 +322,6 @@ void LocalSocketController::cleanupBackendLogs() {
}
void LocalSocketController::readData() {
logger.debug() << "Reading";
Q_ASSERT(m_socket);
Q_ASSERT(m_daemonState == eInitializing || m_daemonState == eReady);
@@ -366,8 +363,6 @@ void LocalSocketController::parseCommand(const QByteArray& command) {
}
QString type = typeValue.toString();
logger.debug() << "Parse command:" << type;
if (m_daemonState == eInitializing && type == "status") {
m_daemonState = eReady;
@@ -393,6 +388,7 @@ void LocalSocketController::parseCommand(const QByteArray& command) {
}
emit initialized(true, connected.toBool(), datetime);
checkStatus();
return;
}

View File

@@ -136,7 +136,7 @@ ErrorCode AndroidController::start(const QJsonObject &vpnConfig)
callActivityMethod("start", "(Ljava/lang/String;)V",
QJniObject::fromString(config).object<jstring>());
return ErrorCode::NoError;
return NoError;
}
void AndroidController::stop()

View File

@@ -0,0 +1,15 @@
#include "MobileUtils.h"
MobileUtils::MobileUtils(QObject *parent) : QObject(parent)
{
}
bool MobileUtils::shareText(const QStringList &)
{
return false;
}
QString MobileUtils::openFile()
{
return QString();
}

View File

@@ -0,0 +1,22 @@
#ifndef MOBILEUTILS_H
#define MOBILEUTILS_H
#include <QObject>
#include <QStringList>
class MobileUtils : public QObject
{
Q_OBJECT
public:
explicit MobileUtils(QObject *parent = nullptr);
public slots:
bool shareText(const QStringList &filesToSend);
QString openFile();
signals:
void finished();
};
#endif // MOBILEUTILS_H

View File

@@ -0,0 +1,109 @@
#include "MobileUtils.h"
#include <UIKit/UIKit.h>
#include <Security/Security.h>
#include <QEventLoop>
static UIViewController* getViewController() {
NSArray *windows = [[UIApplication sharedApplication]windows];
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
return window.rootViewController;
}
}
return nil;
}
MobileUtils::MobileUtils(QObject *parent) : QObject(parent) {
}
bool MobileUtils::shareText(const QStringList& filesToSend) {
NSMutableArray *sharingItems = [NSMutableArray new];
for (int i = 0; i < filesToSend.size(); i++) {
NSURL *logFileUrl = [[NSURL alloc] initFileURLWithPath:filesToSend[i].toNSString()];
[sharingItems addObject:logFileUrl];
}
UIViewController *qtController = getViewController();
if (!qtController) return;
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
__block bool isAccepted = false;
[activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
isAccepted = completed;
emit finished();
}];
[qtController presentViewController:activityController animated:YES completion:nil];
UIPopoverPresentationController *popController = activityController.popoverPresentationController;
if (popController) {
popController.sourceView = qtController.view;
popController.sourceRect = CGRectMake(100, 100, 100, 100);
}
QEventLoop wait;
QObject::connect(this, &MobileUtils::finished, &wait, &QEventLoop::quit);
wait.exec();
return isAccepted;
}
typedef void (^DocumentPickerClosedCallback)(NSString *path);
@interface DocumentPickerDelegate : NSObject <UIDocumentPickerDelegate>
@property (nonatomic, copy) DocumentPickerClosedCallback documentPickerClosedCallback;
@end
@implementation DocumentPickerDelegate
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
for (NSURL *url in urls) {
if (self.documentPickerClosedCallback) {
self.documentPickerClosedCallback([url path]);
}
}
}
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
if (self.documentPickerClosedCallback) {
self.documentPickerClosedCallback(nil);
}
}
@end
QString MobileUtils::openFile() {
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.item"] inMode:UIDocumentPickerModeOpen];
DocumentPickerDelegate *documentPickerDelegate = [[DocumentPickerDelegate alloc] init];
documentPicker.delegate = documentPickerDelegate;
UIViewController *qtController = getViewController();
if (!qtController) return;
[qtController presentViewController:documentPicker animated:YES completion:nil];
__block QString filePath;
documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) {
if (path) {
filePath = QString::fromUtf8(path.UTF8String);
} else {
filePath = QString();
}
emit finished();
};
QEventLoop wait;
QObject::connect(this, &MobileUtils::finished, &wait, &QEventLoop::quit);
wait.exec();
return filePath;
}

View File

@@ -50,19 +50,12 @@ public:
void getBackendLogs(std::function<void(const QString &)> &&callback);
void checkStatus();
bool shareText(const QStringList &filesToSend);
QString openFile();
void requestInetAccess();
signals:
void connectionStateChanged(Vpn::ConnectionState state);
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
void importConfigFromOutside(const QString);
void importBackupFromOutside(const QString);
void finished();
protected slots:
private:

View File

@@ -6,7 +6,6 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QThread>
#include <QEventLoop>
#include "../protocols/vpnprotocol.h"
#import "ios_controller_wrapper.h"
@@ -27,15 +26,6 @@ const char* MessageKey::isOnDemand = "is-on-demand";
const char* MessageKey::SplitTunnelType = "SplitTunnelType";
const char* MessageKey::SplitTunnelSites = "SplitTunnelSites";
static UIViewController* getViewController() {
NSArray *windows = [[UIApplication sharedApplication]windows];
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
return window.rootViewController;
}
}
return nil;
}
Vpn::ConnectionState iosStatusToState(NEVPNStatus status) {
switch (status) {
@@ -713,86 +703,3 @@ void IosController::sendVpnExtensionMessage(NSDictionary* message, std::function
}
}
bool IosController::shareText(const QStringList& filesToSend) {
NSMutableArray *sharingItems = [NSMutableArray new];
for (int i = 0; i < filesToSend.size(); i++) {
NSURL *logFileUrl = [[NSURL alloc] initFileURLWithPath:filesToSend[i].toNSString()];
[sharingItems addObject:logFileUrl];
}
UIViewController *qtController = getViewController();
if (!qtController) return;
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
__block bool isAccepted = false;
[activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
isAccepted = completed;
emit finished();
}];
[qtController presentViewController:activityController animated:YES completion:nil];
UIPopoverPresentationController *popController = activityController.popoverPresentationController;
if (popController) {
popController.sourceView = qtController.view;
popController.sourceRect = CGRectMake(100, 100, 100, 100);
}
QEventLoop wait;
QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit);
wait.exec();
return isAccepted;
}
QString IosController::openFile() {
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.item"] inMode:UIDocumentPickerModeOpen];
DocumentPickerDelegate *documentPickerDelegate = [[DocumentPickerDelegate alloc] init];
documentPicker.delegate = documentPickerDelegate;
UIViewController *qtController = getViewController();
if (!qtController) return;
[qtController presentViewController:documentPicker animated:YES completion:nil];
__block QString filePath;
documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) {
if (path) {
filePath = QString::fromUtf8(path.UTF8String);
} else {
filePath = QString();
}
emit finished();
};
QEventLoop wait;
QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit);
wait.exec();
return filePath;
}
void IosController::requestInetAccess() {
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
if (url) {
qDebug() << "IosController::requestInetAccess URL error";
return;
}
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
qDebug() << "IosController::requestInetAccess error:" << error.localizedDescription;
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
qDebug() << "IosController::requestInetAccess server response:" << httpResponse.statusCode << "\n\n" <<responseBody;
}
}];
[task resume];
}

View File

@@ -1,8 +1,6 @@
#import <NetworkExtension/NetworkExtension.h>
#import <NetworkExtension/NETunnelProviderSession.h>
#import <Foundation/Foundation.h>
#include <UIKit/UIKit.h>
#include <Security/Security.h>
class IosController;
@@ -15,11 +13,3 @@ class IosController;
- (void)vpnConfigurationDidChange:(NSNotification *)notification;
@end
typedef void (^DocumentPickerClosedCallback)(NSString *path);
@interface DocumentPickerDelegate : NSObject <UIDocumentPickerDelegate>
@property (nonatomic, copy) DocumentPickerClosedCallback documentPickerClosedCallback;
@end

View File

@@ -24,22 +24,5 @@
// cppController->vpnStatusDidChange(notification);
}
@end
@implementation DocumentPickerDelegate
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
for (NSURL *url in urls) {
if (self.documentPickerClosedCallback) {
self.documentPickerClosedCallback([url path]);
}
}
}
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
if (self.documentPickerClosedCallback) {
self.documentPickerClosedCallback(nil);
}
}
@end

View File

@@ -20,9 +20,20 @@ WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject *
});
connect(m_impl.get(), &ControllerImpl::disconnected, this,
[this]() { emit connectionStateChanged(Vpn::ConnectionState::Disconnected); });
connect(m_impl.get(), &ControllerImpl::statusUpdated, this,
&WireguardProtocol::statusUpdated);
m_impl->initialize(nullptr, nullptr);
}
void WireguardProtocol::statusUpdated(const QString& serverIpv4Gateway, const QString& deviceIpv4Address,
uint64_t txBytes, uint64_t rxBytes) {
setBytesChanged(rxBytes, txBytes);
QThread::msleep(1000);
m_impl->checkStatus();
}
WireguardProtocol::~WireguardProtocol()
{
WireguardProtocol::stop();

View File

@@ -21,7 +21,8 @@ public:
ErrorCode start() override;
void stop() override;
void statusUpdated(const QString& serverIpv4Gateway, const QString& deviceIpv4Address,
uint64_t txBytes, uint64_t rxBytes);
ErrorCode startMzImpl();
ErrorCode stopMzImpl();

View File

@@ -225,6 +225,7 @@
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
<file>images/controls/close.svg</file>
<file>images/controls/search.svg</file>
<file>ui/qml/Controls2/GraphViewType.qml</file>
<file>server_scripts/xray/configure_container.sh</file>
<file>server_scripts/xray/Dockerfile</file>
<file>server_scripts/xray/run_container.sh</file>

View File

@@ -1,4 +1,5 @@
#include "secure_qsettings.h"
#include "platforms/ios/MobileUtils.h"
#include "QAead.h"
#include "QBlockCipher.h"

View File

@@ -2944,8 +2944,8 @@ For more detailed information, you can
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="115"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>بروتوكول IKEv2 - بروتوكول مستقر حديث, اسرع بقليل من الباقي, يسترجع الاتصال بعد خسارة الاشارة.</translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>بروتوكول IKEv2 - بروتوكول مستقر حديث, اسرع بقليل من الباقي, يسترجع الاتصال بعد خسارة الاشارة. لدية يتمتع بدعم أصلي على أحدث إصدارات Android وiOS.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="118"/>

View File

@@ -2850,8 +2850,8 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="115"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>پروتکل IKEv2 پروتکلی پایدار و مدرن که مقداری سریعتر از سایر پروتکلهاست. بعد از قطع سیگنال دوباره اتصال را بازیابی میکند.</translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>پروتکل IKEv2 پروتکلی پایدار و مدرن که مقداری سریعتر از سایر پروتکلهاست. بعد از قطع سیگنال دوباره اتصال را بازیابی میکند. به صورت پیشفرض بر روی آخرین نسخه دستگاههای اندروید و iOS پیشتیبانی میشود.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="118"/>

View File

@@ -2998,8 +2998,8 @@ For more detailed information, you can
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="124"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>IKEv2 - ि ि , , ि ि ि </translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>IKEv2 - ि ि , , ि ि ि Android iOS .</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="127"/>

View File

@@ -2851,8 +2851,8 @@ IKEv2 သည် လုံခြုံရေး၊ တည်ငြိမ်မှ
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="115"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>IKEv2 - က က signal ကက ကက .</translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>IKEv2 - က က signal ကက ကက . Android iOS က က.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="118"/>

View File

@@ -2997,8 +2997,8 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="121"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>IKEv2 Современный стабильный протокол, немного быстрее других восстанавливает соединение после потери сигнала.</translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>IKEv2 Современный стабильный протокол, немного быстрее других восстанавливает соединение после потери сигнала. Имеет нативную поддержку последних версиий Android и iOS.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="124"/>

View File

@@ -3191,8 +3191,8 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="124"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>IKEv2 сучасний стабільний протокол, трішки швидше за інших відновлює підключення.</translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>IKEv2 сучасний стабільний протокол, трішки швидше за інших відновлює підключення. Підтримується в останніх версіях Android и iOS самими операційними системами.</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="127"/>

View File

@@ -2947,8 +2947,8 @@ For more detailed information, you can
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="124"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>IKEv2 - جدید مستحکم پروٹوکول، دوسروں کے مقابلے میں تھوڑا تیز، سگنل ضائع ہونے کے بعد کنکشن بحال کرتا ہے۔</translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>IKEv2 - جدید مستحکم پروٹوکول، دوسروں کے مقابلے میں تھوڑا تیز، سگنل ضائع ہونے کے بعد کنکشن بحال کرتا ہے۔ اسے اینڈرائیڈ اور آئی او ایس کے تازہ ترین ورژنز پر مقامی حمایت حاصل ہے۔</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="127"/>

View File

@@ -3057,8 +3057,8 @@ WireGuard非常容易被阻挡因为其独特的数据包签名。与一些
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="115"/>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss.</source>
<translation>IKEv2 - </translation>
<source>IKEv2 - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
<translation>IKEv2 - Android iOS最新版原生支持</translation>
</message>
<message>
<location filename="../containers/containers_defs.cpp" line="118"/>

View File

@@ -7,7 +7,10 @@
#endif
#include <QtConcurrent>
#include "core/controllers/apiController.h"
#include "core/controllers/vpnConfigurationController.h"
#include "core/errorstrings.h"
#include "utilities.h"
#include "version.h"
ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &serversModel,
@@ -16,7 +19,6 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
const QSharedPointer<VpnConnection> &vpnConnection, const std::shared_ptr<Settings> &settings,
QObject *parent)
: QObject(parent),
m_apiController(this),
m_serversModel(serversModel),
m_containersModel(containersModel),
m_clientManagementModel(clientManagementModel),
@@ -27,9 +29,22 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
connect(this, &ConnectionController::connectToVpn, m_vpnConnection.get(), &VpnConnection::connectToVpn, Qt::QueuedConnection);
connect(this, &ConnectionController::disconnectFromVpn, m_vpnConnection.get(), &VpnConnection::disconnectFromVpn, Qt::QueuedConnection);
connect(&m_apiController, &ApiController::configUpdated, this,
static_cast<void (ConnectionController::*)(const bool, const QJsonObject &, const int)>(&ConnectionController::openConnection));
connect(&m_apiController, qOverload<ErrorCode>(&ApiController::errorOccurred), this, qOverload<ErrorCode>(&ConnectionController::connectionErrorOccurred));
connect(m_vpnConnection.get(), &VpnConnection::bytesChanged, this, [this](quint64 rx, quint64 tx) {
m_rxBytes = rx;
m_txBytes = tx;
});
connect(&m_tick, &QTimer::timeout, this, [this]() {
quint64 time = QDateTime::currentSecsSinceEpoch();
if (m_times.length() > viewSize) {
m_times.removeFirst();
m_rxView.removeFirst();
m_txView.removeFirst();
}
m_times.append(time);
m_rxView.append(m_rxBytes);
m_txView.append(m_txBytes);
emit bytesChanged();
});
m_state = Vpn::ConnectionState::Disconnected;
}
@@ -37,24 +52,71 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
void ConnectionController::openConnection()
{
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true))
{
emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning);
if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true)) {
emit connectionErrorOccurred(errorString(ErrorCode::AmneziaServiceNotRunning));
return;
}
#endif
int serverIndex = m_serversModel->getDefaultServerIndex();
QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex);
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
ErrorCode errorCode = ErrorCode::NoError;
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Preparing);
if (serverConfig.value(config_key::configVersion).toInt()
&& !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
m_apiController.updateServerConfigFromApi(m_settings->getInstallationUuid(true), serverIndex, serverConfig);
} else {
openConnection(false, serverConfig, serverIndex);
ApiController apiController;
errorCode = apiController.updateServerConfigFromApi(m_settings->getInstallationUuid(true), serverConfig);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorString(errorCode));
return;
}
m_serversModel->editServer(serverConfig, serverIndex);
}
if (!m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
emit noInstalledContainers();
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
return;
}
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
if (!m_containersModel->isSupportedByCurrentPlatform(container)) {
emit connectionErrorOccurred(tr("The selected protocol is not supported on the current platform"));
return;
}
if (container == DockerContainer::None) {
emit connectionErrorOccurred(tr("VPN Protocols is not installed.\n Please install VPN container at first"));
return;
}
qApp->processEvents();
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
errorCode = updateProtocolConfig(container, credentials, containerConfig, serverController);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorString(errorCode));
return;
}
auto dns = m_serversModel->getDnsPair(serverIndex);
serverConfig = m_serversModel->getServerConfig(serverIndex);
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns, serverConfig, containerConfig, container, errorCode);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(tr("unable to create configuration"));
return;
}
emit connectToVpn(serverIndex, credentials, container, vpnConfiguration);
}
void ConnectionController::closeConnection()
@@ -62,9 +124,9 @@ void ConnectionController::closeConnection()
emit disconnectFromVpn();
}
ErrorCode ConnectionController::getLastConnectionError()
QString ConnectionController::getLastConnectionError()
{
return m_vpnConnection->lastError();
return errorString(m_vpnConnection->lastError());
}
void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
@@ -78,6 +140,7 @@ void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
m_isConnectionInProgress = false;
m_isConnected = true;
m_connectionStateText = tr("Connected");
m_tick.start(1000);
break;
}
case Vpn::ConnectionState::Connecting: {
@@ -97,6 +160,7 @@ void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
case Vpn::ConnectionState::Disconnecting: {
m_isConnectionInProgress = true;
m_connectionStateText = tr("Disconnecting...");
m_tick.stop();
break;
}
case Vpn::ConnectionState::Preparing: {
@@ -146,6 +210,30 @@ QString ConnectionController::connectionStateText() const
return m_connectionStateText;
}
quint64 ConnectionController::rxBytes() const
{
return m_rxBytes;
}
quint64 ConnectionController::txBytes() const
{
return m_txBytes;
}
QVector<quint64> ConnectionController::getRxView() const
{
return m_rxView;
}
QVector<quint64> ConnectionController::getTxView() const
{
return m_txView;
}
QVector<quint64> ConnectionController::getTimes() const
{
return m_times;
}
void ConnectionController::toggleConnection()
{
if (m_state == Vpn::ConnectionState::Preparing) {
@@ -185,53 +273,6 @@ bool ConnectionController::isProtocolConfigExists(const QJsonObject &containerCo
return true;
}
void ConnectionController::openConnection(const bool updateConfig, const QJsonObject &config, const int serverIndex)
{
// Update config for this server as it was received from API
if (updateConfig) {
m_serversModel->editServer(config, serverIndex);
}
if (!m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
emit noInstalledContainers();
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
return;
}
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
if (!m_containersModel->isSupportedByCurrentPlatform(container)) {
emit connectionErrorOccurred(tr("The selected protocol is not supported on the current platform"));
return;
}
if (container == DockerContainer::None) {
emit connectionErrorOccurred(tr("VPN Protocols is not installed.\n Please install VPN container at first"));
return;
}
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
VpnConfigurationsController vpnConfigurationController(m_settings, serverController);
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
ErrorCode errorCode = updateProtocolConfig(container, credentials, containerConfig, serverController);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(errorCode);
return;
}
auto dns = m_serversModel->getDnsPair(serverIndex);
auto vpnConfiguration = vpnConfigurationController.createVpnConfiguration(dns, config, containerConfig, container, errorCode);
if (errorCode != ErrorCode::NoError) {
emit connectionErrorOccurred(tr("unable to create configuration"));
return;
}
emit connectToVpn(serverIndex, credentials, container, vpnConfiguration);
}
ErrorCode ConnectionController::updateProtocolConfig(const DockerContainer container, const ServerCredentials &credentials,
QJsonObject &containerConfig, QSharedPointer<ServerController> serverController)
{

View File

@@ -1,7 +1,6 @@
#ifndef CONNECTIONCONTROLLER_H
#define CONNECTIONCONTROLLER_H
#include "core/controllers/apiController.h"
#include "protocols/vpnprotocol.h"
#include "ui/models/clientManagementModel.h"
#include "ui/models/containers_model.h"
@@ -16,6 +15,8 @@ public:
Q_PROPERTY(bool isConnected READ isConnected NOTIFY connectionStateChanged)
Q_PROPERTY(bool isConnectionInProgress READ isConnectionInProgress NOTIFY connectionStateChanged)
Q_PROPERTY(QString connectionStateText READ connectionStateText NOTIFY connectionStateChanged)
Q_PROPERTY(quint64 rxBytes READ rxBytes NOTIFY bytesChanged)
Q_PROPERTY(quint64 txBytes READ txBytes NOTIFY bytesChanged)
explicit ConnectionController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
const QSharedPointer<ClientManagementModel> &clientManagementModel,
@@ -27,6 +28,12 @@ public:
bool isConnected() const;
bool isConnectionInProgress() const;
QString connectionStateText() const;
quint64 rxBytes() const;
quint64 txBytes() const;
Q_INVOKABLE QVector<quint64> getRxView() const;
Q_INVOKABLE QVector<quint64> getTxView() const;
Q_INVOKABLE QVector<quint64> getTimes() const;
public slots:
void toggleConnection();
@@ -34,7 +41,7 @@ public slots:
void openConnection();
void closeConnection();
ErrorCode getLastConnectionError();
QString getLastConnectionError();
void onConnectionStateChanged(Vpn::ConnectionState state);
void onCurrentContainerUpdated();
@@ -50,8 +57,8 @@ signals:
void connectionStateChanged();
void connectionErrorOccurred(const QString &errorMessage);
void connectionErrorOccurred(ErrorCode errorCode);
void reconnectWithUpdatedContainer(const QString &message);
void bytesChanged();
void noInstalledContainers();
@@ -62,10 +69,6 @@ private:
Vpn::ConnectionState getCurrentConnectionState();
bool isProtocolConfigExists(const QJsonObject &containerConfig, const DockerContainer container);
void openConnection(const bool updateConfig, const QJsonObject &config, const int serverIndex);
ApiController m_apiController;
QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<ContainersModel> m_containersModel;
QSharedPointer<ClientManagementModel> m_clientManagementModel;
@@ -77,8 +80,17 @@ private:
bool m_isConnected = false;
bool m_isConnectionInProgress = false;
QString m_connectionStateText = tr("Connect");
quint64 m_rxBytes = 0;
quint64 m_txBytes = 0;
QVector<quint64> m_rxView{};
QVector<quint64> m_txView{};
QVector<quint64> m_times{};
QTimer m_tick{};
Vpn::ConnectionState m_state;
const static quint8 viewSize{60};
};
#endif // CONNECTIONCONTROLLER_H

View File

@@ -9,6 +9,7 @@
#include <QStandardPaths>
#include "core/controllers/vpnConfigurationController.h"
#include "core/errorstrings.h"
#include "systemController.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/android_utils.h"
@@ -100,7 +101,7 @@ void ExportController::generateConnectionConfig(const QString &clientName)
errorCode = m_clientManagementModel->appendClient(container, credentials, containerConfig, clientName, serverController);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -170,7 +171,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
}
if (errorCode) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -188,7 +189,7 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
QJsonObject nativeConfig;
ErrorCode errorCode = generateNativeConfig(DockerContainer::WireGuard, clientName, Proto::WireGuard, nativeConfig);
if (errorCode) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -208,7 +209,7 @@ void ExportController::generateAwgConfig(const QString &clientName)
QJsonObject nativeConfig;
ErrorCode errorCode = generateNativeConfig(DockerContainer::Awg, clientName, Proto::Awg, nativeConfig);
if (errorCode) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -236,7 +237,7 @@ void ExportController::generateShadowSocksConfig()
}
if (errorCode) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -262,7 +263,7 @@ void ExportController::generateCloakConfig()
QJsonObject nativeConfig;
ErrorCode errorCode = generateNativeConfig(DockerContainer::Cloak, "", Proto::Cloak, nativeConfig);
if (errorCode) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -282,7 +283,7 @@ void ExportController::generateXrayConfig()
QJsonObject nativeConfig;
ErrorCode errorCode = generateNativeConfig(DockerContainer::Xray, "", Proto::Xray, nativeConfig);
if (errorCode) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
return;
}
@@ -319,7 +320,7 @@ void ExportController::updateClientManagementModel(const DockerContainer contain
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_clientManagementModel->updateModel(container, credentials, serverController);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
}
}
@@ -329,7 +330,7 @@ void ExportController::revokeConfig(const int row, const DockerContainer contain
ErrorCode errorCode =
m_clientManagementModel->revokeClient(row, container, credentials, m_serversModel->getProcessedServerIndex(), serverController);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
}
}
@@ -338,7 +339,7 @@ void ExportController::renameClient(const int row, const QString &clientName, co
QSharedPointer<ServerController> serverController(new ServerController(m_settings));
ErrorCode errorCode = m_clientManagementModel->renameClient(row, clientName, container, credentials, serverController);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorCode);
emit exportErrorOccurred(errorString(errorCode));
}
}

View File

@@ -49,7 +49,6 @@ public slots:
signals:
void generateConfig(int type);
void exportErrorOccurred(const QString &errorMessage);
void exportErrorOccurred(ErrorCode errorCode);
void exportConfigChanged();

View File

@@ -6,6 +6,7 @@
#include <QRandomGenerator>
#include <QStandardPaths>
#include "core/errorstrings.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h"
#endif
@@ -220,7 +221,7 @@ void ImportController::importConfig()
} else if (m_config.contains(config_key::configVersion)) {
quint16 crc = qChecksum(QJsonDocument(m_config).toJson());
if (m_serversModel->isServerFromApiAlreadyExists(crc)) {
emit importErrorOccurred(ErrorCode::ApiConfigAlreadyAdded, true);
emit importErrorOccurred(errorString(ErrorCode::ApiConfigAlreadyAdded), true);
} else {
m_config.insert(config_key::crc, crc);
@@ -230,7 +231,7 @@ void ImportController::importConfig()
} else {
qDebug() << "Failed to import profile";
qDebug().noquote() << QJsonDocument(m_config).toJson();
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError), false);
}
m_config = {};
@@ -307,7 +308,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
hostName = hostNameAndPortMatch.captured(1);
} else {
qDebug() << "Key parameter 'Endpoint' is missing";
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError), false);
return QJsonObject();
}
@@ -333,7 +334,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::server_pub_key] = configMap.value("PublicKey");
} else {
qDebug() << "One of the key parameters is missing (PrivateKey, Address, PublicKey)";
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError), false);
return QJsonObject();
}

View File

@@ -54,7 +54,6 @@ public slots:
signals:
void importFinished();
void importErrorOccurred(const QString &errorMessage, bool goToPageHome);
void importErrorOccurred(ErrorCode errorCode, bool goToPageHome);
void qrDecodingFinished();

View File

@@ -9,6 +9,7 @@
#include "core/controllers/serverController.h"
#include "core/controllers/vpnConfigurationController.h"
#include "core/errorstrings.h"
#include "core/networkUtilities.h"
#include "logger.h"
#include "ui/models/protocols/awgConfigModel.h"
@@ -148,7 +149,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr
QMap<DockerContainer, QJsonObject> installedContainers;
ErrorCode errorCode = getAlreadyInstalledContainers(serverCredentials, serverController, installedContainers);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
@@ -157,7 +158,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr
if (!installedContainers.contains(container)) {
errorCode = serverController->setupContainer(serverCredentials, container, config);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
@@ -168,7 +169,7 @@ void InstallController::install(DockerContainer container, int port, TransportPr
}
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
@@ -203,7 +204,7 @@ void InstallController::installServer(const DockerContainer container, const QMa
auto errorCode = vpnConfigurationController.createProtocolConfigForContainer(m_processedServerCredentials, iterator.key(),
containerConfig);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
containerConfigs.append(containerConfig);
@@ -211,7 +212,7 @@ void InstallController::installServer(const DockerContainer container, const QMa
errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
} else {
@@ -243,7 +244,7 @@ void InstallController::installContainer(const DockerContainer container, const
auto errorCode =
vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, iterator.key(), containerConfig);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
m_serversModel->addContainerConfig(iterator.key(), containerConfig);
@@ -251,7 +252,7 @@ void InstallController::installContainer(const DockerContainer container, const
errorCode = m_clientManagementModel->appendClient(iterator.key(), serverCredentials, containerConfig,
QString("Admin [%1]").arg(QSysInfo::prettyProductName()), serverController);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
} else {
@@ -309,7 +310,7 @@ void InstallController::scanServerForInstalledContainers()
auto errorCode =
vpnConfigurationController.createProtocolConfigForContainer(serverCredentials, container, containerConfig);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
m_serversModel->addContainerConfig(container, containerConfig);
@@ -318,7 +319,7 @@ void InstallController::scanServerForInstalledContainers()
QString("Admin [%1]").arg(QSysInfo::prettyProductName()),
serverController);
if (errorCode) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return;
}
} else {
@@ -333,7 +334,7 @@ void InstallController::scanServerForInstalledContainers()
return;
}
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
}
ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentials &credentials,
@@ -514,7 +515,7 @@ void InstallController::updateContainer(QJsonObject config)
return;
}
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
}
void InstallController::rebootProcessedServer()
@@ -527,7 +528,7 @@ void InstallController::rebootProcessedServer()
if (errorCode == ErrorCode::NoError) {
emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
} else {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
}
}
@@ -551,7 +552,7 @@ void InstallController::removeAllContainers()
emit removeAllContainersFinished(tr("All containers from server '%1' have been removed").arg(serverName));
return;
}
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
}
void InstallController::removeProcessedContainer()
@@ -569,7 +570,7 @@ void InstallController::removeProcessedContainer()
emit removeProcessedContainerFinished(tr("%1 has been removed from the server '%2'").arg(containerName, serverName));
return;
}
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
}
void InstallController::removeApiConfig(const int serverIndex)
@@ -737,7 +738,7 @@ bool InstallController::checkSshConnection(QSharedPointer<ServerController> serv
if (errorCode == ErrorCode::NoError) {
m_processedServerCredentials.secretData = decryptedPrivateKey;
} else {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return false;
}
}
@@ -746,7 +747,7 @@ bool InstallController::checkSshConnection(QSharedPointer<ServerController> serv
output = serverController->checkSshConnection(m_processedServerCredentials, errorCode);
if (errorCode != ErrorCode::NoError) {
emit installationErrorOccurred(errorCode);
emit installationErrorOccurred(errorString(errorCode));
return false;
} else {
if (output.contains(tr("Please login as the user"))) {

View File

@@ -64,7 +64,6 @@ signals:
void removeProcessedContainerFinished(const QString &finishedMessage);
void installationErrorOccurred(const QString &errorMessage);
void installationErrorOccurred(ErrorCode errorCode);
void serverAlreadyExists(int serverIndex);

View File

@@ -1,8 +1,4 @@
#include "pageController.h"
#include "utils/converter.h"
#include "ui/models/servers_model.h"
#include "ui/models/languageModel.h"
#include "core/errorstrings.h"
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#include <QGuiApplication>
@@ -20,10 +16,8 @@
#endif
PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
const std::shared_ptr<Settings> &settings,
const QSharedPointer<LanguageModel> &languageModel,
QObject *parent)
: QObject(parent), m_serversModel(serversModel), m_settings(settings), m_languageModel(languageModel)
const std::shared_ptr<Settings> &settings, QObject *parent)
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
{
#ifdef Q_OS_ANDROID
// Change color of navigation and status bar's
@@ -44,8 +38,6 @@ PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
connect(this, &PageController::raiseMainWindow, []() { setDockIconVisible(true); });
connect(this, &PageController::hideMainWindow, []() { setDockIconVisible(false); });
#endif
connect(this, qOverload<ErrorCode>(&PageController::showErrorMessage), this, &PageController::onShowErrorMessage);
m_isTriggeredByConnectButton = false;
}
@@ -169,14 +161,3 @@ int PageController::getDrawerDepth()
{
return m_drawerDepth;
}
void PageController::onShowErrorMessage(ErrorCode errorCode)
{
const auto fullErrorMessage = errorString(errorCode);
const auto errorMessage = fullErrorMessage.mid(fullErrorMessage.indexOf(". ") + 1); // remove ErrorCode %1.
const auto baseUrl = m_languageModel->getDocsEndpoint();
const auto errorUrl = QStringLiteral("%1/troubleshooting/error-codes/#error-%2-%3").arg(baseUrl).arg(static_cast<int>(errorCode)).arg(utils::enumToString(errorCode).toLower());
const auto fullMessage = QStringLiteral("<a href=\"%1\" style=\"color: #FBB26A;\">ErrorCode: %2</a>. %3").arg(errorUrl).arg(static_cast<int>(errorCode)).arg(errorMessage);
emit showErrorMessage(fullMessage);
}

View File

@@ -4,9 +4,7 @@
#include <QObject>
#include <QQmlEngine>
#include "core/defs.h"
#include "ui/models/servers_model.h"
#include "ui/models/languageModel.h"
namespace PageLoader
{
@@ -72,7 +70,7 @@ class PageController : public QObject
Q_OBJECT
public:
explicit PageController(const QSharedPointer<ServersModel> &serversModel, const std::shared_ptr<Settings> &settings,
const QSharedPointer<LanguageModel> & languageModel,QObject *parent = nullptr);
QObject *parent = nullptr);
public slots:
QString getInitialPage();
@@ -95,9 +93,6 @@ public slots:
void setDrawerDepth(const int depth);
int getDrawerDepth();
private slots:
void onShowErrorMessage(amnezia::ErrorCode errorCode);
signals:
void goToPage(PageLoader::PageEnum page, bool slide = true);
void goToStartPage();
@@ -112,7 +107,6 @@ signals:
void restorePageHomeState(bool isContainerInstalled = false);
void replaceStartPage();
void showErrorMessage(amnezia::ErrorCode);
void showErrorMessage(const QString &errorMessage);
void showNotificationMessage(const QString &message);
@@ -137,8 +131,6 @@ private:
std::shared_ptr<Settings> m_settings;
QSharedPointer<LanguageModel> m_languageModel;
bool m_isTriggeredByConnectButton;
int m_drawerDepth = 0;

View File

@@ -15,7 +15,7 @@
#endif
#ifdef Q_OS_IOS
#include "platforms/ios/ios_controller.h"
#include "platforms/ios/MobileUtils.h"
#include <CoreFoundation/CoreFoundation.h>
#endif
@@ -24,6 +24,20 @@ SystemController::SystemController(const std::shared_ptr<Settings> &settings, QO
{
}
void SystemController::setAppHasFocus(bool appHasFocus)
{
if (m_appHasFocus != appHasFocus)
{
m_appHasFocus = appHasFocus;
emit appHasFocusChanged();
}
}
bool SystemController::appHasFocus() const
{
return m_appHasFocus;
}
void SystemController::saveFile(QString fileName, const QString &data)
{
#if defined Q_OS_ANDROID
@@ -46,8 +60,9 @@ void SystemController::saveFile(QString fileName, const QString &data)
#ifdef Q_OS_IOS
QStringList filesToSend;
filesToSend.append(fileUrl.toString());
MobileUtils mobileUtils;
// todo check if save successful
IosController::Instance()->shareText(filesToSend);
mobileUtils.shareText(filesToSend);
return;
#else
QFileInfo fi(fileName);
@@ -66,7 +81,8 @@ QString SystemController::getFileName(const QString &acceptLabel, const QString
#ifdef Q_OS_IOS
fileName = IosController::Instance()->openFile();
MobileUtils mobileUtils;
fileName = mobileUtils.openFile();
if (fileName.isEmpty()) {
return fileName;
}

View File

@@ -8,9 +8,13 @@
class SystemController : public QObject
{
Q_OBJECT
Q_PROPERTY(bool appHasFocus READ appHasFocus WRITE setAppHasFocus NOTIFY appHasFocusChanged)
public:
explicit SystemController(const std::shared_ptr<Settings> &setting, QObject *parent = nullptr);
void setAppHasFocus(bool isActive);
bool appHasFocus() const;
static void saveFile(QString fileName, const QString &data);
public slots:
@@ -21,11 +25,13 @@ public slots:
signals:
void fileDialogClosed(const bool isAccepted);
void appHasFocusChanged();
private:
std::shared_ptr<Settings> m_settings;
QObject *m_qmlRoot;
bool m_appHasFocus{false};
};
#endif // SYSTEMCONTROLLER_H

View File

@@ -90,24 +90,6 @@ int LanguageModel::getCurrentLanguageIndex()
}
}
QString LanguageModel::getDocsEndpoint()
{
QString baseUrl = "https://docs.amnezia.org";
auto locale = m_settings->getAppLanguage();
switch (locale.language()) {
case QLocale::Russian:
baseUrl += "/ru";
break;
case QLocale::Ukrainian:
baseUrl += "/ru";
break;
default:
break;
}
return baseUrl;
}
int LanguageModel::getLineHeightAppend()
{
int langIndex = getCurrentLanguageIndex();

View File

@@ -59,7 +59,6 @@ public slots:
int getCurrentLanguageIndex();
int getLineHeightAppend();
QString getCurrentLanguageName();
QString getDocsEndpoint();
signals:
void updateTranslations(const QLocale &locale);

View File

@@ -0,0 +1,125 @@
import QtQuick
import QtCharts
ChartView {
id: chartView
legend.visible: false
animationOptions: ChartView.AllAnimations
animationDuration: 2000.0
backgroundColor: "#1C1D21"
plotAreaColor: "#1C1D21"
margins.top: 0
margins.bottom: 0
margins.left: 0
margins.right: 0
antialiasing: true
enabled: false
property bool shouldUpdate: SystemController.appHasFocus
function getUTCSeconds() {
return new Date().setMilliseconds(0) / 1000
}
function addValues(rx, tx) {
let currentTime = getUTCSeconds()
xAxis.min = currentTime - 60
xAxis.max = currentTime
if (rx > yAxis.max) yAxis.max = rx * 1.1
if (tx > yAxis.max) yAxis.max = tx * 1.1
rxLine.append(currentTime, rx)
txLine.append(currentTime, tx)
}
function printAll() {
var rxValues = ConnectionController.getRxView()
var txValues = ConnectionController.getTxView()
var times = ConnectionController.getTimes()
let currentTime = getUTCSeconds()
xAxis.min = currentTime - 60
xAxis.max = currentTime
rxLine.clear()
txLine.clear()
if (times.length === 0) return
xAxis.min = times[0]
xAxis.max = times[times.length - 1]
for (let i = 0; i < times.length; i++)
{
if (rxValues[i] > yAxis.max) yAxis.max = rxValues[i]
if (txValues[i] > yAxis.max) yAxis.max = txValues[i]
rxLine.append(times[i], rxValues[i])
txLine.append(times[i], txValues[i])
}
}
Component.onCompleted: {
printAll()
}
Connections {
target: ConnectionController
function onBytesChanged() {
if (shouldUpdate) {
addValues(ConnectionController.rxBytes, ConnectionController.txBytes)
}
}
}
Connections {
target: SystemController
function onAppHasFocusChanged() {
if (shouldUpdate) { printAll() }
}
}
ValueAxis {
id: yAxis
min: -100
max: 1000
visible: false
labelsVisible: false
gridLineColor: "transparent"
}
ValueAxis {
id: xAxis
visible: false
labelsVisible: false
gridLineColor: "transparent"
}
SplineSeries {
id: rxLine
name: "Received Bytes"
//width: 2
axisX: xAxis
axisY: yAxis
capStyle: Qt.RoundCap
useOpenGL: true
color: "#70553c"
XYPoint { x: getUTCSeconds(); y: 0 }
}
SplineSeries {
id: txLine
name: "Transmitted Bytes"
//width: 2
axisX: xAxis
axisY: yAxis
capStyle: Qt.RoundCap
useOpenGL: true
color: "#737274"
XYPoint { x: getUTCSeconds(); y: 0 }
}
}

View File

@@ -57,17 +57,7 @@ Popup {
horizontalAlignment: Text.AlignLeft
Layout.fillWidth: true
onLinkActivated: function(link) {
Qt.openUrlExternally(link)
}
text: root.text
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
Item {

View File

@@ -261,10 +261,15 @@ PageType {
LabelTextType {
id: collapsedServerMenuDescription
Layout.bottomMargin: drawer.isCollapsed ? 44 : ServersModel.isDefaultServerFromApi ? 89 : 44
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
text: drawer.isCollapsed ? ServersModel.defaultServerDescriptionCollapsed : ServersModel.defaultServerDescriptionExpanded
}
GraphViewType {
Layout.minimumHeight: 50
Layout.bottomMargin: drawer.isCollapsed ? 24 : ServersModel.isDefaultServerFromApi ? 69 : 24
Layout.fillWidth: true
}
}
Connections {

View File

@@ -76,9 +76,9 @@ PageType {
Connections {
target: InstallController
function onInstallationErrorOccurred(error) {
function onInstallationErrorOccurred(errorMessage) {
PageController.showBusyIndicator(false)
PageController.showErrorMessage(error)
PageController.showErrorMessage(errorMessage)
var currentPageName = stackView.currentItem.objectName
@@ -97,8 +97,8 @@ PageType {
PageController.showBusyIndicator(false)
}
function onImportErrorOccurred(error, goToPageHome) {
PageController.showErrorMessage(error)
function onImportErrorOccurred(errorMessage, goToPageHome) {
PageController.showErrorMessage(errorMessage)
}
}

View File

@@ -102,10 +102,9 @@ PageType {
PageController.showBusyIndicator(false)
}
function onExportErrorOccurred(error) {
function onExportErrorOccurred(errorMessage) {
shareConnectionDrawer.close()
PageController.showErrorMessage(error)
PageController.showErrorMessage(errorMessage)
}
}

View File

@@ -99,10 +99,9 @@ PageType {
Connections {
target: InstallController
function onInstallationErrorOccurred(error) {
function onInstallationErrorOccurred(errorMessage) {
PageController.showBusyIndicator(false)
PageController.showErrorMessage(error)
PageController.showErrorMessage(errorMessage)
var needCloseCurrentPage = false
var currentPageName = tabBarStackView.currentItem.objectName
@@ -147,8 +146,8 @@ PageType {
Connections {
target: ImportController
function onImportErrorOccurred(error, goToPageHome) {
PageController.showErrorMessage(error)
function onImportErrorOccurred(errorMessage, goToPageHome) {
PageController.showErrorMessage(errorMessage)
}
}

View File

@@ -28,6 +28,10 @@ Window {
PageController.closeWindow()
}
onActiveChanged: {
SystemController.appHasFocus = active
}
title: "AmneziaVPN"
StackViewType {

View File

@@ -1,25 +0,0 @@
#pragma once
#include <QMetaEnum>
namespace utils
{
template<typename Enum>
QString enumToString(Enum value)
{
auto metaEnum = QMetaEnum::fromType<Enum>();
return metaEnum.valueToKey(static_cast<int>(value));
}
template<typename Enum>
Enum enumFromString(const QString &str, Enum defaultValue = {})
{
auto metaEnum = QMetaEnum::fromType<Enum>();
bool isOk;
auto value = metaEnum.keyToValue(str.toLatin1(), &isOk);
if (isOk) {
return static_cast<Enum>(value);
}
return defaultValue;
}
}