mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
feat: update ConfigManager and ProxyServer to utilize Settings
- Modified ConfigManager to accept a Settings object for improved configuration management. - Updated ProxyServer to initialize with Settings, enhancing dependency injection.
This commit is contained in:
@@ -37,7 +37,7 @@ CoreController::CoreController(const QSharedPointer<VpnConnection> &vpnConnectio
|
||||
void CoreController::initLocalProxy()
|
||||
{
|
||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
m_proxyServer.reset(new ProxyServer(this));
|
||||
m_proxyServer.reset(new ProxyServer(m_settings, this));
|
||||
|
||||
auto syncLocalProxy = [this]() {
|
||||
if (!m_proxyServer) {
|
||||
|
||||
@@ -1,565 +1,193 @@
|
||||
#include "configmanager.h"
|
||||
#include "core/serialization/serialization.h"
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
#include "core/api/apiUtils.h"
|
||||
#include "proxylogger.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonParseError>
|
||||
#include <QSaveFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QDebug>
|
||||
#include <QUuid>
|
||||
|
||||
ConfigManager::ConfigManager()
|
||||
ConfigManager::ConfigManager(const std::shared_ptr<Settings> &settings)
|
||||
: m_settings(settings)
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Initializing ConfigManager");
|
||||
|
||||
// Create configs directory if it doesn't exist
|
||||
QString configPath = getConfigsPath();
|
||||
ProxyLogger::getInstance().debug(QString("Ensuring config directory exists: %1").arg(configPath));
|
||||
QDir().mkpath(configPath);
|
||||
|
||||
// Read active config UUID and initialize config count
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
m_activeConfigUuid = configsInfo["activeConfigUuid"].toString();
|
||||
m_configCount = configsInfo["configs"].toObject().size();
|
||||
ProxyLogger::getInstance().info(QString("Active config UUID: %1, Total configs: %2")
|
||||
.arg(m_activeConfigUuid.isEmpty() ? "none" : m_activeConfigUuid)
|
||||
.arg(m_configCount));
|
||||
ProxyLogger::getInstance().debug("ConfigManager initialized (Settings-backed)");
|
||||
}
|
||||
|
||||
QString ConfigManager::getConfigsPath() const
|
||||
std::optional<ConfigManager::ConfigData> ConfigManager::buildConfig(QString &errorDescription) const
|
||||
{
|
||||
QString configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
return QDir(configDir).filePath("xray_configs");
|
||||
}
|
||||
errorDescription.clear();
|
||||
|
||||
QString ConfigManager::getActiveConfigPath() const
|
||||
{
|
||||
return QDir(getConfigsPath()).filePath("active_config.json");
|
||||
}
|
||||
|
||||
QString ConfigManager::getConfigsInfoPath() const
|
||||
{
|
||||
return QDir(getConfigsPath()).filePath("configs_info.json");
|
||||
}
|
||||
|
||||
QJsonObject ConfigManager::readConfigsInfo() const
|
||||
{
|
||||
QFile file(getConfigsInfoPath());
|
||||
|
||||
if (!file.exists()) {
|
||||
ProxyLogger::getInstance().info("Configs info file doesn't exist, creating new one");
|
||||
// If file doesn't exist, return empty structure
|
||||
QJsonObject configsInfo;
|
||||
configsInfo["version"] = 1;
|
||||
configsInfo["configs"] = QJsonObject();
|
||||
return configsInfo;
|
||||
if (!m_settings) {
|
||||
const QString message = QStringLiteral("Settings backend is not available");
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to open configs info file: %1").arg(file.errorString()));
|
||||
return QJsonObject();
|
||||
const QString ownerUuid = m_settings->localProxyOwnerUuid();
|
||||
if (ownerUuid.isEmpty()) {
|
||||
const QString message = QStringLiteral("Local proxy owner UUID is not configured");
|
||||
ProxyLogger::getInstance().warning(message);
|
||||
errorDescription = message;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
const auto ownerServer = findServerByUuid(ownerUuid);
|
||||
if (!ownerServer) {
|
||||
const QString message = QStringLiteral("Owner server with UUID %1 not found in Settings").arg(ownerUuid);
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!apiUtils::isPremiumServer(*ownerServer)) {
|
||||
const QString message = QStringLiteral("Server %1 is not premium, local proxy is unavailable")
|
||||
.arg(ownerServer->value(amnezia::config_key::name).toString());
|
||||
ProxyLogger::getInstance().warning(message);
|
||||
errorDescription = message;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto serializedConfig = extractSerializedXrayConfig(*ownerServer);
|
||||
if (!serializedConfig || serializedConfig->isEmpty()) {
|
||||
const QString message = QStringLiteral("Server %1 lacks Xray last_config payload")
|
||||
.arg(ownerServer->value(amnezia::config_key::name).toString());
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
|
||||
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to parse configs info file: %1").arg(parseError.errorString()));
|
||||
return QJsonObject();
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(serializedConfig->toUtf8(), &parseError);
|
||||
if (parseError.error != QJsonParseError::NoError || !doc.isObject()) {
|
||||
const QString message = QStringLiteral("Failed to parse Xray config JSON: %1").arg(parseError.errorString());
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Successfully read configs info file");
|
||||
return doc.object();
|
||||
ConfigData data;
|
||||
data.ownerUuid = ownerUuid;
|
||||
data.serverName = ownerServer->value(amnezia::config_key::name).toString();
|
||||
data.serializedConfig = *serializedConfig;
|
||||
data.parsedConfig = doc.object();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool ConfigManager::writeConfigsInfo(const QJsonObject &configsInfo)
|
||||
bool ConfigManager::writeTempConfig(const QString &serializedConfig, QString &configPath, QString &errorDescription) const
|
||||
{
|
||||
QFile file(getConfigsInfoPath());
|
||||
errorDescription.clear();
|
||||
configPath.clear();
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to open configs info file for writing: %1").arg(file.errorString()));
|
||||
const QString directory = tempDirectory();
|
||||
if (!QDir().mkpath(directory)) {
|
||||
const QString message = QStringLiteral("Failed to create temp config directory: %1").arg(directory);
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_configCount = configsInfo["configs"].toObject().size();
|
||||
ProxyLogger::getInstance().debug(QString("Updated config count: %1").arg(m_configCount));
|
||||
|
||||
QJsonDocument doc(configsInfo);
|
||||
file.write(doc.toJson(QJsonDocument::Indented));
|
||||
file.close();
|
||||
|
||||
ProxyLogger::getInstance().debug("Successfully wrote configs info file");
|
||||
return true;
|
||||
}
|
||||
|
||||
QJsonObject ConfigManager::readActiveConfig() const
|
||||
{
|
||||
QFile file(getActiveConfigPath());
|
||||
|
||||
if (!file.exists()) {
|
||||
ProxyLogger::getInstance().warning(QString("Active config file not found at: %1").arg(getActiveConfigPath()));
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to open active config file: %1").arg(file.errorString()));
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
|
||||
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to parse active config file: %1").arg(parseError.errorString()));
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Successfully read active config file");
|
||||
return doc.object();
|
||||
}
|
||||
|
||||
bool ConfigManager::writeActiveConfig(const QJsonObject &config)
|
||||
{
|
||||
ProxyLogger::getInstance().info("Writing new active config");
|
||||
QFile file(getActiveConfigPath());
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to open active config file for writing: %1").arg(file.errorString()));
|
||||
const QString path = tempConfigPath();
|
||||
QSaveFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
const QString message = QStringLiteral("Failed to open temp config file %1: %2").arg(path, file.errorString());
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonDocument doc(config);
|
||||
file.write(doc.toJson(QJsonDocument::Indented));
|
||||
file.close();
|
||||
if (file.write(serializedConfig.toUtf8()) == -1) {
|
||||
const QString message = QStringLiteral("Failed to write temp config file %1: %2").arg(path, file.errorString());
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return false;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Successfully wrote active config file");
|
||||
if (!file.commit()) {
|
||||
const QString message = QStringLiteral("Failed to commit temp config file %1").arg(path);
|
||||
ProxyLogger::getInstance().error(message);
|
||||
errorDescription = message;
|
||||
return false;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().info(QStringLiteral("Xray config saved to %1").arg(path));
|
||||
configPath = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigManager::removeActiveConfigFile()
|
||||
bool ConfigManager::removeTempConfig() const
|
||||
{
|
||||
ProxyLogger::getInstance().info("Removing active config file");
|
||||
QFile file(getActiveConfigPath());
|
||||
|
||||
if (file.exists()) {
|
||||
if (file.remove()) {
|
||||
ProxyLogger::getInstance().debug("Successfully removed active config file");
|
||||
return true;
|
||||
} else {
|
||||
ProxyLogger::getInstance().error(QString("Failed to remove active config file: %1").arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
const QString path = tempConfigPath();
|
||||
QFile file(path);
|
||||
if (!file.exists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Active config file does not exist, nothing to remove");
|
||||
|
||||
if (!file.remove()) {
|
||||
ProxyLogger::getInstance().warning(QStringLiteral("Failed to remove temp config file %1: %2").arg(path, file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug(QStringLiteral("Removed temp config file %1").arg(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ConfigManager::generateUuid() const
|
||||
QString ConfigManager::tempConfigPath() const
|
||||
{
|
||||
return QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
return QDir(tempDirectory()).filePath(QStringLiteral("xray_active.json"));
|
||||
}
|
||||
|
||||
QString ConfigManager::getProtocolFromSerializedConfig(const QString &config) const
|
||||
std::optional<QJsonObject> ConfigManager::findServerByUuid(const QString &uuid) const
|
||||
{
|
||||
if (config.startsWith("vless://")) return "vless";
|
||||
if (config.startsWith("vmess://")) return "vmess";
|
||||
if (config.startsWith("trojan://")) return "trojan";
|
||||
if (config.startsWith("ss://")) return "ss";
|
||||
return QString();
|
||||
}
|
||||
if (!m_settings) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QJsonObject ConfigManager::deserializeConfig(const QString &configStr, QString *prefix, QString *errorMsg)
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Deserializing config");
|
||||
QJsonObject outConfig;
|
||||
|
||||
QString localPrefix;
|
||||
QString localErrorMsg;
|
||||
|
||||
QString* safePrefix = prefix ? prefix : &localPrefix;
|
||||
QString* safeErrorMsg = errorMsg ? errorMsg : &localErrorMsg;
|
||||
|
||||
if (configStr.startsWith("vless://")) {
|
||||
ProxyLogger::getInstance().debug("Deserializing VLESS config");
|
||||
outConfig = amnezia::serialization::vless::Deserialize(configStr, safePrefix, safeErrorMsg);
|
||||
if (safePrefix->contains(QRegularExpression("%[0-9A-Fa-f]{2}"))) {
|
||||
*safePrefix = QString::fromUtf8(QByteArray::fromPercentEncoding(safePrefix->toUtf8()));
|
||||
const QJsonArray servers = m_settings->serversArray();
|
||||
for (const QJsonValue &value : servers) {
|
||||
const QJsonObject server = value.toObject();
|
||||
if (server.value(amnezia::config_key::server_uuid).toString() == uuid) {
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
||||
if (configStr.startsWith("vmess://") && configStr.contains("@")) {
|
||||
ProxyLogger::getInstance().debug("Deserializing new VMess config");
|
||||
outConfig = amnezia::serialization::vmess_new::Deserialize(configStr, safePrefix, safeErrorMsg);
|
||||
}
|
||||
|
||||
else if (configStr.startsWith("vmess://")) {
|
||||
ProxyLogger::getInstance().debug("Deserializing VMess config");
|
||||
outConfig = amnezia::serialization::vmess::Deserialize(configStr, safePrefix, safeErrorMsg);
|
||||
}
|
||||
|
||||
if (configStr.startsWith("trojan://")) {
|
||||
ProxyLogger::getInstance().debug("Deserializing Trojan config");
|
||||
outConfig = amnezia::serialization::trojan::Deserialize(configStr, safePrefix, safeErrorMsg);
|
||||
}
|
||||
|
||||
if (configStr.startsWith("ss://") && !configStr.contains("plugin=")) {
|
||||
ProxyLogger::getInstance().debug("Deserializing Shadowsocks config");
|
||||
outConfig = amnezia::serialization::ss::Deserialize(configStr, safePrefix, safeErrorMsg);
|
||||
if (safePrefix->contains(QRegularExpression("%[0-9A-Fa-f]{2}"))) {
|
||||
*safePrefix = QString::fromUtf8(QByteArray::fromPercentEncoding(safePrefix->toUtf8()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!safeErrorMsg->isEmpty()) {
|
||||
ProxyLogger::getInstance().error(QString("Config deserialization error: %1").arg(*safeErrorMsg));
|
||||
}
|
||||
|
||||
return outConfig;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QJsonObject ConfigManager::addInbounds(const QJsonObject &config)
|
||||
std::optional<QString> ConfigManager::extractSerializedXrayConfig(const QJsonObject &server) const
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Adding inbounds configuration");
|
||||
QJsonObject resultConfig = config;
|
||||
const QJsonArray containers = server.value(amnezia::config_key::containers).toArray();
|
||||
const QString targetContainer = ContainerProps::containerToString(amnezia::DockerContainer::Xray);
|
||||
const QString protoKey = ProtocolProps::protoToString(amnezia::Proto::Xray);
|
||||
|
||||
QJsonArray inbounds;
|
||||
QJsonObject socksInbound;
|
||||
socksInbound["listen"] = "127.0.0.1";
|
||||
socksInbound["port"] = 10808;
|
||||
socksInbound["protocol"] = "socks";
|
||||
|
||||
QJsonObject settings;
|
||||
settings["udp"] = true;
|
||||
socksInbound["settings"] = settings;
|
||||
|
||||
inbounds.append(socksInbound);
|
||||
resultConfig["inbounds"] = inbounds;
|
||||
|
||||
ProxyLogger::getInstance().debug("Successfully added SOCKS inbound configuration (port: 10808)");
|
||||
return resultConfig;
|
||||
}
|
||||
|
||||
bool ConfigManager::addConfigs(const QStringList &serializedConfigs)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Adding %1 new config(s)").arg(serializedConfigs.size()));
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
QJsonObject configs = configsInfo["configs"].toObject();
|
||||
QString activeUuid = getActiveConfigUuid();
|
||||
QString firstUuid;
|
||||
|
||||
QSet<QString> existingConfigs;
|
||||
for (auto it = configs.begin(); it != configs.end(); ++it) {
|
||||
QJsonObject configInfo = it.value().toObject();
|
||||
existingConfigs.insert(configInfo["serializedConfig"].toString());
|
||||
}
|
||||
|
||||
for (const QString &serializedConfig : serializedConfigs)
|
||||
{
|
||||
if (existingConfigs.contains(serializedConfig)) {
|
||||
ProxyLogger::getInstance().info("Skipping duplicate config");
|
||||
for (const QJsonValue &value : containers) {
|
||||
const QJsonObject container = value.toObject();
|
||||
if (container.value(amnezia::config_key::container).toString() != targetContainer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString uuid = generateUuid();
|
||||
ProxyLogger::getInstance().debug(QString("Generated new UUID: %1").arg(uuid));
|
||||
|
||||
if (firstUuid.isEmpty()) {
|
||||
firstUuid = uuid;
|
||||
}
|
||||
|
||||
QString prefix;
|
||||
QString errorMsg;
|
||||
ProxyLogger::getInstance().debug(QString("Deserializing config: %1").arg(serializedConfig.left(50) + "..."));
|
||||
QJsonObject config = deserializeConfig(serializedConfig, &prefix, &errorMsg);
|
||||
|
||||
if (!errorMsg.isEmpty()) {
|
||||
ProxyLogger::getInstance().error(QString("Failed to deserialize config: %1").arg(errorMsg));
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject currentConfigInfo;
|
||||
currentConfigInfo["created"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
currentConfigInfo["lastUsed"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
currentConfigInfo["protocol"] = getProtocolFromSerializedConfig(serializedConfig);
|
||||
currentConfigInfo["serializedConfig"] = serializedConfig;
|
||||
currentConfigInfo["name"] = prefix.isEmpty() ? uuid : prefix;
|
||||
currentConfigInfo["isActive"] = false;
|
||||
|
||||
ProxyLogger::getInstance().info(QString("Adding config: UUID=%1, Protocol=%2, Name=%3")
|
||||
.arg(uuid)
|
||||
.arg(currentConfigInfo["protocol"].toString())
|
||||
.arg(currentConfigInfo["name"].toString()));
|
||||
|
||||
configs[uuid] = currentConfigInfo;
|
||||
}
|
||||
|
||||
configsInfo["configs"] = configs;
|
||||
ProxyLogger::getInstance().debug("Writing updated configs info to file");
|
||||
if (!writeConfigsInfo(configsInfo)) {
|
||||
ProxyLogger::getInstance().error("Failed to write configs info");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there's no active config, activate the first added one
|
||||
if (activeUuid.isEmpty() && !firstUuid.isEmpty())
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("No active config, activating first added config: %1").arg(firstUuid));
|
||||
return activateConfig(firstUuid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigManager::removeConfig(const QString &uuid)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Removing config with UUID: %1").arg(uuid));
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
QJsonObject configs = configsInfo["configs"].toObject();
|
||||
|
||||
// Check if config exists
|
||||
if (!configs.contains(uuid))
|
||||
{
|
||||
ProxyLogger::getInstance().warning(QString("Config with UUID %1 not found").arg(uuid));
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject configToRemove = configs[uuid].toObject();
|
||||
ProxyLogger::getInstance().info(QString("Removing config: Name=%1, Protocol=%2")
|
||||
.arg(configToRemove["name"].toString())
|
||||
.arg(configToRemove["protocol"].toString()));
|
||||
|
||||
// Store current active config UUID
|
||||
bool needToActivateNew = (getActiveConfigUuid() == uuid);
|
||||
|
||||
// Remove config from the list
|
||||
configs.remove(uuid);
|
||||
|
||||
// Save updated configs list (without changing activeConfigUuid)
|
||||
configsInfo["configs"] = configs;
|
||||
ProxyLogger::getInstance().debug("Writing updated configs info to file");
|
||||
if (!writeConfigsInfo(configsInfo))
|
||||
{
|
||||
ProxyLogger::getInstance().error("Failed to write configs info");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If active config was removed, activate a new one
|
||||
if (needToActivateNew)
|
||||
{
|
||||
ProxyLogger::getInstance().info("Removed active config, need to activate a new one");
|
||||
if (configs.isEmpty())
|
||||
{
|
||||
ProxyLogger::getInstance().info("No configs left, clearing active config");
|
||||
if (!activateConfig(QString()))
|
||||
{
|
||||
ProxyLogger::getInstance().error("Failed to clear active config");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString newActiveUuid = configs.keys().first();
|
||||
ProxyLogger::getInstance().info(QString("Activating new config: %1").arg(newActiveUuid));
|
||||
if (!activateConfig(newActiveUuid))
|
||||
{
|
||||
ProxyLogger::getInstance().error(QString("Failed to activate new config: %1").arg(newActiveUuid));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigManager::activateConfig(const QString &uuid)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Activating config: %1").arg(uuid.isEmpty() ? "none" : uuid));
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
QJsonObject configs = configsInfo["configs"].toObject();
|
||||
|
||||
// Reset isActive flag for all configs
|
||||
for (auto it = configs.begin(); it != configs.end(); ++it) {
|
||||
QJsonObject config = it.value().toObject();
|
||||
config["isActive"] = false;
|
||||
it.value() = config;
|
||||
}
|
||||
|
||||
// If uuid is empty, just reset active config
|
||||
if (uuid.isEmpty())
|
||||
{
|
||||
ProxyLogger::getInstance().info("Resetting active config");
|
||||
m_activeConfigUuid = QString();
|
||||
configsInfo["activeConfigUuid"] = QString();
|
||||
configsInfo["configs"] = configs;
|
||||
|
||||
// Write changes to the configs info file
|
||||
if (!writeConfigsInfo(configsInfo)) {
|
||||
ProxyLogger::getInstance().error("Failed to write configs info file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the active config file
|
||||
ProxyLogger::getInstance().debug("Removing active config file");
|
||||
return removeActiveConfigFile();
|
||||
}
|
||||
|
||||
// Check if config exists
|
||||
if (!configs.contains(uuid))
|
||||
{
|
||||
ProxyLogger::getInstance().error(QString("Config with UUID %1 not found").arg(uuid));
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject currentConfigInfo = configs[uuid].toObject();
|
||||
ProxyLogger::getInstance().info(QString("Activating config: Name=%1, Protocol=%2")
|
||||
.arg(currentConfigInfo["name"].toString())
|
||||
.arg(currentConfigInfo["protocol"].toString()));
|
||||
|
||||
QString serializedConfig = currentConfigInfo["serializedConfig"].toString();
|
||||
|
||||
// Deserialize config and add inbounds
|
||||
QString prefix;
|
||||
QString errorMsg;
|
||||
ProxyLogger::getInstance().debug("Deserializing config for activation");
|
||||
QJsonObject currentConfig = deserializeConfig(serializedConfig, &prefix, &errorMsg);
|
||||
if (currentConfig.isEmpty())
|
||||
{
|
||||
ProxyLogger::getInstance().error(QString("Failed to deserialize config: %1").arg(errorMsg));
|
||||
return false;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Adding inbounds to config");
|
||||
currentConfig = addInbounds(currentConfig);
|
||||
|
||||
// Update lastUsed and isActive
|
||||
currentConfigInfo["lastUsed"] = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
currentConfigInfo["isActive"] = true;
|
||||
configs[uuid] = currentConfigInfo;
|
||||
configsInfo["configs"] = configs;
|
||||
|
||||
// Update active config
|
||||
m_activeConfigUuid = uuid;
|
||||
configsInfo["activeConfigUuid"] = uuid;
|
||||
|
||||
// Save changes
|
||||
ProxyLogger::getInstance().debug("Writing updated configs info");
|
||||
if (!writeConfigsInfo(configsInfo))
|
||||
{
|
||||
ProxyLogger::getInstance().error("Failed to write configs info file");
|
||||
return false;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Writing new active config file");
|
||||
return writeActiveConfig(currentConfig);
|
||||
}
|
||||
|
||||
QJsonObject ConfigManager::getActiveConfig() const
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Getting active config info");
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
QJsonObject configs = configsInfo["configs"].toObject();
|
||||
QString activeUuid = getActiveConfigUuid();
|
||||
|
||||
if (activeUuid.isEmpty() || !configs.contains(activeUuid)) {
|
||||
ProxyLogger::getInstance().debug("No active config found");
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug(QString("Retrieved active config info for UUID: %1").arg(activeUuid));
|
||||
QJsonObject result = configs[activeUuid].toObject();
|
||||
result["id"] = activeUuid;
|
||||
return result;
|
||||
}
|
||||
|
||||
QMap<QString, QJsonObject> ConfigManager::getAllConfigs() const
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Getting all configs");
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
QJsonObject configs = configsInfo["configs"].toObject();
|
||||
|
||||
QMap<QString, QJsonObject> result;
|
||||
for (auto it = configs.begin(); it != configs.end(); ++it)
|
||||
{
|
||||
result[it.key()] = it.value().toObject();
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug(QString("Retrieved %1 configs").arg(result.size()));
|
||||
return result;
|
||||
}
|
||||
|
||||
QMap<QString, QJsonObject> ConfigManager::getConfigsByUuids(const QStringList &uuids) const
|
||||
{
|
||||
ProxyLogger::getInstance().debug(QString("Getting configs for %1 UUIDs").arg(uuids.size()));
|
||||
QMap<QString, QJsonObject> allConfigs = getAllConfigs();
|
||||
if (uuids.isEmpty())
|
||||
{
|
||||
ProxyLogger::getInstance().debug("UUID list is empty, returning all configs");
|
||||
return allConfigs;
|
||||
}
|
||||
|
||||
QMap<QString, QJsonObject> result;
|
||||
for (const QString &uuid : uuids)
|
||||
{
|
||||
if (allConfigs.contains(uuid))
|
||||
{
|
||||
ProxyLogger::getInstance().debug(QString("Found config for UUID: %1").arg(uuid));
|
||||
result[uuid] = allConfigs[uuid];
|
||||
}
|
||||
else
|
||||
{
|
||||
ProxyLogger::getInstance().warning(QString("Config not found for UUID: %1").arg(uuid));
|
||||
result[uuid] = QJsonObject();
|
||||
const QJsonObject proto = container.value(protoKey).toObject();
|
||||
const QString serialized = proto.value(amnezia::config_key::last_config).toString();
|
||||
if (!serialized.isEmpty()) {
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug(QString("Retrieved %1 configs out of %2 requested").arg(result.size()).arg(uuids.size()));
|
||||
return result;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ConfigManager::updateAllConfigs(const QStringList &serializedConfigs)
|
||||
QString ConfigManager::tempDirectory() const
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Updating all configs with %1 new config(s)").arg(serializedConfigs.size()));
|
||||
|
||||
ProxyLogger::getInstance().debug("Clearing existing configs");
|
||||
if (!clearConfigs()) {
|
||||
ProxyLogger::getInstance().error("Failed to clear existing configs");
|
||||
return false;
|
||||
const QString baseDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
if (baseDir.isEmpty()) {
|
||||
return QDir::temp().filePath(QStringLiteral("amnezia_local_proxy"));
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Adding new configs");
|
||||
bool success = addConfigs(serializedConfigs);
|
||||
if (success) {
|
||||
ProxyLogger::getInstance().info("Successfully updated all configs");
|
||||
} else {
|
||||
ProxyLogger::getInstance().error("Failed to add new configs");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ConfigManager::clearConfigs()
|
||||
{
|
||||
ProxyLogger::getInstance().info("Clearing all configs");
|
||||
QJsonObject configsInfo = readConfigsInfo();
|
||||
configsInfo["configs"] = QJsonObject();
|
||||
|
||||
if (!writeConfigsInfo(configsInfo)) {
|
||||
ProxyLogger::getInstance().error("Failed to clear configs info");
|
||||
return false;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().debug("Resetting active config");
|
||||
bool success = activateConfig(QString());
|
||||
if (success) {
|
||||
ProxyLogger::getInstance().info("Successfully cleared all configs");
|
||||
} else {
|
||||
ProxyLogger::getInstance().error("Failed to reset active config");
|
||||
}
|
||||
return success;
|
||||
return QDir(baseDir).filePath(QStringLiteral("local_proxy"));
|
||||
}
|
||||
@@ -1,47 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QMap>
|
||||
|
||||
class Settings;
|
||||
|
||||
class ConfigManager {
|
||||
public:
|
||||
ConfigManager();
|
||||
struct ConfigData {
|
||||
QString ownerUuid;
|
||||
QString serverName;
|
||||
QString serializedConfig;
|
||||
QJsonObject parsedConfig;
|
||||
};
|
||||
|
||||
// Main config operations
|
||||
bool addConfigs(const QStringList &serializedConfigs);
|
||||
bool removeConfig(const QString &uuid);
|
||||
bool activateConfig(const QString &uuid);
|
||||
bool updateAllConfigs(const QStringList &serializedConfigs);
|
||||
bool clearConfigs();
|
||||
explicit ConfigManager(const std::shared_ptr<Settings> &settings);
|
||||
|
||||
// Information retrieval
|
||||
QString getActiveConfigUuid() const { return m_activeConfigUuid; }
|
||||
QJsonObject getActiveConfig() const;
|
||||
QMap<QString, QJsonObject> getAllConfigs() const;
|
||||
QMap<QString, QJsonObject> getConfigsByUuids(const QStringList &uuids) const;
|
||||
QString getActiveConfigPath() const;
|
||||
int getConfigCount() const { return m_configCount; }
|
||||
std::optional<ConfigData> buildConfig(QString &errorDescription) const;
|
||||
bool writeTempConfig(const QString &serializedConfig, QString &configPath, QString &errorDescription) const;
|
||||
bool removeTempConfig() const;
|
||||
QString tempConfigPath() const;
|
||||
|
||||
private:
|
||||
// File paths
|
||||
QString getConfigsPath() const;
|
||||
QString getConfigsInfoPath() const;
|
||||
std::optional<QJsonObject> findServerByUuid(const QString &uuid) const;
|
||||
std::optional<QString> extractSerializedXrayConfig(const QJsonObject &server) const;
|
||||
QString tempDirectory() const;
|
||||
|
||||
// File operations
|
||||
QJsonObject readConfigsInfo() const;
|
||||
bool writeConfigsInfo(const QJsonObject &configsInfo);
|
||||
QJsonObject readActiveConfig() const;
|
||||
bool writeActiveConfig(const QJsonObject &config);
|
||||
bool removeActiveConfigFile();
|
||||
|
||||
// Helper methods
|
||||
QString generateUuid() const;
|
||||
QString getProtocolFromSerializedConfig(const QString &config) const;
|
||||
QJsonObject deserializeConfig(const QString &configStr, QString *prefix = nullptr, QString *errorMsg = nullptr);
|
||||
QJsonObject addInbounds(const QJsonObject &config);
|
||||
|
||||
QString m_activeConfigUuid;
|
||||
int m_configCount{0};
|
||||
};
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
@@ -1,25 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
class IProxyService {
|
||||
public:
|
||||
virtual ~IProxyService() = default;
|
||||
|
||||
// Config operations
|
||||
virtual QJsonObject getConfig() const = 0;
|
||||
virtual bool updateConfig(const QString& configStr) = 0;
|
||||
virtual QMap<QString, QJsonObject> getAllConfigs() const = 0;
|
||||
virtual QMap<QString, QJsonObject> getConfigsByUuids(const QStringList &uuids) const = 0;
|
||||
virtual bool addConfigs(const QStringList &serializedConfigs) = 0;
|
||||
virtual bool removeConfig(const QString &uuid) = 0;
|
||||
virtual bool activateConfig(const QString &uuid) = 0;
|
||||
virtual QJsonObject getActiveConfig() const = 0;
|
||||
virtual bool updateAllConfigs(const QStringList &serializedConfigs) = 0;
|
||||
virtual int getConfigCount() const = 0;
|
||||
virtual QJsonObject getConfig() = 0;
|
||||
|
||||
// Xray process operations
|
||||
virtual bool startXray() = 0;
|
||||
virtual bool stopXray() = 0;
|
||||
virtual bool isXrayRunning() const = 0;
|
||||
|
||||
@@ -10,15 +10,13 @@
|
||||
|
||||
#include "proxylogger.h"
|
||||
|
||||
ProxyServer::ProxyServer(QObject *parent)
|
||||
ProxyServer::ProxyServer(const std::shared_ptr<Settings> &settings, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_service(new ProxyService(this))
|
||||
, m_service(new ProxyService(settings, this))
|
||||
{
|
||||
const QString logDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/logs";
|
||||
ProxyLogger::getInstance().init(logDir + "/proxy.log");
|
||||
ProxyLogger::getInstance().setLogLevel(ProxyLogger::LogLevel::Info);
|
||||
|
||||
connect(m_service.data(), &ProxyService::configsChanged, this, &ProxyServer::startXrayProcess);
|
||||
}
|
||||
|
||||
ProxyServer::~ProxyServer()
|
||||
|
||||
@@ -3,15 +3,19 @@
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
#include <QSharedPointer>
|
||||
#include "proxyservice.h"
|
||||
#include <memory>
|
||||
|
||||
#include "httpapi.h"
|
||||
#include "proxyservice.h"
|
||||
|
||||
class Settings;
|
||||
|
||||
class ProxyServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProxyServer(QObject *parent = nullptr);
|
||||
explicit ProxyServer(const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
|
||||
~ProxyServer();
|
||||
|
||||
bool start(quint16 port = 8080);
|
||||
|
||||
@@ -1,44 +1,75 @@
|
||||
#include "proxyservice.h"
|
||||
|
||||
#include "proxylogger.h"
|
||||
|
||||
ProxyService::ProxyService(QObject* parent)
|
||||
namespace {
|
||||
|
||||
void logConfigError(const QString &errorMessage)
|
||||
{
|
||||
if (!errorMessage.isEmpty()) {
|
||||
ProxyLogger::getInstance().error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ProxyService::ProxyService(const std::shared_ptr<Settings> &settings, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_configManager(new ConfigManager())
|
||||
, m_configManager(new ConfigManager(settings))
|
||||
, m_xrayController(new XrayController())
|
||||
{
|
||||
ProxyLogger::getInstance().debug("ProxyService initialized");
|
||||
}
|
||||
|
||||
QJsonObject ProxyService::getConfig() const
|
||||
QJsonObject ProxyService::getConfig()
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Getting active config");
|
||||
return m_configManager->getActiveConfig();
|
||||
}
|
||||
|
||||
bool ProxyService::updateConfig(const QString& configStr)
|
||||
{
|
||||
ProxyLogger::getInstance().info("Updating config");
|
||||
bool success = m_configManager->updateAllConfigs({configStr});
|
||||
if (success) {
|
||||
ProxyLogger::getInstance().info("Config updated successfully");
|
||||
emit configsChanged();
|
||||
} else {
|
||||
ProxyLogger::getInstance().error("Failed to update config");
|
||||
if (!m_cachedConfig.isEmpty()) {
|
||||
return m_cachedConfig;
|
||||
}
|
||||
return success;
|
||||
|
||||
QString error;
|
||||
const auto configData = m_configManager->buildConfig(error);
|
||||
if (!configData) {
|
||||
logConfigError(error);
|
||||
return {};
|
||||
}
|
||||
|
||||
m_cachedConfig = configData->parsedConfig;
|
||||
return m_cachedConfig;
|
||||
}
|
||||
|
||||
bool ProxyService::startXray()
|
||||
{
|
||||
ProxyLogger::getInstance().info("Starting Xray");
|
||||
bool success = m_xrayController->start(m_configManager->getActiveConfigPath());
|
||||
|
||||
QString error;
|
||||
const auto configData = m_configManager->buildConfig(error);
|
||||
qDebug() << "configData:" << configData.value().serializedConfig;
|
||||
qDebug() << "configData:" << configData.value().parsedConfig;
|
||||
if (!configData) {
|
||||
logConfigError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString configPath;
|
||||
if (!m_configManager->writeTempConfig(configData->serializedConfig, configPath, error)) {
|
||||
qDebug() << "configPath:" << configPath;
|
||||
logConfigError(error);
|
||||
return false;
|
||||
}
|
||||
qDebug() << "configPath:" << configPath;
|
||||
|
||||
m_cachedConfig = configData->parsedConfig;
|
||||
|
||||
const bool success = m_xrayController->start(configPath);
|
||||
if (success) {
|
||||
ProxyLogger::getInstance().info("Xray started successfully");
|
||||
emit xrayStatusChanged(true);
|
||||
} else {
|
||||
ProxyLogger::getInstance().error("Failed to start Xray");
|
||||
return true;
|
||||
}
|
||||
return success;
|
||||
|
||||
ProxyLogger::getInstance().error(QStringLiteral("Failed to start Xray: %1").arg(m_xrayController->getError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProxyService::stopXray()
|
||||
@@ -47,11 +78,12 @@ bool ProxyService::stopXray()
|
||||
const bool stopped = m_xrayController->stop();
|
||||
if (stopped) {
|
||||
ProxyLogger::getInstance().info("Xray stopped");
|
||||
m_configManager->removeTempConfig();
|
||||
emit xrayStatusChanged(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
ProxyLogger::getInstance().warning(QString("Failed to stop Xray: %1").arg(m_xrayController->getError()));
|
||||
ProxyLogger::getInstance().warning(QStringLiteral("Failed to stop Xray: %1").arg(m_xrayController->getError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -68,121 +100,4 @@ qint64 ProxyService::getXrayProcessId() const
|
||||
QString ProxyService::getXrayError() const
|
||||
{
|
||||
return m_xrayController->getError();
|
||||
}
|
||||
|
||||
QMap<QString, QJsonObject> ProxyService::getAllConfigs() const
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Getting all configs");
|
||||
return m_configManager->getAllConfigs();
|
||||
}
|
||||
|
||||
QMap<QString, QJsonObject> ProxyService::getConfigsByUuids(const QStringList &uuids) const
|
||||
{
|
||||
ProxyLogger::getInstance().debug(QString("Getting configs for UUIDs: %1").arg(uuids.join(", ")));
|
||||
return m_configManager->getConfigsByUuids(uuids);
|
||||
}
|
||||
|
||||
bool ProxyService::addConfigs(const QStringList &serializedConfigs)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Adding %1 new config(s)").arg(serializedConfigs.size()));
|
||||
bool success = m_configManager->addConfigs(serializedConfigs);
|
||||
if (success) {
|
||||
ProxyLogger::getInstance().info("Configs added successfully");
|
||||
emit configsChanged();
|
||||
} else {
|
||||
ProxyLogger::getInstance().error("Failed to add configs");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ProxyService::removeConfig(const QString &uuid)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Removing config with UUID: %1").arg(uuid));
|
||||
|
||||
// Store current active config UUID before removal
|
||||
QString activeUuid = m_configManager->getActiveConfigUuid();
|
||||
|
||||
// Try to remove the config
|
||||
bool removed = m_configManager->removeConfig(uuid);
|
||||
if (removed) {
|
||||
ProxyLogger::getInstance().info("Config removed successfully");
|
||||
emit configsChanged();
|
||||
if (uuid == activeUuid && isXrayRunning()) {
|
||||
ProxyLogger::getInstance().info("Removed active config, restarting Xray");
|
||||
if (!stopXray()) {
|
||||
ProxyLogger::getInstance().warning("Failed to stop Xray after removing active config");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there are any configs left
|
||||
QString newActiveUuid = m_configManager->getActiveConfigUuid();
|
||||
if (!newActiveUuid.isEmpty()) {
|
||||
ProxyLogger::getInstance().info(QString("Starting Xray with new active config: %1").arg(newActiveUuid));
|
||||
return startXray();
|
||||
} else {
|
||||
ProxyLogger::getInstance().info("No configs left after removal");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ProxyLogger::getInstance().error(QString("Failed to remove config with UUID: %1").arg(uuid));
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
bool ProxyService::activateConfig(const QString &uuid)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Activating config with UUID: %1").arg(uuid));
|
||||
if (m_configManager->activateConfig(uuid)) {
|
||||
ProxyLogger::getInstance().info("Config activated successfully");
|
||||
emit configsChanged();
|
||||
// If config is successfully activated, restart Xray
|
||||
if (isXrayRunning()) {
|
||||
ProxyLogger::getInstance().info("Restarting Xray with new config");
|
||||
if (!stopXray()) {
|
||||
ProxyLogger::getInstance().warning("Failed to stop Xray while activating new config");
|
||||
return false;
|
||||
}
|
||||
return startXray();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
ProxyLogger::getInstance().error(QString("Failed to activate config with UUID: %1").arg(uuid));
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject ProxyService::getActiveConfig() const
|
||||
{
|
||||
ProxyLogger::getInstance().debug("Getting active config");
|
||||
return m_configManager->getActiveConfig();
|
||||
}
|
||||
|
||||
bool ProxyService::updateAllConfigs(const QStringList &serializedConfigs)
|
||||
{
|
||||
ProxyLogger::getInstance().info(QString("Updating all configs with %1 new config(s)").arg(serializedConfigs.size()));
|
||||
bool success = m_configManager->updateAllConfigs(serializedConfigs);
|
||||
if (success) {
|
||||
ProxyLogger::getInstance().info("All configs updated successfully");
|
||||
emit configsChanged();
|
||||
if (isXrayRunning()) {
|
||||
ProxyLogger::getInstance().info("Restarting Xray with updated configs");
|
||||
if (!stopXray()) {
|
||||
ProxyLogger::getInstance().warning("Failed to stop Xray while updating configs");
|
||||
return false;
|
||||
}
|
||||
return startXray();
|
||||
}
|
||||
} else {
|
||||
ProxyLogger::getInstance().error("Failed to update all configs");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
QString ProxyService::getActiveConfigUuid() const
|
||||
{
|
||||
return m_configManager->getActiveConfigUuid();
|
||||
}
|
||||
|
||||
int ProxyService::getConfigCount() const
|
||||
{
|
||||
return m_configManager->getConfigCount();
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "iproxyservice.h"
|
||||
#include "configmanager.h"
|
||||
#include "iproxyservice.h"
|
||||
#include "xraycontroller.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
#include <QJsonObject>
|
||||
#include <memory>
|
||||
|
||||
class Settings;
|
||||
|
||||
class ProxyService : public QObject, public IProxyService {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProxyService(QObject* parent = nullptr);
|
||||
explicit ProxyService(const std::shared_ptr<Settings> &settings, QObject* parent = nullptr);
|
||||
~ProxyService() = default;
|
||||
|
||||
QJsonObject getConfig() const override;
|
||||
bool updateConfig(const QString& configStr) override;
|
||||
QMap<QString, QJsonObject> getAllConfigs() const override;
|
||||
QMap<QString, QJsonObject> getConfigsByUuids(const QStringList &uuids) const override;
|
||||
bool addConfigs(const QStringList &serializedConfigs) override;
|
||||
bool removeConfig(const QString &uuid) override;
|
||||
bool activateConfig(const QString &uuid) override;
|
||||
QJsonObject getActiveConfig() const override;
|
||||
bool updateAllConfigs(const QStringList &serializedConfigs) override;
|
||||
QString getActiveConfigUuid() const;
|
||||
int getConfigCount() const override;
|
||||
|
||||
QJsonObject getConfig() override;
|
||||
bool startXray() override;
|
||||
bool stopXray() override;
|
||||
bool isXrayRunning() const override;
|
||||
@@ -32,10 +26,10 @@ public:
|
||||
QString getXrayError() const override;
|
||||
|
||||
signals:
|
||||
void configsChanged();
|
||||
void xrayStatusChanged(bool running);
|
||||
|
||||
private:
|
||||
QScopedPointer<ConfigManager> m_configManager;
|
||||
QScopedPointer<XrayController> m_xrayController;
|
||||
QJsonObject m_cachedConfig;
|
||||
};
|
||||
Reference in New Issue
Block a user