mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-22 02:01:08 +07:00
feat: add mtproxy(#2370)
* Feat: Add MtProxy (Telegram) * add path files * refactor: move logic from ui to core --------- Co-authored-by: vkamn <vk@amnezia.org>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
#include "networkReachabilityController.h"
|
||||
|
||||
#include <QNetworkInformation>
|
||||
|
||||
namespace {
|
||||
|
||||
bool reachabilityAllowsRemoteOperations(QNetworkInformation::Reachability r) {
|
||||
using R = QNetworkInformation::Reachability;
|
||||
// Unknown: no backend or not yet determined — do not block UI.
|
||||
return r == R::Online || r == R::Unknown;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NetworkReachabilityController::NetworkReachabilityController(QObject *parent) : QObject(parent) {
|
||||
attachToNetworkInformation();
|
||||
}
|
||||
|
||||
bool NetworkReachabilityController::hasInternetAccess() const {
|
||||
return m_hasInternetAccess;
|
||||
}
|
||||
|
||||
void NetworkReachabilityController::attachToNetworkInformation() {
|
||||
if (!QNetworkInformation::loadDefaultBackend()) {
|
||||
return;
|
||||
}
|
||||
QNetworkInformation *ni = QNetworkInformation::instance();
|
||||
if (!ni) {
|
||||
return;
|
||||
}
|
||||
const bool initial = reachabilityAllowsRemoteOperations(ni->reachability());
|
||||
const bool previous = m_hasInternetAccess;
|
||||
m_hasInternetAccess = initial;
|
||||
if (previous != m_hasInternetAccess) {
|
||||
emit hasInternetAccessChanged();
|
||||
}
|
||||
connect(ni, &QNetworkInformation::reachabilityChanged, this,
|
||||
[this](QNetworkInformation::Reachability r) {
|
||||
const bool ok = reachabilityAllowsRemoteOperations(r);
|
||||
if (ok == m_hasInternetAccess) {
|
||||
return;
|
||||
}
|
||||
m_hasInternetAccess = ok;
|
||||
emit hasInternetAccessChanged();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef NETWORKREACHABILITYCONTROLLER_H
|
||||
#define NETWORKREACHABILITYCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
// Exposes QNetworkInformation to QML for UI that must not run remote operations offline.
|
||||
// Note: mozilla/networkwatcher.h has NetworkWatcher::getReachability() using the same API,
|
||||
// but networkwatcher.cpp is not linked into the desktop client (only the service process).
|
||||
|
||||
class NetworkReachabilityController final : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool hasInternetAccess READ hasInternetAccess NOTIFY hasInternetAccessChanged)
|
||||
|
||||
public:
|
||||
explicit NetworkReachabilityController(QObject *parent = nullptr);
|
||||
|
||||
bool hasInternetAccess() const;
|
||||
|
||||
signals:
|
||||
|
||||
void hasInternetAccessChanged();
|
||||
|
||||
private:
|
||||
void attachToNetworkInformation();
|
||||
|
||||
bool m_hasInternetAccess = true;
|
||||
};
|
||||
|
||||
#endif // NETWORKREACHABILITYCONTROLLER_H
|
||||
@@ -50,6 +50,7 @@ namespace PageLoader
|
||||
PageServiceTorWebsiteSettings,
|
||||
PageServiceDnsSettings,
|
||||
PageServiceSocksProxySettings,
|
||||
PageServiceMtProxySettings,
|
||||
|
||||
PageSetupWizardStart,
|
||||
PageSetupWizardCredentials,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "../systemController.h"
|
||||
#include "core/utils/qrCodeUtils.h"
|
||||
|
||||
ExportUiController::ExportUiController(ExportController* exportController, QObject *parent)
|
||||
: QObject(parent),
|
||||
@@ -53,6 +54,14 @@ void ExportUiController::generateXrayConfig(const QString &serverId, const QStri
|
||||
applyExportResult(result);
|
||||
}
|
||||
|
||||
void ExportUiController::generateQrFromString(const QString &text)
|
||||
{
|
||||
clearPreviousConfig();
|
||||
m_config = text;
|
||||
m_qrCodes = qrCodeUtils::generateQrCodeImageSeries(text.toUtf8());
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
QString ExportUiController::getConfig()
|
||||
{
|
||||
return m_config;
|
||||
|
||||
@@ -25,6 +25,7 @@ public slots:
|
||||
void generateWireGuardConfig(const QString &serverId, const QString &clientName);
|
||||
void generateAwgConfig(const QString &serverId, int containerIndex, const QString &clientName);
|
||||
void generateXrayConfig(const QString &serverId, const QString &clientName);
|
||||
void generateQrFromString(const QString &text);
|
||||
|
||||
QString getConfig();
|
||||
QString getNativeConfigString();
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
#include <QEventLoop>
|
||||
#include <QJsonObject>
|
||||
#include <QRandomGenerator>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "core/utils/api/apiUtils.h"
|
||||
#include "core/controllers/selfhosted/installController.h"
|
||||
#include "core/utils/selfhosted/sshSession.h"
|
||||
#include "core/utils/networkUtilities.h"
|
||||
#include "core/utils/protocolEnum.h"
|
||||
#include "core/protocols/protocolUtils.h"
|
||||
@@ -47,6 +49,7 @@ InstallUiController::InstallUiController(InstallController *installController,
|
||||
#endif
|
||||
SftpConfigModel *sftpConfigModel,
|
||||
Socks5ProxyConfigModel *socks5ConfigModel,
|
||||
MtProxyConfigModel* mtConfigModel,
|
||||
QObject *parent)
|
||||
: QObject(parent),
|
||||
m_installController(installController),
|
||||
@@ -63,7 +66,8 @@ InstallUiController::InstallUiController(InstallController *installController,
|
||||
m_ikev2ConfigModel(ikev2ConfigModel),
|
||||
#endif
|
||||
m_sftpConfigModel(sftpConfigModel),
|
||||
m_socks5ConfigModel(socks5ConfigModel)
|
||||
m_socks5ConfigModel(socks5ConfigModel),
|
||||
m_mtProxyConfigModel(mtConfigModel)
|
||||
{
|
||||
connect(m_installController, &InstallController::configValidated, this, &InstallUiController::configValidated);
|
||||
connect(m_installController, &InstallController::validationErrorOccurred, this, [this](ErrorCode errorCode) {
|
||||
@@ -199,7 +203,7 @@ void InstallUiController::scanServerForInstalledContainers(const QString &server
|
||||
emit installationErrorOccurred(errorCode);
|
||||
}
|
||||
|
||||
void InstallUiController::updateContainer(const QString &serverId, int containerIndex, int protocolIndex)
|
||||
void InstallUiController::updateContainer(const QString &serverId, int containerIndex, int protocolIndex, bool closePage)
|
||||
{
|
||||
DockerContainer container = static_cast<DockerContainer>(containerIndex);
|
||||
|
||||
@@ -238,6 +242,10 @@ void InstallUiController::updateContainer(const QString &serverId, int container
|
||||
containerConfig.protocolConfig = m_socks5ConfigModel->getProtocolConfig();
|
||||
break;
|
||||
}
|
||||
case Proto::MtProxy: {
|
||||
containerConfig.protocolConfig = m_mtProxyConfigModel->getProtocolConfig();
|
||||
break;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
case Proto::Ikev2: {
|
||||
containerConfig.protocolConfig = m_ikev2ConfigModel->getProtocolConfig();
|
||||
@@ -249,19 +257,113 @@ void InstallUiController::updateContainer(const QString &serverId, int container
|
||||
}
|
||||
ContainerConfig oldContainerConfig = m_serversController->getContainerConfig(serverId, container);
|
||||
|
||||
if (container == DockerContainer::MtProxy) {
|
||||
emit serverIsBusy(true);
|
||||
auto *watcher = new QFutureWatcher<ErrorCode>(this);
|
||||
QObject::connect(watcher, &QFutureWatcher<ErrorCode>::finished, this,
|
||||
[this, watcher, serverId, container, closePage]() {
|
||||
const ErrorCode errorCode = watcher->result();
|
||||
watcher->deleteLater();
|
||||
emit serverIsBusy(false);
|
||||
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
const ContainerConfig updatedConfig =
|
||||
m_serversController->getContainerConfig(serverId, container);
|
||||
m_protocolModel->updateModel(updatedConfig);
|
||||
|
||||
const auto defaultContainer =
|
||||
m_serversController->getDefaultContainer(serverId);
|
||||
if ((serverId == m_serversController->getDefaultServerId())
|
||||
&& (container == defaultContainer)) {
|
||||
emit currentContainerUpdated();
|
||||
} else {
|
||||
emit updateContainerFinished(tr("Settings updated successfully"), closePage);
|
||||
}
|
||||
} else {
|
||||
emit installationErrorOccurred(errorCode);
|
||||
}
|
||||
});
|
||||
|
||||
ContainerConfig newConfigCopy = containerConfig;
|
||||
ContainerConfig oldConfigCopy = oldContainerConfig;
|
||||
InstallController *installController = m_installController;
|
||||
QFuture<ErrorCode> future =
|
||||
QtConcurrent::run([installController, serverId, container, oldConfigCopy,
|
||||
newConfigCopy]() mutable -> ErrorCode {
|
||||
return installController->updateContainer(serverId, container, oldConfigCopy, newConfigCopy);
|
||||
});
|
||||
watcher->setFuture(future);
|
||||
return;
|
||||
}
|
||||
|
||||
ErrorCode errorCode = m_installController->updateContainer(serverId, container, oldContainerConfig, containerConfig);
|
||||
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
ContainerConfig updatedConfig = m_serversController->getContainerConfig(serverId, container);
|
||||
m_protocolModel->updateModel(updatedConfig);
|
||||
|
||||
emit updateContainerFinished(tr("Settings updated successfully"));
|
||||
const auto defaultContainer = m_serversController->getDefaultContainer(serverId);
|
||||
if ((serverId == m_serversController->getDefaultServerId()) && (container == defaultContainer)) {
|
||||
emit currentContainerUpdated();
|
||||
} else {
|
||||
emit updateContainerFinished(tr("Settings updated successfully"), closePage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
emit installationErrorOccurred(errorCode);
|
||||
}
|
||||
|
||||
void InstallUiController::setContainerEnabled(const QString &serverId, int containerIndex, bool enabled)
|
||||
{
|
||||
const DockerContainer container = static_cast<DockerContainer>(containerIndex);
|
||||
|
||||
emit serverIsBusy(true);
|
||||
const ErrorCode errorCode = m_installController->setDockerContainerEnabledState(serverId, container, enabled);
|
||||
emit serverIsBusy(false);
|
||||
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
const ContainerConfig currentConfig = m_serversController->getContainerConfig(serverId, container);
|
||||
m_protocolModel->updateModel(currentConfig);
|
||||
emit setContainerEnabledFinished(enabled);
|
||||
return;
|
||||
}
|
||||
|
||||
emit installationErrorOccurred(errorCode);
|
||||
}
|
||||
|
||||
void InstallUiController::refreshContainerStatus(const QString &serverId, int containerIndex)
|
||||
{
|
||||
const DockerContainer container = static_cast<DockerContainer>(containerIndex);
|
||||
int status = 3;
|
||||
const ErrorCode errorCode = m_installController->queryDockerContainerStatus(serverId, container, status);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
emit containerStatusRefreshed(3);
|
||||
return;
|
||||
}
|
||||
emit containerStatusRefreshed(status);
|
||||
}
|
||||
|
||||
void InstallUiController::refreshContainerDiagnostics(const QString &serverId, int containerIndex, int port)
|
||||
{
|
||||
const DockerContainer container = static_cast<DockerContainer>(containerIndex);
|
||||
MtProxyContainerDiagnostics diag;
|
||||
const ErrorCode errorCode = m_installController->queryMtProxyDiagnostics(serverId, container, port, diag);
|
||||
if (errorCode != ErrorCode::NoError) {
|
||||
emit containerDiagnosticsRefreshed(false, false, -1, QString(), QString());
|
||||
return;
|
||||
}
|
||||
emit containerDiagnosticsRefreshed(diag.portReachable, diag.upstreamReachable, diag.clientsConnected,
|
||||
diag.lastConfigRefresh, diag.statsEndpoint);
|
||||
}
|
||||
|
||||
void InstallUiController::fetchContainerSecret(const QString &serverId, int containerIndex)
|
||||
{
|
||||
const DockerContainer container = static_cast<DockerContainer>(containerIndex);
|
||||
const QString secret = m_installController->fetchDockerContainerSecret(serverId, container);
|
||||
emit containerSecretFetched(secret);
|
||||
}
|
||||
|
||||
void InstallUiController::rebootServer(const QString &serverId)
|
||||
{
|
||||
const QString serverName = m_serversController->notificationDisplayName(serverId);
|
||||
@@ -473,6 +575,7 @@ void InstallUiController::updateProtocolConfigModel(const QString &serverId, int
|
||||
case Proto::TorWebSite: updateIfPresent(m_torConfigModel, containerConfig.getTorProtocolConfig()); break;
|
||||
case Proto::Sftp: updateIfPresent(m_sftpConfigModel, containerConfig.getSftpProtocolConfig()); break;
|
||||
case Proto::Socks5Proxy: updateIfPresent(m_socks5ConfigModel, containerConfig.getSocks5ProxyProtocolConfig()); break;
|
||||
case Proto::MtProxy: updateIfPresent(m_mtProxyConfigModel, containerConfig.getMtProxyProtocolConfig()); break;
|
||||
#ifdef Q_OS_WINDOWS
|
||||
case Proto::Ikev2: updateIfPresent(m_ikev2ConfigModel, containerConfig.getIkev2ProtocolConfig()); break;
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "ui/models/services/torConfigModel.h"
|
||||
#include "core/models/protocols/sftpProtocolConfig.h"
|
||||
#include "core/models/protocols/socks5ProxyProtocolConfig.h"
|
||||
#include "ui/models/services/mtProxyConfigModel.h"
|
||||
|
||||
class InstallUiController : public QObject
|
||||
{
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
#endif
|
||||
SftpConfigModel* sftpConfigModel,
|
||||
Socks5ProxyConfigModel* socks5ConfigModel,
|
||||
MtProxyConfigModel* mtConfigModel,
|
||||
QObject *parent = nullptr);
|
||||
~InstallUiController();
|
||||
|
||||
@@ -58,12 +60,16 @@ public slots:
|
||||
|
||||
void scanServerForInstalledContainers(const QString &serverId);
|
||||
|
||||
void updateContainer(const QString &serverId, int containerIndex, int protocolIndex);
|
||||
void updateContainer(const QString &serverId, int containerIndex, int protocolIndex, bool closePage = true);
|
||||
|
||||
void removeServer(const QString &serverId);
|
||||
void rebootServer(const QString &serverId);
|
||||
void removeAllContainers(const QString &serverId);
|
||||
void removeContainer(const QString &serverId, int containerIndex);
|
||||
void setContainerEnabled(const QString &serverId, int containerIndex, bool enabled);
|
||||
void refreshContainerStatus(const QString &serverId, int containerIndex);
|
||||
void refreshContainerDiagnostics(const QString &serverId, int containerIndex, int port);
|
||||
void fetchContainerSecret(const QString &serverId, int containerIndex);
|
||||
|
||||
void clearCachedProfile(const QString &serverId, int containerIndex);
|
||||
|
||||
@@ -94,7 +100,7 @@ signals:
|
||||
void installContainerFinished(const QString &finishMessage, bool isServiceInstall);
|
||||
void installServerFinished(const QString &finishMessage);
|
||||
|
||||
void updateContainerFinished(const QString &message);
|
||||
void updateContainerFinished(const QString &message, bool closePage);
|
||||
|
||||
void scanServerFinished(bool isInstalledContainerFound);
|
||||
|
||||
@@ -102,6 +108,11 @@ signals:
|
||||
void removeServerFinished(const QString &finishedMessage);
|
||||
void removeAllContainersFinished(const QString &finishedMessage);
|
||||
void removeContainerFinished(const QString &finishedMessage);
|
||||
void setContainerEnabledFinished(bool enabled);
|
||||
void containerStatusRefreshed(int status);
|
||||
void containerDiagnosticsRefreshed(bool portReachable, bool upstreamReachable, int clientsConnected,
|
||||
const QString &lastConfigRefresh, const QString &statsEndpoint);
|
||||
void containerSecretFetched(const QString &secret);
|
||||
|
||||
void installationErrorOccurred(ErrorCode errorCode);
|
||||
void wrongInstallationUser(const QString &message);
|
||||
@@ -114,6 +125,8 @@ signals:
|
||||
void serverIsBusy(const bool isBusy);
|
||||
void cancelInstallation();
|
||||
|
||||
void currentContainerUpdated();
|
||||
|
||||
void cachedProfileCleared(const QString &message);
|
||||
void apiConfigRemoved(const QString &message);
|
||||
|
||||
@@ -138,6 +151,7 @@ private:
|
||||
#endif
|
||||
SftpConfigModel* m_sftpConfigModel;
|
||||
Socks5ProxyConfigModel* m_socks5ConfigModel;
|
||||
MtProxyConfigModel* m_mtProxyConfigModel;
|
||||
|
||||
ServerCredentials m_processedServerCredentials;
|
||||
|
||||
|
||||
@@ -510,6 +510,8 @@ QStringList ServersUiController::getAllInstalledServicesName(int serverIndex) co
|
||||
servicesName.append("TOR");
|
||||
} else if (container == DockerContainer::Socks5Proxy) {
|
||||
servicesName.append("SOCKS5");
|
||||
} else if (container == DockerContainer::MtProxy) {
|
||||
servicesName.append("MTProxy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user