diff --git a/CMakeLists.txt b/CMakeLists.txt index c43cbb1..2132d5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,6 @@ set(PROJECT_SOURCES src/dataStore/Database.cpp src/stats/traffic/TrafficLooper.cpp src/dataStore/ProfileFilter.cpp - src/configs/ConfigBuilder.cpp src/configs/proxy/AbstractBean.cpp src/configs/proxy/Bean2CoreObj_box.cpp diff --git a/include/configs/ConfigBuilder.hpp b/include/configs/ConfigBuilder.hpp deleted file mode 100644 index 2f9b190..0000000 --- a/include/configs/ConfigBuilder.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#pragma once - -#include "include/dataStore/ProxyEntity.hpp" -#include "include/sys/Process.hpp" - -namespace Configs { - enum OSType - { - Unknown = 0, - Linux = 1, - Windows = 2, - Darwin = 3, - }; - - class ExtraCoreData - { - public: - QString path; - QString args; - QString config; - QString configDir; - bool noLog; - }; - - class BuildConfigResult { - public: - QString error; - QJsonObject coreConfig; - std::shared_ptr extraCoreData; - - QList> outboundStats; // all, but not including "bypass" "block" - }; - - class BuildTestConfigResult { - public: - QString error; - QMap fullConfigs; - QMap tag2entID; - QJsonObject coreConfig; - QStringList outboundTags; - }; - - class BuildConfigStatus { - public: - std::shared_ptr result; - std::shared_ptr ent; - int chainID = 0; - bool forTest; - bool forExport; - - // xxList is V2Ray format string list - - QStringList domainListDNSDirect; - - // config format - - QJsonArray routingRules; - QJsonArray inbounds; - QJsonArray outbounds; - QJsonArray endpoints; - }; - - inline OSType getOS() - { -#ifdef Q_OS_MACOS - return Darwin; -#endif -#ifdef Q_OS_LINUX - return Linux; -#endif -#ifdef Q_OS_WIN - return Windows; -#endif - return Unknown; - }; - - bool IsValid(const std::shared_ptr &ent); - - std::shared_ptr BuildTestConfig(const QList>& profiles); - - std::shared_ptr BuildConfig(const std::shared_ptr &ent, bool forTest, bool forExport, int chainID = 0); - - void BuildConfigSingBox(const std::shared_ptr &status); - - QJsonObject BuildDnsObject(QString address, bool tunEnabled); - - QString BuildChain(int chainId, const std::shared_ptr &status); - - QString BuildChainInternal(int chainId, const QList> &ents, - const std::shared_ptr &status); - - void BuildOutbound(const std::shared_ptr &ent, const std::shared_ptr &status, QJsonObject& outbound, const QString& tag); - - inline QString get_jsdelivr_link(QString link) - { - if(dataStore->routing->ruleset_mirror == Mirrors::GITHUB) - return link; - if(auto url = QUrl(link); url.isValid() && url.host() == "raw.githubusercontent.com") - { - QStringList list = url.path().split('/'); - QString result; - switch(dataStore->routing->ruleset_mirror) { - case Mirrors::GCORE: result = "https://gcore.jsdelivr.net/gh"; break; - case Mirrors::QUANTIL: result = "https://quantil.jsdelivr.net/gh"; break; - case Mirrors::FASTLY: result = "https://fastly.jsdelivr.net/gh"; break; - case Mirrors::CDN: result = "https://cdn.jsdelivr.net/gh"; break; - default: result = "https://testingcf.jsdelivr.net/gh"; - } - - int index = 0; - foreach(QString item, list) - { - if(!item.isEmpty()) - { - if(index == 2) - result += "@" + item; - else - result += "/" + item; - index++; - } - } - return result; - } - return link; - } -} // namespace Configs diff --git a/include/configs/baseConfig.h b/include/configs/baseConfig.h index 3850196..e84c118 100644 --- a/include/configs/baseConfig.h +++ b/include/configs/baseConfig.h @@ -13,14 +13,24 @@ namespace Configs class baseConfig : public JsonStore { public: - virtual bool ParseFromLink(const QString& link); + virtual bool ParseFromLink(const QString& link) { + return false; + } - virtual bool ParseFromJson(const QJsonObject& object); + virtual bool ParseFromJson(const QJsonObject& object) { + return false; + } - virtual QString ExportToLink(); + virtual QString ExportToLink() { + return {}; + } - virtual QJsonObject ExportToJson(); + virtual QJsonObject ExportToJson() { + return {}; + } - virtual BuildResult Build(); + virtual BuildResult Build() { + return {{}, "base class function called!"}; + } }; } diff --git a/include/configs/generate.h b/include/configs/generate.h index 991dc7f..735910f 100644 --- a/include/configs/generate.h +++ b/include/configs/generate.h @@ -86,7 +86,7 @@ namespace Configs bool forExport = false; bool tunEnabled = false; bool isResolvedUsed = false; - std::shared_ptr ent = std::make_shared(nullptr, nullptr); + std::shared_ptr ent = std::make_shared(nullptr, nullptr, nullptr); std::shared_ptr buildPrerequisities = std::make_shared(); OSType os; @@ -161,5 +161,5 @@ namespace Configs bool IsValid(const std::shared_ptr &ent); - std::shared_ptr BuildTestConfig(const QList>& profiles); + std::shared_ptr BuildTestConfig(const QList > &profiles); } diff --git a/include/configs/outbounds/anyTLS.h b/include/configs/outbounds/anyTLS.h index 01be158..f3a6639 100644 --- a/include/configs/outbounds/anyTLS.h +++ b/include/configs/outbounds/anyTLS.h @@ -13,7 +13,7 @@ namespace Configs int min_idle_session = 5; std::shared_ptr tls = std::make_shared(); - anyTLS() + anyTLS() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("password", &password, string)); diff --git a/include/configs/outbounds/chain.h b/include/configs/outbounds/chain.h index 10edcef..4e6c0e1 100644 --- a/include/configs/outbounds/chain.h +++ b/include/configs/outbounds/chain.h @@ -8,7 +8,7 @@ namespace Configs public: QList list; // from in to out - chain() + chain() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("list", &list, integerList)); diff --git a/include/configs/outbounds/custom.h b/include/configs/outbounds/custom.h index ce0b109..a9c0b00 100644 --- a/include/configs/outbounds/custom.h +++ b/include/configs/outbounds/custom.h @@ -3,13 +3,13 @@ namespace Configs { - class custom : public outbound + class Custom : public outbound { public: QString config; - QString type; // one of outbound or fullconfig + QString type; // one of outbound or fullconfig TODO use consts - custom() + Custom() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("config", &config, string)); diff --git a/include/configs/outbounds/extracore.h b/include/configs/outbounds/extracore.h index 7086234..ea19d38 100644 --- a/include/configs/outbounds/extracore.h +++ b/include/configs/outbounds/extracore.h @@ -12,7 +12,7 @@ namespace Configs QString extraCoreConf; bool noLogs = false; - extracore() { + extracore() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("socks_address", &socksAddress, itemType::string)); _add(new configItem("socks_port", &socksPort, itemType::integer)); diff --git a/include/configs/outbounds/http.h b/include/configs/outbounds/http.h index ac6ad48..a3c9546 100644 --- a/include/configs/outbounds/http.h +++ b/include/configs/outbounds/http.h @@ -14,7 +14,7 @@ namespace Configs QStringList headers; std::shared_ptr tls = std::make_shared(); - http() + http() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("username", &username, string)); diff --git a/include/configs/outbounds/hysteria.h b/include/configs/outbounds/hysteria.h index 2594e25..e07eaa4 100644 --- a/include/configs/outbounds/hysteria.h +++ b/include/configs/outbounds/hysteria.h @@ -19,7 +19,7 @@ namespace Configs bool disable_mtu_discovery = false; std::shared_ptr tls = std::make_shared(); - hysteria() + hysteria() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("server_ports", &server_ports, stringList)); diff --git a/include/configs/outbounds/hysteria2.h b/include/configs/outbounds/hysteria2.h index 125849a..b463250 100644 --- a/include/configs/outbounds/hysteria2.h +++ b/include/configs/outbounds/hysteria2.h @@ -16,7 +16,7 @@ namespace Configs QString password; std::shared_ptr tls = std::make_shared(); - hysteria2() + hysteria2() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("server_ports", &server_ports, stringList)); diff --git a/include/configs/outbounds/shadowsocks.h b/include/configs/outbounds/shadowsocks.h index 1cf37cb..8c7a435 100644 --- a/include/configs/outbounds/shadowsocks.h +++ b/include/configs/outbounds/shadowsocks.h @@ -17,7 +17,7 @@ namespace Configs bool uot = false; std::shared_ptr multiplex = std::make_shared(); - shadowsocks() + shadowsocks() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("method", &method, string)); diff --git a/include/configs/outbounds/socks.h b/include/configs/outbounds/socks.h index 3581132..25f91e9 100644 --- a/include/configs/outbounds/socks.h +++ b/include/configs/outbounds/socks.h @@ -12,7 +12,7 @@ namespace Configs int version = 5; bool uot = false; - socks() + socks() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("username", &username, string)); diff --git a/include/configs/outbounds/ssh.h b/include/configs/outbounds/ssh.h index 5f4882b..2944f8b 100644 --- a/include/configs/outbounds/ssh.h +++ b/include/configs/outbounds/ssh.h @@ -15,7 +15,7 @@ namespace Configs QStringList host_key_algorithms; QString client_version; - ssh() + ssh() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("user", &user, string)); diff --git a/include/configs/outbounds/tailscale.h b/include/configs/outbounds/tailscale.h index 40d7cf3..005b6b3 100644 --- a/include/configs/outbounds/tailscale.h +++ b/include/configs/outbounds/tailscale.h @@ -18,7 +18,7 @@ namespace Configs bool advertise_exit_node = false; bool globalDNS = false; - tailscale() + tailscale() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("state_directory", &state_directory, itemType::string)); diff --git a/include/configs/outbounds/trojan.h b/include/configs/outbounds/trojan.h index c47691d..50d230e 100644 --- a/include/configs/outbounds/trojan.h +++ b/include/configs/outbounds/trojan.h @@ -14,7 +14,7 @@ namespace Configs std::shared_ptr multiplex = std::make_shared(); std::shared_ptr transport = std::make_shared(); - Trojan() + Trojan() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("password", &password, string)); diff --git a/include/configs/outbounds/tuic.h b/include/configs/outbounds/tuic.h index d7acf1e..c1fe3f9 100644 --- a/include/configs/outbounds/tuic.h +++ b/include/configs/outbounds/tuic.h @@ -20,7 +20,7 @@ namespace Configs QString heartbeat; std::shared_ptr tls = std::make_shared(); - tuic() + tuic() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("uuid", &uuid, string)); diff --git a/include/configs/outbounds/vless.h b/include/configs/outbounds/vless.h index ff41dce..af5e7a7 100644 --- a/include/configs/outbounds/vless.h +++ b/include/configs/outbounds/vless.h @@ -18,7 +18,7 @@ namespace Configs std::shared_ptr multiplex = std::make_shared(); std::shared_ptr transport = std::make_shared(); - vless() + vless() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("uuid", &uuid, string)); diff --git a/include/configs/outbounds/vmess.h b/include/configs/outbounds/vmess.h index 4b3f919..ed02460 100644 --- a/include/configs/outbounds/vmess.h +++ b/include/configs/outbounds/vmess.h @@ -23,7 +23,7 @@ namespace Configs std::shared_ptr transport = std::make_shared(); std::shared_ptr multiplex = std::make_shared(); - vmess() + vmess() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); _add(new configItem("uuid", &uuid, string)); diff --git a/include/configs/outbounds/wireguard.h b/include/configs/outbounds/wireguard.h index 7ecf85b..afd4254 100644 --- a/include/configs/outbounds/wireguard.h +++ b/include/configs/outbounds/wireguard.h @@ -54,7 +54,7 @@ namespace Configs int underload_packet_magic_header = 0; int transport_packet_magic_header = 0; - wireguard() + wireguard() : outbound() { _add(new configItem("commons", dynamic_cast(commons.get()), jsonStore)); diff --git a/include/dataStore/ProxyEntity.hpp b/include/dataStore/ProxyEntity.hpp index c097717..a0bcfc8 100644 --- a/include/dataStore/ProxyEntity.hpp +++ b/include/dataStore/ProxyEntity.hpp @@ -25,32 +25,6 @@ #include "include/configs/proxy/AbstractBean.hpp" #include "include/configs/proxy/ExtraCore.h" -namespace Configs { - class SocksHttpBean; - - class ShadowSocksBean; - - class VMessBean; - - class TrojanVLESSBean; - - class NaiveBean; - - class QUICBean; - - class AnyTLSBean; - - class WireguardBean; - - class TailscaleBean; - - class SSHBean; - - class CustomBean; - - class ChainBean; -}; // namespace Configs - namespace Configs { class ProxyEntity : public JsonStore { public: @@ -68,68 +42,12 @@ namespace Configs { QString full_test_report; - ProxyEntity(Configs::AbstractBean *bean, const QString &type_); - - ProxyEntity(Configs::outbound *outbound, const QString &type_); + ProxyEntity(Configs::outbound *outbound, Configs::AbstractBean *bean, const QString &type_); [[nodiscard]] QString DisplayTestResult() const; [[nodiscard]] QColor DisplayLatencyColor() const; - [[nodiscard]] Configs::ChainBean *ChainBean() const { - return (Configs::ChainBean *) bean.get(); - }; - - [[nodiscard]] Configs::SocksHttpBean *SocksHTTPBean() const { - return (Configs::SocksHttpBean *) bean.get(); - }; - - [[nodiscard]] Configs::ShadowSocksBean *ShadowSocksBean() const { - return (Configs::ShadowSocksBean *) bean.get(); - }; - - [[nodiscard]] Configs::VMessBean *VMessBean() const { - return (Configs::VMessBean *) bean.get(); - }; - - [[nodiscard]] Configs::TrojanVLESSBean *TrojanVLESSBean() const { - return (Configs::TrojanVLESSBean *) bean.get(); - }; - - [[nodiscard]] Configs::NaiveBean *NaiveBean() const { - return (Configs::NaiveBean *) bean.get(); - }; - - [[nodiscard]] Configs::QUICBean *QUICBean() const { - return (Configs::QUICBean *) bean.get(); - }; - - [[nodiscard]] Configs::AnyTLSBean *AnyTLSBean() const { - return (Configs::AnyTLSBean *) bean.get(); - }; - - [[nodiscard]] Configs::WireguardBean *WireguardBean() const { - return (Configs::WireguardBean *) bean.get(); - }; - - [[nodiscard]] Configs::TailscaleBean *TailscaleBean() const - { - return (Configs::TailscaleBean *) bean.get(); - } - - [[nodiscard]] Configs::SSHBean *SSHBean() const { - return (Configs::SSHBean *) bean.get(); - }; - - [[nodiscard]] Configs::CustomBean *CustomBean() const { - return (Configs::CustomBean *) bean.get(); - }; - - [[nodiscard]] Configs::ExtraCoreBean *ExtraCoreBean() const { - return (Configs::ExtraCoreBean *) bean.get(); - }; - - // Outbound getter functions [[nodiscard]] Configs::socks *Socks() const { return dynamic_cast(outbound.get()); }; @@ -182,8 +100,8 @@ namespace Configs { return dynamic_cast(outbound.get()); }; - [[nodiscard]] Configs::custom *Custom() const { - return dynamic_cast(outbound.get()); + [[nodiscard]] Configs::Custom *Custom() const { + return dynamic_cast(outbound.get()); }; [[nodiscard]] Configs::chain *Chain() const { diff --git a/include/global/ConfigItem.hpp b/include/global/ConfigItem.hpp index 6e96c5c..34d7781 100644 --- a/include/global/ConfigItem.hpp +++ b/include/global/ConfigItem.hpp @@ -48,6 +48,8 @@ namespace Configs_ConfigItem { void _add(configItem *item); + void _remove(const QString &key); + QString _name(void *p); std::shared_ptr _get(const QString &name); diff --git a/include/ui/setting/dialog_hotkey.ui b/include/ui/setting/dialog_hotkey.ui index 5bf76bc..05d8207 100644 --- a/include/ui/setting/dialog_hotkey.ui +++ b/include/ui/setting/dialog_hotkey.ui @@ -72,7 +72,7 @@ - + @@ -94,8 +94,8 @@ 0 0 - 380 - 311 + 360 + 264 diff --git a/src/configs/ConfigBuilder.cpp b/src/configs/ConfigBuilder.cpp deleted file mode 100644 index ba41037..0000000 --- a/src/configs/ConfigBuilder.cpp +++ /dev/null @@ -1,991 +0,0 @@ -#include "include/configs/ConfigBuilder.hpp" -#include "include/dataStore/Database.hpp" -#include "include/configs/proxy/includes.h" -#include "include/configs/proxy/Preset.hpp" -#include "include/api/RPC.h" - -#include -#include -#include -namespace Configs { - QString genTunName() { - auto tun_name = "throne-tun"; -#ifdef Q_OS_MACOS - tun_name = ""; -#endif - return tun_name; - } - - void MergeJson(const QJsonObject &custom, QJsonObject &outbound) { - // 合并 - if (custom.isEmpty()) return; - for (const auto &key: custom.keys()) { - if (outbound.contains(key)) { - auto v = custom[key]; - auto v_orig = outbound[key]; - if (v.isObject() && v_orig.isObject()) { // isObject 则合并? - auto vo = v.toObject(); - QJsonObject vo_orig = v_orig.toObject(); - MergeJson(vo, vo_orig); - outbound[key] = vo_orig; - } else { - outbound[key] = v; - } - } else { - outbound[key] = custom[key]; - } - } - } - - - - // Common - - std::shared_ptr BuildConfig(const std::shared_ptr &ent, bool forTest, bool forExport, int chainID) { - auto result = std::make_shared(); - result->extraCoreData = std::make_shared(); - auto status = std::make_shared(); - status->ent = ent; - status->result = result; - status->forTest = forTest; - status->forExport = forExport; - status->chainID = chainID; - - auto customBean = dynamic_cast(ent->bean.get()); - if (customBean != nullptr && customBean->core == "internal-full") { - if (dataStore->spmode_vpn) - { - status->result->error = QObject::tr("Tun mode cannot be used with Custom configs"); - return result; - } - result->coreConfig = QString2QJsonObject(customBean->config_simple); - } else { - BuildConfigSingBox(status); - } - - // apply custom config - MergeJson(QString2QJsonObject(ent->bean->custom_config), result->coreConfig); - - return result; - } - - bool IsValid(const std::shared_ptr& ent) - { - if (ent->type == "chain") - { - for (int eId : ent->ChainBean()->list) - { - auto e = profileManager->GetProfile(eId); - if (e == nullptr) - { - MW_show_log("Null ent in validator"); - return false; - } - if (!IsValid(e)) - { - MW_show_log("Invalid ent in chain: ID=" + QString::number(eId)); - return false; - } - } - return true; - } - QJsonObject conf; - if (ent->type == "custom" && ent->CustomBean()->core == "internal-full") - { - conf = QString2QJsonObject(ent->CustomBean()->config_simple); - } else - { - auto out = ent->bean->BuildCoreObjSingBox(); - auto outArr = QJsonArray{out.outbound}; - auto key = ent->bean->IsEndpoint() ? "endpoints" : "outbounds"; - conf = { - {key, outArr}, - }; - } - bool ok; - auto resp = API::defaultClient->CheckConfig(&ok, QJsonObject2QString(conf, true)); - if (!ok) - { - MW_show_log("Failed to contact the Core: " + resp); - return false; - } - if (resp.isEmpty()) return true; - // else - MW_show_log("Invalid ent " + ent->bean->name + ": " + resp); - return false; - } - - - std::shared_ptr BuildTestConfig(const QList>& profiles) { - auto results = std::make_shared(); - - QJsonArray outboundArray = { - QJsonObject{ - {"type", "direct"}, - {"tag", "direct"} - } - }; - QJsonArray endpointArray = {}; - int index = 0; - - QJsonArray directDomainArray; - for (const auto &item: profiles) { - if (item->type == "extracore") - { - MW_show_log("Skipping ExtraCore conf"); - continue; - } - if (!IsValid(item)) { - MW_show_log("Skipping invalid config: " + item->bean->name); - item->latency = -1; - continue; - } - auto res = BuildConfig(item, true, false, ++index); - if (!res->error.isEmpty()) { - results->error = res->error; - return results; - } - if (item->type == "custom" && item->CustomBean()->core == "internal-full") { - res->coreConfig["inbounds"] = QJsonArray(); - results->fullConfigs[item->id] = QJsonObject2QString(res->coreConfig, true); - continue; - } - - // not full config, process it - if (results->coreConfig.isEmpty()) { - results->coreConfig = res->coreConfig; - } - // add the direct dns domains - for (const auto &rule: res->coreConfig["dns"].toObject()["rules"].toArray()) { - if (rule.toObject().contains("domain")) { - for (const auto &domain: rule.toObject()["domain"].toArray()) { - directDomainArray.append(domain); - } - } - } - // now we add the outbounds of the current config to the final one - auto outbounds = res->coreConfig["outbounds"].toArray(); - if (outbounds.isEmpty()) { - results->error = QString("outbounds is empty for %1").arg(item->bean->name); - return results; - } - auto endpoints = res->coreConfig["endpoints"].toArray(); - for (auto endpoint : endpoints) outbounds.append(endpoint); - for (const auto &outboundRef: outbounds) { - auto outbound = outboundRef.toObject(); - if (outbound["tag"] == "direct" || outbound["tag"] == "block" || outbound["tag"] == "dns-out" || outbound["tag"].toString().startsWith("rout")) continue; - if (outbound["tag"] == "proxy") { - QString tag = "proxy"; - if (index > 1) tag += Int2String(index); - outbound.insert("tag", tag); - if (outbound["type"] == "wireguard" || outbound["type"] == "tailscale") - { - endpointArray.append(outbound); - } else - { - outboundArray.append(outbound); - } - results->outboundTags << tag; - results->tag2entID.insert(tag, item->id); - continue; - } - outboundArray.append(outbound); - } - } - - results->coreConfig["outbounds"] = outboundArray; - results->coreConfig["endpoints"] = endpointArray; - auto dnsObj = results->coreConfig["dns"].toObject(); - auto dnsRulesObj = QJsonArray(); - if (!directDomainArray.empty()) { - dnsRulesObj += QJsonObject{ - {"domain", directDomainArray}, - {"action", "route"}, - {"server", "dns-direct"} - }; - } - dnsObj["rules"] = dnsRulesObj; - results->coreConfig["dns"] = dnsObj; - results->coreConfig["route"] = QJsonObject{ - {"auto_detect_interface", true}, - {"default_domain_resolver", QJsonObject{ - {"server", "dns-direct"}, - {"strategy", dataStore->routing->outbound_domain_strategy}, - }} - }; - - return results; - } - - QString BuildChain(int chainId, const std::shared_ptr &status) { - auto group = profileManager->GetGroup(status->ent->gid); - if (group == nullptr) { - status->result->error = QString("This profile is not in any group, your data may be corrupted."); - return {}; - } - - auto resolveChain = [=](const std::shared_ptr &ent) { - QList> resolved; - if (ent->type == "chain") { - auto list = ent->ChainBean()->list; - std::reverse(std::begin(list), std::end(list)); - for (auto id: list) { - resolved += profileManager->GetProfile(id); - if (resolved.last() == nullptr) { - status->result->error = QString("chain missing ent: %1").arg(id); - break; - } - if (resolved.last()->type == "chain") { - status->result->error = QString("chain in chain is not allowed: %1").arg(id); - break; - } - } - } else { - resolved += ent; - }; - return resolved; - }; - - // Make list - auto ents = resolveChain(status->ent); - if (!status->result->error.isEmpty()) return {}; - - if (group->front_proxy_id >= 0) { - auto fEnt = profileManager->GetProfile(group->front_proxy_id); - if (fEnt == nullptr) { - status->result->error = QString("front proxy ent not found."); - return {}; - } - ents += resolveChain(fEnt); - if (!status->result->error.isEmpty()) return {}; - } - - if (group->landing_proxy_id >= 0) { - auto lEnt = profileManager->GetProfile(group->landing_proxy_id); - if (lEnt == nullptr) { - status->result->error = QString("landing proxy ent not found."); - return {}; - } - ents = resolveChain(lEnt) + ents; - if (!status->result->error.isEmpty()) return {}; - } - - // BuildChain - QString chainTagOut = BuildChainInternal(chainId, ents, status); - - // Chain ent traffic stat - if (ents.length() > 1) { - status->ent->traffic_data->id = status->ent->id; - status->ent->traffic_data->tag = chainTagOut.toStdString(); - status->ent->traffic_data->ignoreForRate = true; - status->result->outboundStats += status->ent->traffic_data; - } - - return chainTagOut; - } - - QString BuildChainInternal(int chainId, const QList> &ents, - const std::shared_ptr &status) { - QString chainTag = "c-" + Int2String(chainId); - QString chainTagOut; - bool lastWasEndpoint = false; - - for (int index = 0; index < ents.length(); index++) { - const auto& ent = ents.at(index); - auto tagOut = chainTag + "-" + Int2String(ent->id) + "-" + Int2String(index); - - // last profile set as "proxy" - if (index == 0) { - tagOut = "proxy"; - } - - if (index > 0) { - // chain rules: past - auto replaced = (lastWasEndpoint ? status->endpoints : status->outbounds).last().toObject(); - replaced["detour"] = tagOut; - ent->traffic_data->isChainTail = true; - (lastWasEndpoint ? status->endpoints : status->outbounds).removeLast(); - (lastWasEndpoint ? status->endpoints : status->outbounds) += replaced; - } else { - // index == 0 means last profile in chain / not chain - chainTagOut = tagOut; - } - - // Outbound - - QJsonObject outbound; - - BuildOutbound(ent, status, outbound, tagOut); - - // apply custom outbound settings - MergeJson(QString2QJsonObject(ent->bean->custom_outbound), outbound); - - // Bypass Lookup for the first profile - auto serverAddress = ent->bean->serverAddress; - - if (auto customBean = dynamic_cast(ent->bean.get()); customBean != nullptr && customBean->core == "internal") { - auto server = QString2QJsonObject(customBean->config_simple)["server"].toString(); - if (!server.isEmpty()) serverAddress = server; - } - - if (!IsIpAddress(serverAddress)) { - status->domainListDNSDirect += serverAddress; - } - - if (ent->bean->IsEndpoint()) - { - status->endpoints += outbound; - lastWasEndpoint = true; - } else - { - status->outbounds += outbound; - lastWasEndpoint = false; - } - } - - return chainTagOut; - } - - void BuildOutbound(const std::shared_ptr &ent, const std::shared_ptr &status, QJsonObject& outbound, const QString& tag) { - if (ent->type == "wireguard") { - if (ent->WireguardBean()->useSystemInterface && !IsAdmin()) { - MW_dialog_message("configBuilder" ,"NeedAdmin"); - status->result->error = "using wireguard system interface requires elevated permissions"; - return; - } - } - - const auto coreR = ent->bean->BuildCoreObjSingBox(); - if (coreR.outbound.isEmpty()) { - status->result->error = "unsupported outbound"; - return; - } - if (!coreR.error.isEmpty()) { // rejected - status->result->error = coreR.error; - return; - } - outbound = coreR.outbound; - - // outbound misc - outbound["tag"] = tag; - ent->traffic_data->id = ent->id; - ent->traffic_data->tag = tag.toStdString(); - status->result->outboundStats += ent->traffic_data; - - // mux common - auto needMux = ent->type == "vmess" || ent->type == "trojan" || ent->type == "vless" || ent->type == "shadowsocks"; - needMux &= dataStore->mux_concurrency > 0; - - auto stream = GetStreamSettings(ent->bean.get()); - if (stream != nullptr) { - if (stream->network == "grpc" || stream->network == "quic" || stream->network == "anytls" || (stream->network == "http" && stream->security == "tls")) { - needMux = false; - } - } - - auto mux_state = ent->bean->mux_state; - if (mux_state == 0) { - if (!dataStore->mux_default_on && !ent->bean->enable_brutal) needMux = false; - } else if (mux_state == 1) { - needMux = true; - } else if (mux_state == 2) { - needMux = false; - } - - if (ent->type == "vless" && outbound["flow"] != "") { - needMux = false; - } - - // common - // apply mux - if (needMux) { - auto muxObj = QJsonObject{ - {"enabled", true}, - {"protocol", dataStore->mux_protocol}, - {"padding", dataStore->mux_padding}, - {"max_streams", dataStore->mux_concurrency}, - }; - if (ent->bean->enable_brutal) { - auto brutalObj = QJsonObject{ - {"enabled", true}, - {"up_mbps", ent->bean->brutal_speed}, - {"down_mbps", ent->bean->brutal_speed}, - }; - muxObj["max_connections"] = 1; - muxObj["brutal"] = brutalObj; - } - outbound["multiplex"] = muxObj; - } - } - - // SingBox - - QJsonObject BuildDnsObject(QString address, bool tunEnabled) - { - bool usingSystemdResolved = false; -#ifdef Q_OS_LINUX - usingSystemdResolved = ReadFileText("/etc/resolv.conf").contains("systemd-resolved"); -#endif - if (address.startsWith("local")) - { - if (tunEnabled && usingSystemdResolved) - { - return { - {"type", "underlying"} - }; - } - if (tunEnabled && getOS() == Darwin) - { - return { - {"type", "udp"}, - {"server", dataStore->core_box_underlying_dns} - }; - } - return { - {"type", "local"} - }; - } - if (address.startsWith("dhcp://")) - { - auto ifcName = address.replace("dhcp://", ""); - if (ifcName == "auto") ifcName = ""; - return { - {"type", "dhcp"}, - {"interface", ifcName}, - }; - } - QString addr = address; - int port = -1; - QString type = "udp"; - QString path = ""; - if (address.startsWith("tcp://")) - { - type = "tcp"; - addr = addr.replace("tcp://", ""); - } - if (address.startsWith("tls://")) - { - type = "tls"; - addr = addr.replace("tls://", ""); - } - if (address.startsWith("quic://")) - { - type = "quic"; - addr = addr.replace("quic://", ""); - } - if (address.startsWith("https://")) - { - type = "https"; - addr = addr.replace("https://", ""); - if (addr.contains("/")) - { - path = addr.split("/").last(); - addr = addr.left(addr.indexOf("/")); - } - } - if (address.startsWith("h3://")) - { - type = "h3"; - addr = addr.replace("h3://", ""); - if (addr.contains("/")) - { - path = addr.split("/").last(); - addr = addr.left(addr.indexOf("/")); - } - } - if (addr.contains(":")) - { - auto spl = addr.split(":"); - addr = spl[0]; - port = spl[1].toInt(); - } - QJsonObject res = { - {"type", type}, - {"server", addr}, - }; - if (port != -1) res["server_port"] = port; - if (!path.isEmpty()) res["path"] = path; - return res; - } - - - void BuildConfigSingBox(const std::shared_ptr &status) { - // Prefetch - auto routeChain = profileManager->GetRouteChain(dataStore->routing->current_route_id); - if (routeChain == nullptr) { - status->result->error = "Routing profile does not exist, try resetting the route profile in Routing Settings"; - return; - } - - // will be removed on November 1st, 2025 - for (auto ruleItem = routeChain->Rules.begin(); ruleItem != routeChain->Rules.end(); ++ruleItem) { - for (auto ruleSetItem = (*ruleItem)->rule_set.begin(); ruleSetItem != (*ruleItem)->rule_set.end(); ++ruleSetItem) { - if ((*ruleSetItem).endsWith("_IP")) { - *ruleSetItem = "geoip-" + (*ruleSetItem).left((*ruleSetItem).length() - 3); - } - if ((*ruleSetItem).endsWith("_SITE")) { - *ruleSetItem = "geosite-" + (*ruleSetItem).left((*ruleSetItem).length() - 5); - } - } - } - routeChain->Save(); - - if (getOS() == Darwin && dataStore->core_box_underlying_dns.isEmpty() && dataStore->spmode_vpn) - { - status->result->error = QObject::tr("Local DNS and Tun mode do not work together, please set an IP to be used as the Local DNS server in the Routing Settings -> Local override"); - return; - } - - // copy for modification - routeChain = std::make_shared(*routeChain); - - // Outbounds - auto tagProxy = BuildChain(status->chainID, status); - if (!status->result->error.isEmpty()) return; - if (status->ent->type == "extracore") - { - auto bean = status->ent->ExtraCoreBean(); - status->result->extraCoreData->path = QFileInfo(bean->extraCorePath).canonicalFilePath(); - status->result->extraCoreData->args = bean->extraCoreArgs; - status->result->extraCoreData->config = bean->extraCoreConf; - status->result->extraCoreData->configDir = GetBasePath(); - status->result->extraCoreData->noLog = bean->noLogs; - routeChain->Rules << RouteRule::get_processPath_direct_rule(status->result->extraCoreData->path); - } - - // Direct domains - bool needDirectDnsRules = false; - QJsonArray directDomains; - QJsonArray directRuleSets; - QJsonArray directSuffixes; - QJsonArray directKeywords; - QJsonArray directRegexes; - - // server addresses - for (const auto &item: status->domainListDNSDirect) { - directDomains.append(item); - needDirectDnsRules = true; - } - - auto sets = routeChain->get_direct_sites(); - for (const auto &item: sets) { - if (item.startsWith("ruleset:")) { - directRuleSets << item.mid(8); - } - if (item.startsWith("domain:")) { - directDomains << item.mid(7); - } - if (item.startsWith("suffix:")) { - directSuffixes << item.mid(7); - } - if (item.startsWith("keyword:")) { - directKeywords << item.mid(8); - } - if (item.startsWith("regex:")) { - directRegexes << item.mid(6); - } - needDirectDnsRules = true; - } - - // Direct IPs - QJsonArray directIPSets; - QJsonArray directIPCIDRs; - - auto directIPraw = routeChain->get_direct_ips(); - for (const auto &item: directIPraw) - { - if (item.startsWith("ruleset:")) - { - directIPSets << item.mid(8); - } - if (item.startsWith("ip:")) - { - directIPCIDRs << item.mid(3); - } - } - - // Inbounds - // mixed-in - if (IsValidPort(dataStore->inbound_socks_port) && !status->forTest) { - QJsonObject inboundObj; - inboundObj["tag"] = "mixed-in"; - inboundObj["type"] = "mixed"; - inboundObj["listen"] = dataStore->inbound_address; - inboundObj["listen_port"] = dataStore->inbound_socks_port; - status->inbounds += inboundObj; - } - - // tun-in - if (dataStore->spmode_vpn && !status->forTest) { - QJsonObject inboundObj; - inboundObj["tag"] = "tun-in"; - inboundObj["type"] = "tun"; - inboundObj["interface_name"] = genTunName(); - inboundObj["auto_route"] = true; - inboundObj["mtu"] = dataStore->vpn_mtu; - inboundObj["stack"] = dataStore->vpn_implementation; - inboundObj["strict_route"] = dataStore->vpn_strict_route; -#ifdef Q_OS_LINUX - inboundObj["auto_redirect"] = true; -#endif - auto tunAddress = QJsonArray{"172.19.0.1/24"}; - if (dataStore->vpn_ipv6) tunAddress += "fdfe:dcba:9876::1/96"; - inboundObj["address"] = tunAddress; - - QJsonArray routeExcludeAddrs = {"127.0.0.0/8"}; - QJsonArray routeExcludeSets; - if (dataStore->enable_tun_routing) - { - for (auto item:directIPCIDRs) routeExcludeAddrs << item; - for (auto item: directIPSets) routeExcludeSets << item; - } - if (routeChain->defaultOutboundID == proxyID) - { - inboundObj["route_exclude_address"] = routeExcludeAddrs; - if (!routeExcludeSets.isEmpty()) inboundObj["route_exclude_address_set"] = routeExcludeSets; - } - status->inbounds += inboundObj; - } - - // ntp - if (dataStore->enable_ntp) { - QJsonObject ntpObj; - ntpObj["enabled"] = true; - ntpObj["server"] = dataStore->ntp_server_address; - ntpObj["server_port"] = dataStore->ntp_server_port; - ntpObj["interval"] = dataStore->ntp_interval; - status->result->coreConfig["ntp"] = ntpObj; - } - - // direct - status->outbounds += QJsonObject{ - {"type", "direct"}, - {"tag", "direct"}, - }; - status->result->outboundStats += std::make_shared("direct"); - - // Hijack - if (dataStore->enable_dns_server && !status->forTest) - { - auto sniffRule = std::make_shared(); - sniffRule->action = "sniff"; - sniffRule->inbound = {"dns-in"}; - - auto redirRule = std::make_shared(); - redirRule->action = "hijack-dns"; - redirRule->inbound = {"dns-in"}; - - routeChain->Rules.prepend(redirRule); - routeChain->Rules.prepend(sniffRule); - } - if (dataStore->enable_redirect && !status->forTest) { - status->inbounds.prepend(QJsonObject{ - {"tag", "hijack"}, - {"type", "direct"}, - {"listen", dataStore->redirect_listen_address}, - {"listen_port", dataStore->redirect_listen_port}, - }); - auto sniffRule = std::make_shared(); - sniffRule->action = "sniff"; - sniffRule->sniffOverrideDest = true; - sniffRule->inbound = {"hijack"}; - routeChain->Rules.prepend(sniffRule); - } - - // custom inbound - if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray()) - - // DNS hijack deps - QJsonArray hijackDomains; - QJsonArray hijackDomainSuffix; - QJsonArray hijackDomainRegex; - QJsonArray hijackGeoAssets; - - // manage routing section - auto routeObj = QJsonObject(); - if (dataStore->spmode_vpn) { - routeObj["auto_detect_interface"] = true; - } - if (!status->forTest) { - if (dataStore->enable_stats) - { - routeObj["find_process"] = true; - } - routeObj["final"] = outboundIDToString(routeChain->defaultOutboundID); - - if (!dataStore->routing->domain_strategy.isEmpty()) - { - auto resolveRule = std::make_shared(); - resolveRule->action = "resolve"; - resolveRule->strategy = dataStore->routing->domain_strategy; - resolveRule->inbound = {"mixed-in", "tun-in"}; - routeChain->Rules.prepend(resolveRule); - } - if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) - { - auto sniffRule = std::make_shared(); - sniffRule->action = "sniff"; - sniffRule->inbound = {"mixed-in", "tun-in"}; - routeChain->Rules.prepend(sniffRule); - } - auto neededOutbounds = routeChain->get_used_outbounds(); - auto neededRuleSets = routeChain->get_used_rule_sets(); - std::map outboundMap; - outboundMap[-1] = "proxy"; - outboundMap[-2] = "direct"; - int suffix = 0; - for (const auto &item: *neededOutbounds) { - if (item < 0) continue; - auto neededEnt = profileManager->GetProfile(item); - if (neededEnt == nullptr) { - status->result->error = "The routing profile is referencing outbounds that no longer exists, consider revising your settings"; - return; - } - QJsonObject currOutbound; - QString tag = "rout-" + Int2String(suffix++); - BuildOutbound(neededEnt, status, currOutbound, tag); - if (neededEnt->type == "wireguard") - { - status->endpoints += currOutbound; - } else - { - status->outbounds += currOutbound; - } - outboundMap[item] = tag; - - // add to dns direct resolve - if (!IsIpAddress(neededEnt->bean->serverAddress)) { - directDomains << neededEnt->bean->serverAddress; - needDirectDnsRules = true; - } - } - auto routeRules = routeChain->get_route_rules(false, outboundMap); - routeObj["rules"] = routeRules; - - if (dataStore->enable_dns_server) { - for (const auto& rule : dataStore->dns_server_rules) { - if (rule.startsWith("ruleset:")) { - hijackGeoAssets << rule.mid(8); - } - if (rule.startsWith("domain:")) { - hijackDomains << rule.mid(7); - } - if (rule.startsWith("suffix:")) { - hijackDomainSuffix << rule.mid(7); - } - if (rule.startsWith("regex:")) { - hijackDomainRegex << rule.mid(6); - } - } - } - for (auto ruleSet : hijackGeoAssets) { - if (!neededRuleSets->contains(ruleSet.toString())) neededRuleSets->append(ruleSet.toString()); - } - - auto ruleSetArray = QJsonArray(); - for (const auto &item: *neededRuleSets) { - if(auto url = QUrl(item); url.isValid() && url.fileName().contains(".srs")) { - ruleSetArray += QJsonObject{ - {"type", "remote"}, - {"tag", get_rule_set_name(item)}, - {"format", "binary"}, - {"url", item}, - }; - } - else - if(ruleSetMap.count(item.toStdString()) > 0) { - ruleSetArray += QJsonObject{ - {"type", "remote"}, - {"tag", item}, - {"format", "binary"}, - {"url", get_jsdelivr_link(QString::fromStdString(ruleSetMap.at(item.toStdString())))}, - }; - } - } - if (dataStore->adblock_enable) { - ruleSetArray += QJsonObject{ - {"type", "remote"}, - {"tag", "throne-adblocksingbox"}, - {"format", "binary"}, - {"url", get_jsdelivr_link("https://raw.githubusercontent.com/217heidai/adblockfilters/main/rules/adblocksingbox.srs")}, - }; - } - routeObj["rule_set"] = ruleSetArray; - } - - // DNS settings - QJsonObject dns; - QJsonArray dnsServers; - QJsonArray dnsRules; - - routeObj["default_domain_resolver"] = QJsonObject{ - {"server", "dns-direct"}, - {"strategy", dataStore->routing->outbound_domain_strategy}, - }; - - // Remote - if (status->ent->type == "tailscale") - { - auto tailDns = QJsonObject{ - {"type", "tailscale"}, - {"tag", "dns-remote"}, - {"endpoint", "proxy"}, - {"accept_default_resolvers", status->ent->TailscaleBean()->globalDNS}, - }; - dnsServers += tailDns; - } else - { - auto remoteDnsObj = BuildDnsObject(dataStore->routing->remote_dns, dataStore->spmode_vpn); - remoteDnsObj["tag"] = "dns-remote"; - remoteDnsObj["domain_resolver"] = "dns-local"; - remoteDnsObj["detour"] = tagProxy; - dnsServers += remoteDnsObj; - } - - // Direct - auto directDNSAddress = dataStore->routing->direct_dns; - auto directDnsObj = BuildDnsObject(directDNSAddress, dataStore->spmode_vpn); - directDnsObj["tag"] = "dns-direct"; - directDnsObj["domain_resolver"] = "dns-local"; - - // default dns server - if (dataStore->routing->dns_final_out == "direct") { - dnsServers.prepend(directDnsObj); - } else { - dnsServers.append(directDnsObj); - } - - // Handle localhost - dnsRules += QJsonObject{ - {"domain", "localhost"}, - {"action", "predefined"}, - {"query_type", "A"}, - {"rcode", "NOERROR"}, - {"answer", "localhost. IN A 127.0.0.1"}, - }; - - dnsRules += QJsonObject{ - {"domain", "localhost"}, - {"action", "predefined"}, - {"query_type", "AAAA"}, - {"rcode", "NOERROR"}, - {"answer", "localhost. IN AAAA ::1"}, - }; - - // Hijack - if (dataStore->enable_dns_server && !status->forTest) { - dnsRules += QJsonObject{ - {"rule_set", hijackGeoAssets}, - {"domain", hijackDomains}, - {"domain_suffix", hijackDomainSuffix}, - {"domain_regex", hijackDomainRegex}, - {"query_type", "A"}, - {"action", "predefined"}, - {"rcode", "NOERROR"}, - {"answer", QString("* IN A %1").arg(dataStore->dns_v4_resp)}, - }; - - if (!dataStore->dns_v6_resp.isEmpty()) - { - dnsRules += QJsonObject{ - {"rule_set", hijackGeoAssets}, - {"domain", hijackDomains}, - {"domain_suffix", hijackDomainSuffix}, - {"domain_regex", hijackDomainRegex}, - {"query_type", "AAAA"}, - {"action", "predefined"}, - {"rcode", "NOERROR"}, - {"answer", QString("* IN AAAA %1").arg(dataStore->dns_v6_resp)}, - }; - } - - status->inbounds.prepend(QJsonObject{ - {"tag", "dns-in"}, - {"type", "direct"}, - {"listen", dataStore->dns_server_listen_lan ? "0.0.0.0" : "127.1.1.1"}, - {"listen_port", dataStore->dns_server_listen_port}, - }); - } - - // Fakedns - if (dataStore->fake_dns) { - dnsServers += QJsonObject{ - {"tag", "dns-fake"}, - {"type", "fakeip"}, - {"inet4_range", "198.18.0.0/15"}, - {"inet6_range", "fc00::/18"}, - }; - dnsRules += QJsonObject{ - {"query_type", QJsonArray{ - "A", - "AAAA" - }}, - {"action", "route"}, - {"server", "dns-fake"} - }; - dns["independent_cache"] = true; - } - - if (needDirectDnsRules) { - dnsRules += QJsonObject{ - {"rule_set", directRuleSets}, - {"domain", directDomains}, - {"domain_suffix", directSuffixes}, - {"domain_keyword", directKeywords}, - {"domain_regex", directRegexes}, - {"action", "route"}, - {"server", "dns-direct"}, - }; - } - - // Underlying DNS - auto dnsLocalAddress = dataStore->core_box_underlying_dns.isEmpty() ? "local" : dataStore->core_box_underlying_dns; - auto dnsLocalObj = BuildDnsObject(dnsLocalAddress, dataStore->spmode_vpn); - dnsLocalObj["tag"] = "dns-local"; - dnsServers += dnsLocalObj; - - dns["servers"] = dnsServers; - dns["rules"] = dnsRules; - - if (dataStore->routing->use_dns_object) { - dns = QString2QJsonObject(dataStore->routing->dns_object); - } - - // experimental - QJsonObject experimentalObj; - QJsonObject clash_api = { - {"default_mode", ""} // dummy to make sure it is created - }; - - if (!status->forTest) - { - if (dataStore->core_box_clash_api > 0){ - clash_api = { - {"external_controller", dataStore->core_box_clash_listen_addr + ":" + Int2String(dataStore->core_box_clash_api)}, - {"secret", dataStore->core_box_clash_api_secret}, - {"external_ui", "dashboard"}, - }; - } - if (dataStore->core_box_clash_api > 0 || dataStore->enable_stats) - { - experimentalObj["clash_api"] = clash_api; - } - - QJsonObject cache_file = { - {"enabled", true}, - {"store_fakeip", true}, - {"store_rdrc", true} - }; - experimentalObj["cache_file"] = cache_file; - } - - status->result->coreConfig.insert("log", QJsonObject{{"level", dataStore->log_level}}); - status->result->coreConfig.insert("certificate", QJsonObject{{"store", dataStore->use_mozilla_certs ? "mozilla" : "system"}}); - status->result->coreConfig.insert("dns", dns); - status->result->coreConfig.insert("inbounds", status->inbounds); - status->result->coreConfig.insert("outbounds", status->outbounds); - status->result->coreConfig.insert("endpoints", status->endpoints); - status->result->coreConfig.insert("route", routeObj); - if (!experimentalObj.isEmpty()) status->result->coreConfig.insert("experimental", experimentalObj); - } -} // namespace Configs diff --git a/src/configs/common/DialFields.cpp b/src/configs/common/DialFields.cpp index 7fadff8..729e7a7 100644 --- a/src/configs/common/DialFields.cpp +++ b/src/configs/common/DialFields.cpp @@ -18,7 +18,7 @@ namespace Configs { } bool DialFields::ParseFromJson(const QJsonObject& object) { - if (object == nullptr) return false; + if (object.isEmpty()) return false; if (object.contains("reuse_addr")) reuse_addr = object["reuse_addr"].toBool(); if (object.contains("connect_timeout")) connect_timeout = object["connect_timeout"].toString(); diff --git a/src/configs/common/TLS.cpp b/src/configs/common/TLS.cpp index 1e2228a..e89e104 100644 --- a/src/configs/common/TLS.cpp +++ b/src/configs/common/TLS.cpp @@ -1,8 +1,6 @@ #include "include/configs/common/TLS.h" #include -#include -#include #include #include "include/configs/common/utils.h" @@ -15,7 +13,6 @@ namespace Configs { auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded)); // handle the common format - fingerPrint = dataStore->utlsFingerprint; if (query.hasQueryItem("fp")) fingerPrint = query.queryItemValue("fp"); if (!fingerPrint.isEmpty()) enabled = true; return true; @@ -44,6 +41,11 @@ namespace Configs { } BuildResult uTLS::Build() { + auto obj = ExportToJson(); + if ((obj.isEmpty() || obj["enabled"].toBool() == false) && !dataStore->utlsFingerprint.isEmpty()) { + obj["enabled"] = true; + obj["fingerprint"] = dataStore->utlsFingerprint; + } return {ExportToJson(), ""}; } @@ -165,6 +167,7 @@ namespace Configs { if (query.hasQueryItem("tls_fragment")) fragment = query.queryItemValue("tls_fragment") == "true"; if (query.hasQueryItem("tls_fragment_fallback_delay")) fragment_fallback_delay = query.queryItemValue("tls_fragment_fallback_delay"); if (query.hasQueryItem("tls_record_fragment")) record_fragment = query.queryItemValue("tls_record_fragment") == "true"; + if (!server_name.isEmpty()) enabled = true; ech->ParseFromLink(link); utls->ParseFromLink(link); reality->ParseFromLink(link); @@ -275,6 +278,10 @@ namespace Configs { } BuildResult TLS::Build() { + auto obj = ExportToJson(); + if (!obj.isEmpty() && obj["enabled"].toBool()) { + if (dataStore->skip_cert) obj["insecure"] = true; + } return {ExportToJson(), ""}; } } diff --git a/src/configs/common/multiplex.cpp b/src/configs/common/multiplex.cpp index 0367216..cf4028b 100644 --- a/src/configs/common/multiplex.cpp +++ b/src/configs/common/multiplex.cpp @@ -1,8 +1,4 @@ #include "include/configs/common/multiplex.h" - -#include -#include - #include "include/configs/common/utils.h" namespace Configs { @@ -19,7 +15,7 @@ namespace Configs { } bool TcpBrutal::ParseFromJson(const QJsonObject& object) { - if (object == nullptr) return false; + if (object.isEmpty()) return false; if (object.contains("enabled")) enabled = object["enabled"].toBool(); if (object.contains("up_mbps")) up_mbps = object["up_mbps"].toInt(); if (object.contains("down_mbps")) down_mbps = object["down_mbps"].toInt(); @@ -56,7 +52,7 @@ namespace Configs { if (query.hasQueryItem("mux")) enabled = query.queryItemValue("mux") == "true"; else unspecified = true; - protocol = query.hasQueryItem("mux_protocol") ? query.queryItemValue("mux_protocol") : "smux"; + if (query.hasQueryItem("mux_protocol")) protocol = query.queryItemValue("mux_protocol"); if (query.hasQueryItem("mux_max_connections")) max_connections = query.queryItemValue("mux_max_connections").toInt(); if (query.hasQueryItem("mux_min_streams")) min_streams = query.queryItemValue("mux_min_streams").toInt(); if (query.hasQueryItem("mux_max_streams")) max_streams = query.queryItemValue("mux_max_streams").toInt(); @@ -66,7 +62,7 @@ namespace Configs { } bool Multiplex::ParseFromJson(const QJsonObject& object) { - if (object == nullptr) + if (object.isEmpty()) { unspecified = true; return false; @@ -111,6 +107,7 @@ namespace Configs { { auto obj = ExportToJson(); if (unspecified && dataStore->mux_default_on) obj["enabled"] = true; + if (!obj["enabled"].toBool()) return {{}, ""}; if (protocol.isEmpty()) obj["protocol"] = dataStore->mux_protocol; if (max_streams == 0 && max_connections == 0 && min_streams == 0) obj["max_streams"] = dataStore->mux_concurrency; if (dataStore->mux_padding) obj["padding"] = true; diff --git a/src/configs/generate.cpp b/src/configs/generate.cpp index c5c2782..b5e6f0a 100644 --- a/src/configs/generate.cpp +++ b/src/configs/generate.cpp @@ -1,15 +1,12 @@ #include "include/configs/generate.h" #include "include/dataStore/Database.hpp" #include "include/configs/proxy/includes.h" -#include "include/configs/proxy/Preset.hpp" #include "include/api/RPC.h" #include "include/global/Configs.hpp" #include "include/global/Utils.hpp" #include -#include #include -#include namespace Configs { @@ -340,28 +337,30 @@ namespace Configs { QJsonArray servers; QJsonArray rules; // remote - if (isTailscale) - { - auto tailscale = ctx->ent->Tailscale(); - if (tailscale == nullptr) + if (!ctx->forTest) { + if (isTailscale) { - ctx->error = "Corrupted state, needed tailscale been but could not cast"; - return; + auto tailscale = ctx->ent->Tailscale(); + if (tailscale == nullptr) + { + ctx->error = "Corrupted state, needed tailscale been but could not cast"; + return; + } + auto tailDns = QJsonObject{ + {"type", "tailscale"}, + {"tag", "dns-remote"}, + {"endpoint", "proxy"}, + {"accept_default_resolvers", tailscale->globalDNS}, + }; + servers += tailDns; + } else + { + auto remoteDnsObj = buildDnsObj(dataStore->routing->remote_dns, ctx); + remoteDnsObj["tag"] = "dns-remote"; + remoteDnsObj["domain_resolver"] = "dns-local"; + remoteDnsObj["detour"] = "proxy"; + servers += remoteDnsObj; } - auto tailDns = QJsonObject{ - {"type", "tailscale"}, - {"tag", "dns-remote"}, - {"endpoint", "proxy"}, - {"accept_default_resolvers", tailscale->globalDNS}, - }; - servers += tailDns; - } else - { - auto remoteDnsObj = buildDnsObj(dataStore->routing->remote_dns, ctx); - remoteDnsObj["tag"] = "dns-remote"; - remoteDnsObj["domain_resolver"] = "dns-local"; - remoteDnsObj["detour"] = "proxy"; - servers += remoteDnsObj; } // direct @@ -375,21 +374,23 @@ namespace Configs { } // Handle localhost - rules += QJsonObject{ - {"domain", "localhost"}, - {"action", "predefined"}, - {"query_type", "A"}, - {"rcode", "NOERROR"}, - {"answer", "localhost. IN A 127.0.0.1"}, - }; + if (!ctx->forTest) { + rules += QJsonObject{ + {"domain", "localhost"}, + {"action", "predefined"}, + {"query_type", "A"}, + {"rcode", "NOERROR"}, + {"answer", "localhost. IN A 127.0.0.1"}, + }; - rules += QJsonObject{ - {"domain", "localhost"}, - {"action", "predefined"}, - {"query_type", "AAAA"}, - {"rcode", "NOERROR"}, - {"answer", "localhost. IN AAAA ::1"}, - }; + rules += QJsonObject{ + {"domain", "localhost"}, + {"action", "predefined"}, + {"query_type", "AAAA"}, + {"rcode", "NOERROR"}, + {"answer", "localhost. IN AAAA ::1"}, + }; + } // HijackRules if (dataStore->enable_dns_server && !ctx->forTest) @@ -453,7 +454,7 @@ namespace Configs { // Local auto dnsLocalAddress = dataStore->core_box_underlying_dns.isEmpty() ? "local" : dataStore->core_box_underlying_dns; - auto dnsLocalObj = BuildDnsObject(dnsLocalAddress, dataStore->spmode_vpn); + auto dnsLocalObj = buildDnsObj(dnsLocalAddress, ctx); dnsLocalObj["tag"] = "dns-local"; servers += dnsLocalObj; @@ -714,6 +715,9 @@ namespace Configs { route["rules"] = routeRules; route["rule_set"] = ruleSetArray; route["final"] = outboundIDToString(routeChain->defaultOutboundID); + route["default_domain_resolver"] = QJsonObject{ + {"server", "dns-direct"}, + {"strategy", dataStore->routing->outbound_domain_strategy}}; if (dataStore->spmode_vpn) route["auto_detect_interface"] = true; ctx->buildConfigResult->coreConfig["route"] = route; @@ -771,6 +775,8 @@ namespace Configs { auto ctx = std::make_shared(); ctx->ent = ent; + CalculatePrerequisities(ctx); + // log buildLogSections(ctx); // ntp @@ -779,6 +785,7 @@ namespace Configs { buildDNSSection(ctx); if (!ctx->error.isEmpty()) { + MW_show_log("Config build error:" + ctx->error); ctx->buildConfigResult->error = ctx->error; return ctx->buildConfigResult; } @@ -788,6 +795,7 @@ namespace Configs { buildInboundSection(ctx); if (!ctx->error.isEmpty()) { + MW_show_log("Config build error:" + ctx->error); ctx->buildConfigResult->error = ctx->error; return ctx->buildConfigResult; } @@ -795,6 +803,7 @@ namespace Configs { buildOutboundsSection(ctx); if (!ctx->error.isEmpty()) { + MW_show_log("Config build error:" + ctx->error); ctx->buildConfigResult->error = ctx->error; return ctx->buildConfigResult; } @@ -802,6 +811,7 @@ namespace Configs { buildRouteSection(ctx); if (!ctx->error.isEmpty()) { + MW_show_log("Config build error:" + ctx->error); ctx->buildConfigResult->error = ctx->error; return ctx->buildConfigResult; } @@ -809,6 +819,7 @@ namespace Configs { buildExperimentalSection(ctx); if (!ctx->error.isEmpty()) { + MW_show_log("Config build error:" + ctx->error); ctx->buildConfigResult->error = ctx->error; return ctx->buildConfigResult; } @@ -879,10 +890,11 @@ namespace Configs { return false; } - std::shared_ptr BuildTestConfig(const QList>& profiles) + std::shared_ptr BuildTestConfig(const QList > &profiles) { - auto res = std::make_shared(); + auto res = std::make_shared(); auto ctx = std::make_shared(); + ctx->forTest = true; QList entIDs; for (const auto& proxy : profiles) entIDs << proxy->id; ctx->buildPrerequisities->dnsDeps->directDomains = QListStr2QJsonArray(getEntDomains(entIDs, ctx->error)); @@ -896,7 +908,7 @@ namespace Configs { buildCertificateSection(ctx); buildNTPSection(ctx); int suffix = 1; - for (auto item : profiles) + for (const auto& item : profiles) { if (item->type == "extracore") { @@ -930,10 +942,11 @@ namespace Configs { continue; } } - buildOutboundChain(ctx, {item->id}, "proxy-" + Int2String(suffix++), false, true); - auto tag = "proxy-" + Int2String(suffix++) + "-0"; + buildOutboundChain(ctx, {item->id}, "proxy-" + Int2String(suffix), false, true); + auto tag = "proxy-" + Int2String(suffix) + "-0"; res->outboundTags << tag; res->tag2entID.insert(tag, item->id); + suffix++; } ctx->outbounds << QJsonObject{{"type", "direct"}, {"tag", "direct"}}; ctx->buildConfigResult->coreConfig["outbounds"] = ctx->outbounds; diff --git a/src/configs/outbounds/anyTLS.cpp b/src/configs/outbounds/anyTLS.cpp index c73ac59..0979120 100644 --- a/src/configs/outbounds/anyTLS.cpp +++ b/src/configs/outbounds/anyTLS.cpp @@ -75,7 +75,15 @@ namespace Configs { BuildResult anyTLS::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "anytls"; + mergeJsonObjects(object, commons->Build().object); + if (!password.isEmpty()) object["password"] = password; + if (!idle_session_check_interval.isEmpty()) object["idle_session_check_interval"] = idle_session_check_interval; + if (!idle_session_timeout.isEmpty()) object["idle_session_timeout"] = idle_session_timeout; + if (min_idle_session > 0) object["min_idle_session"] = min_idle_session; + object["tls"] = tls->Build().object; + return {object, ""}; } QString anyTLS::DisplayType() diff --git a/src/configs/outbounds/http.cpp b/src/configs/outbounds/http.cpp index bf08e48..cb03cf8 100644 --- a/src/configs/outbounds/http.cpp +++ b/src/configs/outbounds/http.cpp @@ -67,7 +67,15 @@ namespace Configs { } BuildResult http::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "http"; + mergeJsonObjects(object, commons->Build().object); + if (!username.isEmpty()) object["username"] = username; + if (!password.isEmpty()) object["password"] = password; + if (!path.isEmpty()) object["path"] = path; + if (auto headerObj = qStringListToJsonObject(headers); !headerObj.isEmpty()) object["headers"] = headerObj; + if (auto tlsObj = tls->Build().object; !tlsObj.isEmpty()) object["tls"] = tlsObj; + return {object, ""}; } QString http::DisplayType() diff --git a/src/configs/outbounds/hysteria.cpp b/src/configs/outbounds/hysteria.cpp index 919ca8e..a7ae5b8 100644 --- a/src/configs/outbounds/hysteria.cpp +++ b/src/configs/outbounds/hysteria.cpp @@ -134,7 +134,21 @@ namespace Configs { BuildResult hysteria::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "hysteria"; + mergeJsonObjects(object, commons->Build().object); + if (!server_ports.isEmpty()) object["server_ports"] = QListStr2QJsonArray(server_ports); + if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval; + if (up_mbps > 0) object["up_mbps"] = up_mbps; + if (down_mbps > 0) object["down_mbps"] = down_mbps; + if (!obfs.isEmpty()) object["obfs"] = obfs; + if (!auth.isEmpty()) object["auth"] = auth; + if (!auth_str.isEmpty()) object["auth_str"] = auth_str; + if (recv_window_conn > 0) object["recv_window_conn"] = recv_window_conn; + if (recv_window > 0) object["recv_window"] = recv_window; + if (disable_mtu_discovery) object["disable_mtu_discovery"] = disable_mtu_discovery; + if (tls->enabled) object["tls"] = tls->Build().object; + return {object, ""}; } QString hysteria::DisplayType() diff --git a/src/configs/outbounds/hysteria2.cpp b/src/configs/outbounds/hysteria2.cpp index 6615318..8a0aa67 100644 --- a/src/configs/outbounds/hysteria2.cpp +++ b/src/configs/outbounds/hysteria2.cpp @@ -63,7 +63,11 @@ namespace Configs { if (object.contains("hop_interval")) hop_interval = object["hop_interval"].toString(); if (object.contains("up_mbps")) up_mbps = object["up_mbps"].toInt(); if (object.contains("down_mbps")) down_mbps = object["down_mbps"].toInt(); - if (object.contains("obfsType")) obfsType = object["obfsType"].toString(); + if (object.contains("obfs")) { + auto obfsObj = object["obfs"].toObject(); + if (obfsObj.contains("type")) obfsType = obfsObj["type"].toString(); + if (obfsObj.contains("password")) obfsPassword = obfsObj["password"].toString(); + } if (object.contains("obfsPassword")) obfsPassword = object["obfsPassword"].toString(); if (object.contains("password")) password = object["password"].toString(); if (object.contains("tls")) tls->ParseFromJson(object["tls"].toObject()); @@ -127,8 +131,10 @@ namespace Configs { if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval; if (up_mbps > 0) object["up_mbps"] = up_mbps; if (down_mbps > 0) object["down_mbps"] = down_mbps; - if (!obfsType.isEmpty()) object["obfsType"] = obfsType; - if (!obfsPassword.isEmpty()) object["obfsPassword"] = obfsPassword; + QJsonObject obfsObj; + if (!obfsType.isEmpty()) obfsObj["type"] = obfsType; + if (!obfsPassword.isEmpty()) obfsObj["password"] = obfsPassword; + if (!obfsObj.isEmpty()) object["obfs"] = obfsObj; if (!password.isEmpty()) object["password"] = password; if (tls->enabled) object["tls"] = tls->ExportToJson(); return object; @@ -136,7 +142,20 @@ namespace Configs { BuildResult hysteria2::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "hysteria2"; + mergeJsonObjects(object, commons->Build().object); + if (!server_ports.isEmpty()) object["server_ports"] = QListStr2QJsonArray(server_ports); + if (!hop_interval.isEmpty()) object["hop_interval"] = hop_interval; + if (up_mbps > 0) object["up_mbps"] = up_mbps; + if (down_mbps > 0) object["down_mbps"] = down_mbps; + QJsonObject obfsObj; + obfsObj["type"] = obfsType; + obfsObj["password"] = obfsPassword; + if (!obfsObj.isEmpty()) object["obfs"] = obfsObj; + if (!password.isEmpty()) object["password"] = password; + if (tls->enabled) object["tls"] = tls->Build().object; + return {object, ""}; } QString hysteria2::DisplayType() diff --git a/src/configs/outbounds/shadowsocks.cpp b/src/configs/outbounds/shadowsocks.cpp index 2da81a7..5ffca1a 100644 --- a/src/configs/outbounds/shadowsocks.cpp +++ b/src/configs/outbounds/shadowsocks.cpp @@ -112,7 +112,16 @@ namespace Configs { BuildResult shadowsocks::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "shadowsocks"; + mergeJsonObjects(object, commons->Build().object); + if (!method.isEmpty()) object["method"] = method; + if (!password.isEmpty()) object["password"] = password; + if (!plugin.isEmpty()) object["plugin"] = plugin; + if (!plugin_opts.isEmpty()) object["plugin_opts"] = plugin_opts; + if (uot) object["uot"] = uot; + if (auto obj = multiplex->Build().object; !obj.isEmpty()) object["multiplex"] = obj; + return {object, ""}; } QString shadowsocks::DisplayType() diff --git a/src/configs/outbounds/socks.cpp b/src/configs/outbounds/socks.cpp index 1acac98..87b4246 100644 --- a/src/configs/outbounds/socks.cpp +++ b/src/configs/outbounds/socks.cpp @@ -95,7 +95,14 @@ namespace Configs { BuildResult socks::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "socks"; + mergeJsonObjects(object, commons->Build().object); + if (!username.isEmpty()) object["username"] = username; + if (!password.isEmpty()) object["password"] = password; + if (version == 4) object["version"] = "4"; + if (uot) object["uot"] = uot; + return {object, ""}; } QString socks::DisplayType() diff --git a/src/configs/outbounds/ssh.cpp b/src/configs/outbounds/ssh.cpp index fd0521a..5e7c0c6 100644 --- a/src/configs/outbounds/ssh.cpp +++ b/src/configs/outbounds/ssh.cpp @@ -124,7 +124,18 @@ namespace Configs { BuildResult ssh::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "ssh"; + mergeJsonObjects(object, commons->Build().object); + if (!user.isEmpty()) object["user"] = user; + if (!password.isEmpty()) object["password"] = password; + if (!private_key.isEmpty()) object["private_key"] = private_key; + if (!private_key_path.isEmpty()) object["private_key_path"] = private_key_path; + if (!private_key_passphrase.isEmpty()) object["private_key_passphrase"] = private_key_passphrase; + if (!host_key.isEmpty()) object["host_key"] = QListStr2QJsonArray(host_key); + if (!host_key_algorithms.isEmpty()) object["host_key_algorithms"] = QListStr2QJsonArray(host_key_algorithms); + if (!client_version.isEmpty()) object["client_version"] = client_version; + return {object, ""}; } QString ssh::DisplayType() diff --git a/src/configs/outbounds/tailscale.cpp b/src/configs/outbounds/tailscale.cpp index cbdc7d2..7a41972 100644 --- a/src/configs/outbounds/tailscale.cpp +++ b/src/configs/outbounds/tailscale.cpp @@ -98,7 +98,21 @@ namespace Configs { BuildResult tailscale::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "tailscale"; + mergeJsonObjects(object, commons->Build().object); + if (!state_directory.isEmpty()) object["state_directory"] = state_directory; + if (!auth_key.isEmpty()) object["auth_key"] = auth_key; + if (!control_url.isEmpty()) object["control_url"] = control_url; + if (ephemeral) object["ephemeral"] = ephemeral; + if (!hostname.isEmpty()) object["hostname"] = hostname; + if (accept_routes) object["accept_routes"] = accept_routes; + if (!exit_node.isEmpty()) object["exit_node"] = exit_node; + if (exit_node_allow_lan_access) object["exit_node_allow_lan_access"] = exit_node_allow_lan_access; + if (!advertise_routes.isEmpty()) object["advertise_routes"] = QListStr2QJsonArray(advertise_routes); + if (advertise_exit_node) object["advertise_exit_node"] = advertise_exit_node; + if (globalDNS) object["globalDNS"] = globalDNS; + return {object, ""}; } QString tailscale::DisplayAddress() diff --git a/src/configs/outbounds/trojan.cpp b/src/configs/outbounds/trojan.cpp index ce196bb..311f5df 100644 --- a/src/configs/outbounds/trojan.cpp +++ b/src/configs/outbounds/trojan.cpp @@ -56,7 +56,14 @@ namespace Configs { } BuildResult Trojan::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "trojan"; + mergeJsonObjects(object, commons->Build().object); + if (!password.isEmpty()) object["password"] = password; + if (tls->enabled) object["tls"] = tls->Build().object; + if (!transport->type.isEmpty()) object["transport"] = transport->Build().object; + if (auto obj = multiplex->Build().object; !obj.isEmpty()) object["multiplex"] = obj; + return {object, ""}; } QString Trojan::DisplayType() diff --git a/src/configs/outbounds/tuic.cpp b/src/configs/outbounds/tuic.cpp index 7c9aa87..785d3ea 100644 --- a/src/configs/outbounds/tuic.cpp +++ b/src/configs/outbounds/tuic.cpp @@ -86,7 +86,18 @@ namespace Configs { BuildResult tuic::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "tuic"; + mergeJsonObjects(object, commons->Build().object); + if (!uuid.isEmpty()) object["uuid"] = uuid; + if (!password.isEmpty()) object["password"] = password; + if (!congestion_control.isEmpty()) object["congestion_control"] = congestion_control; + if (!udp_relay_mode.isEmpty()) object["udp_relay_mode"] = udp_relay_mode; + if (udp_over_stream) object["udp_over_stream"] = udp_over_stream; + if (zero_rtt_handshake) object["zero_rtt_handshake"] = zero_rtt_handshake; + if (!heartbeat.isEmpty()) object["heartbeat"] = heartbeat; + if (tls->enabled) object["tls"] = tls->Build().object; + return {object, ""}; } QString tuic::DisplayType() diff --git a/src/configs/outbounds/vless.cpp b/src/configs/outbounds/vless.cpp index 8e9e0cf..f3a191d 100644 --- a/src/configs/outbounds/vless.cpp +++ b/src/configs/outbounds/vless.cpp @@ -83,7 +83,16 @@ namespace Configs { BuildResult vless::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "vless"; + mergeJsonObjects(object, commons->Build().object); + if (!uuid.isEmpty()) object["uuid"] = uuid; + if (!flow.isEmpty()) object["flow"] = flow; + if (!packet_encoding.isEmpty()) object["packet_encoding"] = packet_encoding; + if (tls->enabled) object["tls"] = tls->Build().object; + if (!transport->type.isEmpty()) object["transport"] = transport->Build().object; + if (auto obj = multiplex->Build().object; !obj.isEmpty()) object["multiplex"] = obj; + return {object, ""}; } QString vless::DisplayType() diff --git a/src/configs/outbounds/vmess.cpp b/src/configs/outbounds/vmess.cpp index 36c52a0..45076d9 100644 --- a/src/configs/outbounds/vmess.cpp +++ b/src/configs/outbounds/vmess.cpp @@ -128,7 +128,19 @@ namespace Configs { BuildResult vmess::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "vmess"; + mergeJsonObjects(object, commons->Build().object); + if (!uuid.isEmpty()) object["uuid"] = uuid; + if (security != "auto") object["security"] = security; + if (alter_id > 0) object["alter_id"] = alter_id; + if (global_padding) object["global_padding"] = global_padding; + if (authenticated_length) object["authenticated_length"] = authenticated_length; + if (!packet_encoding.isEmpty()) object["packet_encoding"] = packet_encoding; + if (tls->enabled) object["tls"] = tls->Build().object; + if (!transport->type.isEmpty()) object["transport"] = transport->Build().object; + if (auto obj = multiplex->Build().object; !obj.isEmpty()) object["multiplex"] = obj; + return {object, ""}; } QString vmess::DisplayType() diff --git a/src/configs/outbounds/wireguard.cpp b/src/configs/outbounds/wireguard.cpp index a0d3fff..5a1b109 100644 --- a/src/configs/outbounds/wireguard.cpp +++ b/src/configs/outbounds/wireguard.cpp @@ -27,7 +27,7 @@ namespace Configs { } } } - if (query.hasQueryItem("persistent_keepalive")) persistent_keepalive = query.queryItemValue("persistent_keepalive").toInt(); + if (query.hasQueryItem("persistent_keepalive_interval")) persistent_keepalive = query.queryItemValue("persistent_keepalive").toInt(); return true; } @@ -42,7 +42,7 @@ namespace Configs { if (object.contains("reserved")) { reserved = QJsonArray2QListInt(object["reserved"].toArray()); } - if (object.contains("persistent_keepalive")) persistent_keepalive = object["persistent_keepalive"].toInt(); + if (object.contains("persistent_keepalive_interval")) persistent_keepalive = object["persistent_keepalive"].toInt(); return true; } @@ -60,7 +60,7 @@ namespace Configs { } query.addQueryItem("reserved", reservedStr.join("-")); } - if (persistent_keepalive > 0) query.addQueryItem("persistent_keepalive", QString::number(persistent_keepalive)); + if (persistent_keepalive > 0) query.addQueryItem("persistent_keepalive_interval", QString::number(persistent_keepalive)); return query.toString(); } @@ -72,13 +72,21 @@ namespace Configs { if (!public_key.isEmpty()) object["public_key"] = public_key; if (!pre_shared_key.isEmpty()) object["pre_shared_key"] = pre_shared_key; if (!reserved.isEmpty()) object["reserved"] = QListInt2QJsonArray(reserved); - if (persistent_keepalive > 0) object["persistent_keepalive"] = persistent_keepalive; + if (persistent_keepalive > 0) object["persistent_keepalive_interval"] = persistent_keepalive; return object; } BuildResult Peer::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + if (!address.isEmpty()) object["address"] = address; + if (port > 0) object["port"] = port; + if (!public_key.isEmpty()) object["public_key"] = public_key; + if (!pre_shared_key.isEmpty()) object["pre_shared_key"] = pre_shared_key; + if (!reserved.isEmpty()) object["reserved"] = QListInt2QJsonArray(reserved); + if (persistent_keepalive > 0) object["persistent_keepalive_interval"] = persistent_keepalive; + object["allowed_ips"] = QListStr2QJsonArray({"0.0.0.0/0", "::/0"}); + return {object, ""}; } bool wireguard::ParseFromLink(const QString& link) @@ -98,7 +106,7 @@ namespace Configs { QString value = trimmed.mid(eqIdx + 1).trimmed(); if (key == "PrivateKey") private_key = value; - if (key == "Address") address = value.split(","); + if (key == "Address") address = value.replace(" ", "").split(","); if (key == "MTU") mtu = value.toInt(); if (key == "PublicKey") peer->public_key = value; if (key == "PresharedKey") peer->pre_shared_key = value; @@ -216,7 +224,8 @@ namespace Configs { { QJsonObject object; object["type"] = "wireguard"; - mergeJsonObjects(object, commons->ExportToJson()); + if (!commons->name.isEmpty()) object["tag"] = commons->name; + mergeJsonObjects(object, commons->dialFields->ExportToJson()); if (!private_key.isEmpty()) object["private_key"] = private_key; if (!address.isEmpty()) object["address"] = QListStr2QJsonArray(address); if (mtu > 0) object["mtu"] = mtu; @@ -226,7 +235,7 @@ namespace Configs { auto peerObj = peer->ExportToJson(); if (!peerObj.isEmpty()) { - object["peer"] = QJsonArray({peerObj}); + object["peers"] = QJsonArray({peerObj}); } return object; @@ -234,7 +243,22 @@ namespace Configs { BuildResult wireguard::Build() { - return {ExportToJson(), ""}; + QJsonObject object; + object["type"] = "wireguard"; + if (!commons->name.isEmpty()) object["tag"] = commons->name; + mergeJsonObjects(object, commons->dialFields->Build().object); + if (!private_key.isEmpty()) object["private_key"] = private_key; + if (!address.isEmpty()) object["address"] = QListStr2QJsonArray(address); + if (mtu > 0) object["mtu"] = mtu; + if (system) object["system"] = system; + if (worker_count > 0) object["worker_count"] = worker_count; + if (!udp_timeout.isEmpty()) object["udp_timeout"] = udp_timeout; + + auto peerObj = peer->Build().object; + if (!peerObj.isEmpty()) { + object["peers"] = QJsonArray({peerObj}); + } + return {object, ""}; } QString wireguard::DisplayAddress() diff --git a/src/configs/sub/GroupUpdater.cpp b/src/configs/sub/GroupUpdater.cpp index e3a91c8..cb4b2fd 100644 --- a/src/configs/sub/GroupUpdater.cpp +++ b/src/configs/sub/GroupUpdater.cpp @@ -123,14 +123,14 @@ namespace Subscription { // Json if (str.startsWith('{')) { ent = Configs::ProfileManager::NewProxyEntity("custom"); - auto bean = ent->CustomBean(); + auto custom = ent->Custom(); auto obj = QString2QJsonObject(str); if (obj.contains("outbounds")) { - bean->core = "internal-full"; - bean->config_simple = str; + custom->type = "fullconfig"; + custom->config = str; } else if (obj.contains("server")) { - bean->core = "internal"; - bean->config_simple = str; + custom->type = "outbound"; + custom->config = str; } else { return; } @@ -140,49 +140,49 @@ namespace Subscription { if (str.startsWith("socks5://") || str.startsWith("socks4://") || str.startsWith("socks4a://") || str.startsWith("socks://")) { ent = Configs::ProfileManager::NewProxyEntity("socks"); - auto ok = ent->SocksHTTPBean()->TryParseLink(str); + auto ok = ent->Socks()->ParseFromLink(str); if (!ok) return; } // HTTP if (str.startsWith("http://") || str.startsWith("https://")) { ent = Configs::ProfileManager::NewProxyEntity("http"); - auto ok = ent->SocksHTTPBean()->TryParseLink(str); + auto ok = ent->Http()->ParseFromLink(str); if (!ok) return; } // ShadowSocks if (str.startsWith("ss://")) { ent = Configs::ProfileManager::NewProxyEntity("shadowsocks"); - auto ok = ent->ShadowSocksBean()->TryParseLink(str); + auto ok = ent->ShadowSocks()->ParseFromLink(str); if (!ok) return; } // VMess if (str.startsWith("vmess://")) { ent = Configs::ProfileManager::NewProxyEntity("vmess"); - auto ok = ent->VMessBean()->TryParseLink(str); + auto ok = ent->VMess()->ParseFromLink(str); if (!ok) return; } // VLESS if (str.startsWith("vless://")) { ent = Configs::ProfileManager::NewProxyEntity("vless"); - auto ok = ent->TrojanVLESSBean()->TryParseLink(str); + auto ok = ent->VLESS()->ParseFromLink(str); if (!ok) return; } // Trojan if (str.startsWith("trojan://")) { ent = Configs::ProfileManager::NewProxyEntity("trojan"); - auto ok = ent->TrojanVLESSBean()->TryParseLink(str); + auto ok = ent->Trojan()->ParseFromLink(str); if (!ok) return; } // AnyTLS if (str.startsWith("anytls://")) { ent = Configs::ProfileManager::NewProxyEntity("anytls"); - auto ok = ent->AnyTLSBean()->TryParseLink(str); + auto ok = ent->AnyTLS()->ParseFromLink(str); if (!ok) return; } @@ -190,7 +190,7 @@ namespace Subscription { if (str.startsWith("hysteria://")) { needFix = false; ent = Configs::ProfileManager::NewProxyEntity("hysteria"); - auto ok = ent->QUICBean()->TryParseLink(str); + auto ok = ent->Hysteria()->ParseFromLink(str); if (!ok) return; } @@ -198,7 +198,7 @@ namespace Subscription { if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) { needFix = false; ent = Configs::ProfileManager::NewProxyEntity("hysteria2"); - auto ok = ent->QUICBean()->TryParseLink(str); + auto ok = ent->Hysteria2()->ParseFromLink(str); if (!ok) return; } @@ -206,7 +206,7 @@ namespace Subscription { if (str.startsWith("tuic://")) { needFix = false; ent = Configs::ProfileManager::NewProxyEntity("tuic"); - auto ok = ent->QUICBean()->TryParseLink(str); + auto ok = ent->TUIC()->ParseFromLink(str); if (!ok) return; } @@ -214,7 +214,7 @@ namespace Subscription { if (str.startsWith("wg://")) { needFix = false; ent = Configs::ProfileManager::NewProxyEntity("wireguard"); - auto ok = ent->WireguardBean()->TryParseLink(str); + auto ok = ent->Wireguard()->ParseFromLink(str); if (!ok) return; } @@ -222,7 +222,7 @@ namespace Subscription { if (str.startsWith("ssh://")) { needFix = false; ent = Configs::ProfileManager::NewProxyEntity("ssh"); - auto ok = ent->SSHBean()->TryParseLink(str); + auto ok = ent->SSH()->ParseFromLink(str); if (!ok) return; } @@ -266,83 +266,83 @@ namespace Subscription { // SOCKS if (out["type"] == "socks") { ent = Configs::ProfileManager::NewProxyEntity("socks"); - auto ok = ent->SocksHTTPBean()->TryParseJson(out); + auto ok = ent->Socks()->ParseFromJson(out); if (!ok) continue; } // HTTP if (out["type"] == "http") { - auto ok = ent->SocksHTTPBean()->TryParseJson(out); + auto ok = ent->Http()->ParseFromJson(out); if (!ok) continue; } // ShadowSocks if (out["type"] == "shadowsocks") { ent = Configs::ProfileManager::NewProxyEntity("shadowsocks"); - auto ok = ent->ShadowSocksBean()->TryParseJson(out); + auto ok = ent->ShadowSocks()->ParseFromJson(out); if (!ok) continue; } // VMess if (out["type"] == "vmess") { ent = Configs::ProfileManager::NewProxyEntity("vmess"); - auto ok = ent->VMessBean()->TryParseJson(out); + auto ok = ent->VMess()->ParseFromJson(out); if (!ok) continue; } // VLESS if (out["type"] == "vless") { ent = Configs::ProfileManager::NewProxyEntity("vless"); - auto ok = ent->TrojanVLESSBean()->TryParseJson(out); + auto ok = ent->VLESS()->ParseFromJson(out); if (!ok) continue; } // Trojan if (out["type"] == "trojan") { ent = Configs::ProfileManager::NewProxyEntity("trojan"); - auto ok = ent->TrojanVLESSBean()->TryParseJson(out); + auto ok = ent->Trojan()->ParseFromJson(out); if (!ok) continue; } // AnyTLS if (out["type"] == "anytls") { ent = Configs::ProfileManager::NewProxyEntity("anytls"); - auto ok = ent->AnyTLSBean()->TryParseJson(out); + auto ok = ent->AnyTLS()->ParseFromJson(out); if (!ok) continue; } // Hysteria1 if (out["type"] == "hysteria") { ent = Configs::ProfileManager::NewProxyEntity("hysteria"); - auto ok = ent->QUICBean()->TryParseJson(out); + auto ok = ent->Hysteria()->ParseFromJson(out); if (!ok) continue; } // Hysteria2 if (out["type"] == "hysteria2") { ent = Configs::ProfileManager::NewProxyEntity("hysteria2"); - auto ok = ent->QUICBean()->TryParseJson(out); + auto ok = ent->Hysteria2()->ParseFromJson(out); if (!ok) continue; } // TUIC if (out["type"] == "tuic") { ent = Configs::ProfileManager::NewProxyEntity("tuic"); - auto ok = ent->QUICBean()->TryParseJson(out); + auto ok = ent->TUIC()->ParseFromJson(out); if (!ok) continue; } // Wireguard if (out["type"] == "wireguard") { ent = Configs::ProfileManager::NewProxyEntity("wireguard"); - auto ok = ent->WireguardBean()->TryParseJson(out); + auto ok = ent->Wireguard()->ParseFromJson(out); if (!ok) continue; } // SSH if (out["type"] == "ssh") { ent = Configs::ProfileManager::NewProxyEntity("ssh"); - auto ok = ent->SSHBean()->TryParseJson(out); + auto ok = ent->SSH()->ParseFromJson(out); if (!ok) continue; } @@ -355,7 +355,7 @@ namespace Subscription { void RawUpdater::updateWireguardFileConfig(const QString& str) { auto ent = Configs::ProfileManager::NewProxyEntity("wireguard"); - auto ok = ent->WireguardBean()->TryParseLink(str); + auto ok = ent->Wireguard()->ParseFromLink(str); if (!ok) return; updated_order += ent; } @@ -434,23 +434,23 @@ namespace Subscription { if (type == "socks5") type = "socks"; auto ent = Configs::ProfileManager::NewProxyEntity(type); - if (ent->bean->version == -114514) continue; + if (ent->outbound->DisplayType().isEmpty()) continue; bool needFix = false; // common - ent->bean->name = Node2QString(proxy["name"]); - ent->bean->serverAddress = Node2QString(proxy["server"]); - ent->bean->serverPort = Node2Int(proxy["port"]); + ent->outbound->commons->name = Node2QString(proxy["name"]); + ent->outbound->commons->server = Node2QString(proxy["server"]); + ent->outbound->commons->server_port = Node2Int(proxy["port"]); if (type_clash == "ss") { - auto bean = ent->ShadowSocksBean(); + auto bean = ent->ShadowSocks(); bean->method = Node2QString(proxy["cipher"]).replace("dummy", "none"); bean->password = Node2QString(proxy["password"]); // UDP over TCP if (Node2Bool(proxy["udp-over-tcp"])) { bean->uot = Node2Int(proxy["udp-over-tcp-version"]); - if (bean->uot == 0) bean->uot = 2; + if (bean->uot == 0) bean->uot = true; } if (proxy.contains("plugin") && proxy.contains("plugin-opts")) { @@ -480,56 +480,51 @@ namespace Subscription { // sing-mux auto smux = NodeChild(proxy, {"smux"}); - if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->mux_state = 1; - } else if (type == "socks" || type == "http") { - auto bean = ent->SocksHTTPBean(); + if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->multiplex->enabled = true; + } else if (type == "http") { + auto bean = ent->Http(); bean->username = Node2QString(proxy["username"]); bean->password = Node2QString(proxy["password"]); if (type == "http" && Node2Bool(proxy["tls"])) { - bean->stream->security = "tls"; - if (Node2Bool(proxy["skip-cert-verify"])) bean->stream->allow_insecure = true; - bean->stream->sni = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); - bean->stream->alpn = Node2QStringList(proxy["alpn"]).join(","); - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - if (bean->stream->utlsFingerprint.isEmpty()) { - bean->stream->utlsFingerprint = Configs::dataStore->utlsFingerprint; + bean->tls->enabled = true; + if (Node2Bool(proxy["skip-cert-verify"])) bean->tls->insecure = true; + bean->tls->server_name = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); + bean->tls->alpn = Node2QStringList(proxy["alpn"]); + bean->tls->utls->fingerPrint = Node2QString(proxy["client-fingerprint"]); + bean->tls->utls->enabled = true; + if (bean->tls->utls->fingerPrint.isEmpty()) { + bean->tls->utls->fingerPrint = Configs::dataStore->utlsFingerprint; } auto reality = NodeChild(proxy, {"reality-opts"}); if (reality.is_mapping()) { - bean->stream->reality_pbk = Node2QString(reality["public-key"]); - bean->stream->reality_sid = Node2QString(reality["short-id"]); + bean->tls->reality->enabled = true; + bean->tls->reality->public_key = Node2QString(reality["public-key"]); + bean->tls->reality->short_id = Node2QString(reality["short-id"]); } } - } else if (type == "trojan" || type == "vless") { + } else if (type == "socks") { + auto bean = ent->Socks(); + bean->username = Node2QString(proxy["username"]); + bean->password = Node2QString(proxy["password"]); + } else if (type == "trojan") { needFix = true; - auto bean = ent->TrojanVLESSBean(); - if (type == "vless") { - bean->flow = Node2QString(proxy["flow"]); - bean->password = Node2QString(proxy["uuid"]); - // meta packet encoding - if (Node2Bool(proxy["packet-addr"])) { - bean->stream->packet_encoding = "packetaddr"; - } else { - // For VLESS, default to use xudp - bean->stream->packet_encoding = "xudp"; - } - } else { - bean->password = Node2QString(proxy["password"]); - } - bean->stream->security = "tls"; - bean->stream->network = Node2QString(proxy["network"], "tcp"); - bean->stream->sni = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); - bean->stream->alpn = Node2QStringList(proxy["alpn"]).join(","); - bean->stream->allow_insecure = Node2Bool(proxy["skip-cert-verify"]); - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - if (bean->stream->utlsFingerprint.isEmpty()) { - bean->stream->utlsFingerprint = Configs::dataStore->utlsFingerprint; + auto bean = ent->Trojan(); + bean->password = Node2QString(proxy["password"]); + bean->tls->enabled = true; + bean->transport->type = Node2QString(proxy["network"], "tcp"); + bean->tls->server_name = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); + bean->tls->alpn = Node2QStringList(proxy["alpn"]); + bean->tls->insecure = Node2Bool(proxy["skip-cert-verify"]); + bean->tls->utls->fingerPrint = Node2QString(proxy["client-fingerprint"]); + bean->tls->utls->enabled = true; + if (bean->tls->utls->fingerPrint.isEmpty()) { + bean->tls->utls->fingerPrint = Configs::dataStore->utlsFingerprint; } // sing-mux auto smux = NodeChild(proxy, {"smux"}); - if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->mux_state = 1; + if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->multiplex->enabled = true; // opts auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"}); @@ -539,51 +534,57 @@ namespace Subscription { for (auto header: headers.as_map()) { if (Node2QString(header.first).toLower() == "host") { if (header.second.is_string()) - bean->stream->host = Node2QString(header.second); + bean->transport->host = Node2QString(header.second); else if (header.second.is_sequence() && header.second[0].is_string()) - bean->stream->host = Node2QString(header.second[0]); + bean->transport->host = Node2QString(header.second[0]); break; } } } - bean->stream->path = Node2QString(ws["path"]); - bean->stream->ws_early_data_length = Node2Int(ws["max-early-data"]); - bean->stream->ws_early_data_name = Node2QString(ws["early-data-header-name"]); + bean->transport->path = Node2QString(ws["path"]); + bean->transport->max_early_data = Node2Int(ws["max-early-data"]); + bean->transport->early_data_header_name = Node2QString(ws["early-data-header-name"]); } auto grpc = NodeChild(proxy, {"grpc-opts", "grpc-opt"}); if (grpc.is_mapping()) { - bean->stream->path = Node2QString(grpc["grpc-service-name"]); + bean->transport->path = Node2QString(grpc["grpc-service-name"]); } auto reality = NodeChild(proxy, {"reality-opts"}); if (reality.is_mapping()) { - bean->stream->reality_pbk = Node2QString(reality["public-key"]); - bean->stream->reality_sid = Node2QString(reality["short-id"]); + bean->tls->reality->enabled = true; + bean->tls->reality->public_key = Node2QString(reality["public-key"]); + bean->tls->reality->short_id = Node2QString(reality["short-id"]); } - } else if (type == "vmess") { + } else if (type == "vless") { needFix = true; - auto bean = ent->VMessBean(); - bean->uuid = Node2QString(proxy["uuid"]); - bean->aid = Node2Int(proxy["alterId"]); - bean->security = Node2QString(proxy["cipher"], bean->security); - bean->stream->network = Node2QString(proxy["network"], "tcp").replace("h2", "http"); - bean->stream->sni = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); - bean->stream->alpn = Node2QStringList(proxy["alpn"]).join(","); - if (Node2Bool(proxy["tls"])) bean->stream->security = "tls"; - if (Node2Bool(proxy["skip-cert-verify"])) bean->stream->allow_insecure = true; - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - if (bean->stream->utlsFingerprint.isEmpty()) { - bean->stream->utlsFingerprint = Configs::dataStore->utlsFingerprint; + auto bean = ent->VLESS(); + if (type == "vless") { + bean->flow = Node2QString(proxy["flow"]); + bean->uuid = Node2QString(proxy["uuid"]); + // meta packet encoding + if (Node2Bool(proxy["packet-addr"])) { + bean->packet_encoding = "packetaddr"; + } else { + // For VLESS, default to use xudp + bean->packet_encoding = "xudp"; + } + } + bean->tls->enabled = true; + bean->transport->type = Node2QString(proxy["network"], "tcp"); + bean->tls->server_name = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); + bean->tls->alpn = Node2QStringList(proxy["alpn"]); + bean->tls->insecure = Node2Bool(proxy["skip-cert-verify"]); + bean->tls->utls->enabled = true; + bean->tls->utls->fingerPrint = Node2QString(proxy["client-fingerprint"]); + if (bean->tls->utls->fingerPrint.isEmpty()) { + bean->tls->utls->fingerPrint = Configs::dataStore->utlsFingerprint; } // sing-mux auto smux = NodeChild(proxy, {"smux"}); - if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->mux_state = 1; - - // meta packet encoding - if (Node2Bool(proxy["xudp"])) bean->stream->packet_encoding = "xudp"; - if (Node2Bool(proxy["packet-addr"])) bean->stream->packet_encoding = "packetaddr"; + if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->multiplex->enabled = 1; // opts auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"}); @@ -592,100 +593,156 @@ namespace Subscription { if (headers.is_mapping()) { for (auto header: headers.as_map()) { if (Node2QString(header.first).toLower() == "host") { - bean->stream->host = Node2QString(header.second); + if (header.second.is_string()) + bean->transport->host = Node2QString(header.second); + else if (header.second.is_sequence() && header.second[0].is_string()) + bean->transport->host = Node2QString(header.second[0]); break; } } } - bean->stream->path = Node2QString(ws["path"]); - bean->stream->ws_early_data_length = Node2Int(ws["max-early-data"]); - bean->stream->ws_early_data_name = Node2QString(ws["early-data-header-name"]); + bean->transport->path = Node2QString(ws["path"]); + bean->transport->max_early_data = Node2Int(ws["max-early-data"]); + bean->transport->early_data_header_name = Node2QString(ws["early-data-header-name"]); + } + + auto grpc = NodeChild(proxy, {"grpc-opts", "grpc-opt"}); + if (grpc.is_mapping()) { + bean->transport->path = Node2QString(grpc["grpc-service-name"]); + } + + auto reality = NodeChild(proxy, {"reality-opts"}); + if (reality.is_mapping()) { + bean->tls->reality->enabled = true; + bean->tls->reality->public_key = Node2QString(reality["public-key"]); + bean->tls->reality->short_id = Node2QString(reality["short-id"]); + } + } else if (type == "vmess") { + needFix = true; + auto bean = ent->VMess(); + bean->uuid = Node2QString(proxy["uuid"]); + bean->alter_id = Node2Int(proxy["alterId"]); + bean->security = Node2QString(proxy["cipher"], bean->security); + bean->transport->type = Node2QString(proxy["network"], "tcp").replace("h2", "http"); + bean->tls->server_name = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); + bean->tls->alpn = Node2QStringList(proxy["alpn"]); + if (Node2Bool(proxy["tls"])) bean->tls->enabled = true; + if (Node2Bool(proxy["skip-cert-verify"])) bean->tls->insecure = true; + bean->tls->utls->fingerPrint = Node2QString(proxy["client-fingerprint"]); + bean->tls->utls->enabled = true; + if (bean->tls->utls->fingerPrint.isEmpty()) { + bean->tls->utls->fingerPrint = Configs::dataStore->utlsFingerprint; + } + + // sing-mux + auto smux = NodeChild(proxy, {"smux"}); + if (!smux.is_null() && Node2Bool(smux["enabled"])) bean->multiplex->enabled = true; + + // meta packet encoding + if (Node2Bool(proxy["xudp"])) bean->packet_encoding = "xudp"; + if (Node2Bool(proxy["packet-addr"])) bean->packet_encoding = "packetaddr"; + + // opts + auto ws = NodeChild(proxy, {"ws-opts", "ws-opt"}); + if (ws.is_mapping()) { + auto headers = ws["headers"]; + if (headers.is_mapping()) { + for (auto header: headers.as_map()) { + if (Node2QString(header.first).toLower() == "host") { + bean->transport->host = Node2QString(header.second); + break; + } + } + } + bean->transport->path = Node2QString(ws["path"]); + bean->transport->max_early_data = Node2Int(ws["max-early-data"]); + bean->transport->early_data_header_name = Node2QString(ws["early-data-header-name"]); // for Xray if (Node2QString(ws["early-data-header-name"]) == "Sec-WebSocket-Protocol") { - bean->stream->path += "?ed=" + Node2QString(ws["max-early-data"]); + bean->transport->path += "?ed=" + Node2QString(ws["max-early-data"]); } } auto grpc = NodeChild(proxy, {"grpc-opts", "grpc-opt"}); if (grpc.is_mapping()) { - bean->stream->path = Node2QString(grpc["grpc-service-name"]); + bean->transport->path = Node2QString(grpc["grpc-service-name"]); } auto h2 = NodeChild(proxy, {"h2-opts", "h2-opt"}); if (h2.is_mapping()) { auto hosts = h2["host"]; for (auto host: hosts) { - bean->stream->host = Node2QString(host); + bean->transport->host = Node2QString(host); break; } - bean->stream->path = Node2QString(h2["path"]); + bean->transport->path = Node2QString(h2["path"]); } auto tcp_http = NodeChild(proxy, {"http-opts", "http-opt"}); if (tcp_http.is_mapping()) { - bean->stream->network = "tcp"; - bean->stream->header_type = "http"; + bean->transport->type = "http"; auto headers = tcp_http["headers"]; if (headers.is_mapping()) { for (auto header: headers.as_map()) { if (Node2QString(header.first).toLower() == "host") { - bean->stream->host = Node2QString(header.second); + bean->transport->host = Node2QString(header.second); break; } } } auto paths = tcp_http["path"]; if (paths.is_string()) - bean->stream->path = Node2QString(paths); + bean->transport->path = Node2QString(paths); else if (paths.is_sequence() && paths[0].is_string()) - bean->stream->path = Node2QString(paths[0]); + bean->transport->path = Node2QString(paths[0]); } } else if (type == "anytls") { needFix = true; - auto bean = ent->AnyTLSBean(); + auto bean = ent->AnyTLS(); bean->password = Node2QString(proxy["password"]); - bean->stream->security = "tls"; - if (Node2Bool(proxy["skip-cert-verify"])) bean->stream->allow_insecure = true; - bean->stream->sni = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); - bean->stream->alpn = Node2QStringList(proxy["alpn"]).join(","); - bean->stream->utlsFingerprint = Node2QString(proxy["client-fingerprint"]); - if (bean->stream->utlsFingerprint.isEmpty()) { - bean->stream->utlsFingerprint = Configs::dataStore->utlsFingerprint; + bean->tls->enabled = true; + if (Node2Bool(proxy["skip-cert-verify"])) bean->tls->insecure = true; + bean->tls->server_name = FIRST_OR_SECOND(Node2QString(proxy["sni"]), Node2QString(proxy["servername"])); + bean->tls->alpn = Node2QStringList(proxy["alpn"]); + bean->tls->utls->fingerPrint = Node2QString(proxy["client-fingerprint"]); + bean->tls->utls->enabled = true; + if (bean->tls->utls->fingerPrint.isEmpty()) { + bean->tls->utls->fingerPrint = Configs::dataStore->utlsFingerprint; } auto reality = NodeChild(proxy, {"reality-opts"}); if (reality.is_mapping()) { - bean->stream->reality_pbk = Node2QString(reality["public-key"]); - bean->stream->reality_sid = Node2QString(reality["short-id"]); + bean->tls->reality->enabled = true; + bean->tls->reality->public_key = Node2QString(reality["public-key"]); + bean->tls->reality->short_id = Node2QString(reality["short-id"]); } } else if (type == "hysteria") { - auto bean = ent->QUICBean(); + auto bean = ent->Hysteria(); - bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]); + bean->tls->enabled = true; + bean->tls->insecure = Node2Bool(proxy["skip-cert-verify"]); auto alpn = Node2QStringList(proxy["alpn"]); - bean->caText = Node2QString(proxy["ca-str"]); - if (!alpn.isEmpty()) bean->alpn = alpn[0]; - bean->sni = Node2QString(proxy["sni"]); + bean->tls->certificate = Node2QString(proxy["ca-str"]); + if (!alpn.isEmpty()) bean->tls->alpn = {alpn[0]}; + bean->tls->server_name = Node2QString(proxy["sni"]); auto auth_str = FIRST_OR_SECOND(Node2QString(proxy["auth_str"]), Node2QString(proxy["auth-str"])); auto auth = Node2QString(proxy["auth"]); if (!auth_str.isEmpty()) { - bean->authPayloadType = Configs::QUICBean::hysteria_auth_string; - bean->authPayload = auth_str; + bean->auth_str = auth_str; } if (!auth.isEmpty()) { - bean->authPayloadType = Configs::QUICBean::hysteria_auth_base64; - bean->authPayload = auth; + bean->auth = auth; } - bean->obfsPassword = Node2QString(proxy["obfs"]); + bean->obfs = Node2QString(proxy["obfs"]); - if (Node2Bool(proxy["disable_mtu_discovery"]) || Node2Bool(proxy["disable-mtu-discovery"])) bean->disableMtuDiscovery = true; - bean->streamReceiveWindow = Node2Int(proxy["recv-window"]); - bean->connectionReceiveWindow = Node2Int(proxy["recv-window-conn"]); + if (Node2Bool(proxy["disable_mtu_discovery"]) || Node2Bool(proxy["disable-mtu-discovery"])) bean->disable_mtu_discovery = true; + bean->recv_window = Node2Int(proxy["recv-window"]); + bean->recv_window_conn = Node2Int(proxy["recv-window-conn"]); auto upMbps = Node2QString(proxy["up"]).split(" ")[0].toInt(); auto downMbps = Node2QString(proxy["down"]).split(" ")[0].toInt(); - if (upMbps > 0) bean->uploadMbps = upMbps; - if (downMbps > 0) bean->downloadMbps = downMbps; + if (upMbps > 0) bean->up_mbps = upMbps; + if (downMbps > 0) bean->down_mbps = downMbps; auto ports = Node2QString(proxy["ports"]); if (!ports.isEmpty()) { @@ -699,20 +756,21 @@ namespace Subscription { modifiedPort.replace("-", ":"); serverPorts.append(modifiedPort); } - bean->serverPorts = serverPorts; + bean->server_ports = serverPorts; } } else if (type == "hysteria2") { - auto bean = ent->QUICBean(); + auto bean = ent->Hysteria2(); - bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]); - bean->caText = Node2QString(proxy["ca-str"]); - bean->sni = Node2QString(proxy["sni"]); + bean->tls->enabled = true; + bean->tls->insecure = Node2Bool(proxy["skip-cert-verify"]); + bean->tls->certificate = Node2QString(proxy["ca-str"]); + bean->tls->server_name = Node2QString(proxy["sni"]); bean->obfsPassword = Node2QString(proxy["obfs-password"]); bean->password = Node2QString(proxy["password"]); - bean->uploadMbps = Node2QString(proxy["up"]).split(" ")[0].toInt(); - bean->downloadMbps = Node2QString(proxy["down"]).split(" ")[0].toInt(); + bean->up_mbps = Node2QString(proxy["up"]).split(" ")[0].toInt(); + bean->down_mbps = Node2QString(proxy["down"]).split(" ")[0].toInt(); auto ports = Node2QString(proxy["ports"]); if (!ports.isEmpty()) { @@ -726,10 +784,10 @@ namespace Subscription { modifiedPort.replace("-", ":"); serverPorts.append(modifiedPort); } - bean->serverPorts = serverPorts; + bean->server_ports = serverPorts; } } else if (type == "tuic") { - auto bean = ent->QUICBean(); + auto bean = ent->TUIC(); bean->uuid = Node2QString(proxy["uuid"]); bean->password = Node2QString(proxy["password"]); @@ -738,21 +796,22 @@ namespace Subscription { bean->heartbeat = Int2String(Node2Int(proxy["heartbeat-interval"])) + "ms"; } - bean->udpRelayMode = Node2QString(proxy["udp-relay-mode"], bean->udpRelayMode); - bean->congestionControl = Node2QString(proxy["congestion-controller"], bean->congestionControl); + bean->udp_relay_mode = Node2QString(proxy["udp-relay-mode"], "native"); + bean->congestion_control = Node2QString(proxy["congestion-controller"], "bbr"); - bean->disableSni = Node2Bool(proxy["disable-sni"]); - bean->zeroRttHandshake = Node2Bool(proxy["reduce-rtt"]); - bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]); - bean->alpn = Node2QStringList(proxy["alpn"]).join(","); - bean->caText = Node2QString(proxy["ca-str"]); - bean->sni = Node2QString(proxy["sni"]); + bean->tls->enabled = true; + bean->tls->disable_sni = Node2Bool(proxy["disable-sni"]); + bean->zero_rtt_handshake = Node2Bool(proxy["reduce-rtt"]); + bean->tls->insecure = Node2Bool(proxy["skip-cert-verify"]); + bean->tls->alpn = Node2QStringList(proxy["alpn"]); + bean->tls->certificate = Node2QString(proxy["ca-str"]); + bean->tls->server_name = Node2QString(proxy["sni"]); - if (Node2Bool(proxy["udp-over-stream"])) bean->uos = true; + if (Node2Bool(proxy["udp-over-stream"])) bean->udp_over_stream = true; if (!Node2QString(proxy["ip"]).isEmpty()) { - if (bean->sni.isEmpty()) bean->sni = bean->serverAddress; - bean->serverAddress = Node2QString(proxy["ip"]); + if (bean->tls->server_name.isEmpty()) bean->tls->server_name = bean->commons->server; + bean->commons->server = Node2QString(proxy["ip"]); } } else { continue; @@ -762,7 +821,7 @@ namespace Subscription { updated_order += ent; } } catch (const fkyaml::exception &ex) { - runOnUiThread([=,this] { + runOnUiThread([=] { MessageBoxWarning("YAML Exception", ex.what()); }); } diff --git a/src/dataStore/Database.cpp b/src/dataStore/Database.cpp index df33d8f..7c84a22 100644 --- a/src/dataStore/Database.cpp +++ b/src/dataStore/Database.cpp @@ -49,7 +49,7 @@ namespace Configs { continue; } profiles[id] = ent; - if (ent->type == "extracore") extraCorePaths.insert(ent->ExtraCoreBean()->extraCorePath); + if (ent->type == "extracore") extraCorePaths.insert(ent->ExtraCore()->extraCorePath); } // Clear Corrupted profile for (auto id: delProfile) { @@ -117,9 +117,77 @@ namespace Configs { JsonStore::Save(); } + void migrateBeanToOutbound(const std::shared_ptr &ent) + { + if (ent->type == "chain") + { + auto bean = dynamic_cast(ent->bean.get()); + if (bean == nullptr) + { + qDebug() << "Broken state in migrate for chain"; + return; + } + auto chain = ent->Chain(); + if (chain == nullptr) + { + qDebug() << "Invalid state in migrate for chain"; + return; + } + chain->commons->name = bean->name; + chain->list = bean->list; + } else if (ent->type == "custom") + { + auto bean = dynamic_cast(ent->bean.get()); + if (bean == nullptr) + { + qDebug() << "Broken state in migrate for custom"; + return; + } + auto custom = ent->Custom(); + if (custom == nullptr) + { + qDebug() << "Invalid state in migrate for custom"; + return; + } + custom->commons->name = bean->name; + custom->config = bean->config_simple; + custom->type = bean->core == "internal" ? "outbound" : "fullconfig"; + } else if (ent->type == "extracore") + { + auto bean = dynamic_cast(ent->bean.get()); + if (bean == nullptr) + { + qDebug() << "Broken state in migrate for extracore"; + return; + } + auto extraCore = ent->ExtraCore(); + if (extraCore == nullptr) + { + qDebug() << "Invalid state in migrate for extracore"; + return; + } + extraCore->commons->name = bean->name; + extraCore->socksAddress = bean->socksAddress; + extraCore->socksPort = bean->socksPort; + extraCore->extraCorePath = bean->extraCorePath; + extraCore->extraCoreArgs = bean->extraCoreArgs; + extraCore->extraCoreConf = bean->extraCoreConf; + extraCore->noLogs = bean->noLogs; + } else + { + auto beanJson = ent->bean->BuildCoreObjSingBox(); + auto obj = beanJson.outbound; + if (ent->bean->mux_state == 0) obj["multiplex"] = QJsonObject{}; + else if (ent->bean->mux_state == 1) obj["multiplex"] = QJsonObject{{"enabled", true}}; + else if (ent->bean->mux_state == 2) obj["multiplex"] = QJsonObject{{"enabled", false}}; + ent->outbound->ParseFromJson(obj); + ent->outbound->commons->name = ent->bean->name; + } + } + std::shared_ptr ProfileManager::LoadProxyEntity(const QString &jsonPath) { // Load type - ProxyEntity ent0(nullptr, nullptr); + ProxyEntity ent0(nullptr, nullptr, nullptr); ent0.fn = jsonPath; auto validJson = ent0.Load(); auto type = ent0.type; @@ -137,6 +205,15 @@ namespace Configs { ent->load_control_must = true; ent->fn = jsonPath; ent->Load(); + ent->_remove("bean"); + } + + if (!QString2QJsonObject(QString(ent->last_save_content.toStdString().c_str())).contains("outbound")) + { + qDebug() << "migrating" << ent->type; + // migrate + migrateBeanToOutbound(ent); + ent->Save(); } return ent; } @@ -151,48 +228,64 @@ namespace Configs { return routingChain; } - // 新建的不给 fn 和 id - std::shared_ptr ProfileManager::NewProxyEntity(const QString &type) { Configs::AbstractBean *bean; + Configs::outbound *outbound; if (type == "socks") { bean = new Configs::SocksHttpBean(Configs::SocksHttpBean::type_Socks5); + outbound = new Configs::socks(); } else if (type == "http") { bean = new Configs::SocksHttpBean(Configs::SocksHttpBean::type_HTTP); + outbound = new Configs::http(); } else if (type == "shadowsocks") { bean = new Configs::ShadowSocksBean(); + outbound = new Configs::shadowsocks(); } else if (type == "chain") { bean = new Configs::ChainBean(); + outbound = new Configs::chain(); } else if (type == "vmess") { bean = new Configs::VMessBean(); + outbound = new Configs::vmess(); } else if (type == "trojan") { bean = new Configs::TrojanVLESSBean(Configs::TrojanVLESSBean::proxy_Trojan); + outbound = new Configs::Trojan(); } else if (type == "vless") { bean = new Configs::TrojanVLESSBean(Configs::TrojanVLESSBean::proxy_VLESS); + outbound = new Configs::vless(); } else if (type == "hysteria") { bean = new Configs::QUICBean(Configs::QUICBean::proxy_Hysteria); + outbound = new Configs::hysteria(); } else if (type == "hysteria2") { bean = new Configs::QUICBean(Configs::QUICBean::proxy_Hysteria2); + outbound = new Configs::hysteria2(); } else if (type == "tuic") { bean = new Configs::QUICBean(Configs::QUICBean::proxy_TUIC); + outbound = new Configs::tuic(); } else if (type == "anytls") { bean = new Configs::AnyTLSBean(); + outbound = new Configs::anyTLS(); } else if (type == "wireguard") { bean = new Configs::WireguardBean(Configs::WireguardBean()); + outbound = new Configs::wireguard(); } else if (type == "tailscale") { bean = new Configs::TailscaleBean(Configs::TailscaleBean()); + outbound = new Configs::tailscale(); } else if (type == "ssh") { bean = new Configs::SSHBean(Configs::SSHBean()); + outbound = new Configs::ssh(); } else if (type == "custom") { bean = new Configs::CustomBean(); + outbound = new Configs::Custom(); } else if (type == "extracore") { bean = new Configs::ExtraCoreBean(); + outbound = new Configs::extracore(); } else { bean = new Configs::AbstractBean(-114514); + outbound = new Configs::outbound(); } - auto ent = std::make_shared(bean, type); + auto ent = std::make_shared(outbound, bean, type); return ent; } diff --git a/src/dataStore/ProxyEntity.cpp b/src/dataStore/ProxyEntity.cpp index 5e730b5..ef73280 100644 --- a/src/dataStore/ProxyEntity.cpp +++ b/src/dataStore/ProxyEntity.cpp @@ -2,7 +2,8 @@ namespace Configs { - ProxyEntity::ProxyEntity(Configs::AbstractBean *bean, const QString &type_) { + ProxyEntity::ProxyEntity(Configs::outbound *outbound, Configs::AbstractBean *bean, const QString &type_) + { if (type_ != nullptr) this->type = type_; _add(new configItem("type", &type, itemType::string)); @@ -17,22 +18,7 @@ namespace Configs if (bean != nullptr) { this->bean = std::shared_ptr(bean); _add(new configItem("bean", dynamic_cast(bean), itemType::jsonStore)); - _add(new configItem("traffic", dynamic_cast(traffic_data.get()), itemType::jsonStore)); } - }; - - ProxyEntity::ProxyEntity(Configs::outbound *outbound, const QString &type_) - { - if (type_ != nullptr) this->type = type_; - - _add(new configItem("type", &type, itemType::string)); - _add(new configItem("id", &id, itemType::integer)); - _add(new configItem("gid", &gid, itemType::integer)); - _add(new configItem("yc", &latency, itemType::integer)); - _add(new configItem("dl", &dl_speed, itemType::string)); - _add(new configItem("ul", &ul_speed, itemType::string)); - _add(new configItem("report", &full_test_report, itemType::string)); - _add(new configItem("country", &test_country, itemType::string)); if (outbound != nullptr) { this->outbound = std::shared_ptr(outbound); diff --git a/src/global/Configs.cpp b/src/global/Configs.cpp index 9e3b721..43eb40d 100644 --- a/src/global/Configs.cpp +++ b/src/global/Configs.cpp @@ -27,11 +27,14 @@ namespace Configs_ConfigItem { - // 添加关联 void JsonStore::_add(configItem *item) { _map.insert(item->name, std::shared_ptr(item)); } + void JsonStore::_remove(const QString &key) { + _map.remove(key); + } + QString JsonStore::_name(void *p) { for (const auto &_item: _map) { if (_item->ptr == p) return _item->name; @@ -40,7 +43,6 @@ namespace Configs_ConfigItem { } std::shared_ptr JsonStore::_get(const QString &name) { - // 直接 [] 会设置一个 nullptr ,所以先判断是否存在 if (_map.contains(name)) { return _map[name]; } diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 1fc35b4..1d1fbbc 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1,7 +1,6 @@ #include "include/ui/mainwindow.h" #include "include/dataStore/ProfileFilter.hpp" -#include "include/configs/ConfigBuilder.hpp" #include "include/configs/sub/GroupUpdater.hpp" #include "include/sys/Process.hpp" #include "include/sys/AutoRun.hpp" @@ -18,6 +17,7 @@ #include "3rdparty/qrcodegen.hpp" #include "3rdparty/qv2ray/v2/ui/LogHighlighter.hpp" #include "3rdparty/QrDecoder.h" +#include "include/configs/generate.h" #include "include/ui/group/dialog_edit_group.h" #ifdef Q_OS_WIN @@ -1777,7 +1777,7 @@ void MainWindow::on_menu_export_config_triggered() { auto ent = ents.first(); if (ent->bean->DisplayCoreType() != software_core_name) return; - auto result = BuildConfig(ent, false, true); + auto result = Configs::BuildSingBoxConfig(ent); QString config_core = QJsonObject2QString(result->coreConfig, true); QApplication::clipboard()->setText(config_core); @@ -1789,12 +1789,12 @@ void MainWindow::on_menu_export_config_triggered() { msg.setDefaultButton(QMessageBox::Ok); msg.exec(); if (msg.clickedButton() == button_1) { - result = BuildConfig(ent, false, false); + result = BuildSingBoxConfig(ent); config_core = QJsonObject2QString(result->coreConfig, true); QApplication::clipboard()->setText(config_core); } else if (msg.clickedButton() == button_2) { - result = BuildConfig(ent, true, false); - config_core = QJsonObject2QString(result->coreConfig, true); + auto res = Configs::BuildTestConfig({ent}); + config_core = QJsonObject2QString(res->coreConfig, true); QApplication::clipboard()->setText(config_core); } } diff --git a/src/ui/mainwindow_rpc.cpp b/src/ui/mainwindow_rpc.cpp index 3ab84bb..0b511a7 100644 --- a/src/ui/mainwindow_rpc.cpp +++ b/src/ui/mainwindow_rpc.cpp @@ -1,7 +1,6 @@ #include "include/ui/mainwindow.h" #include "include/dataStore/Database.hpp" -#include "include/configs/ConfigBuilder.hpp" #include "include/stats/traffic/TrafficLooper.hpp" #include "include/api/RPC.h" #include "include/ui/utils//MessageBoxTimer.h" @@ -12,6 +11,9 @@ #include #include +#include "include/configs/generate.h" +#include "include/sys/Process.hpp" + // rpc using namespace API; @@ -466,7 +468,7 @@ void MainWindow::profile_start(int _id) { auto group = Configs::profileManager->GetGroup(ent->gid); if (group == nullptr || group->archive) return; - auto result = BuildConfig(ent, false, false); + auto result = Configs::BuildSingBoxConfig(ent); if (!result->error.isEmpty()) { MessageBoxWarning(tr("BuildConfig return error"), result->error); return; @@ -673,7 +675,7 @@ void MainWindow::profile_stop(bool crash, bool block, bool manual) { if (block) blocker.unlock(); - runOnUiThread([=, this, &blocker] { + runOnUiThread([=, this] { refresh_status(); refresh_proxy_list_impl_refresh_data(id, true); diff --git a/src/ui/profile/dialog_edit_profile.cpp b/src/ui/profile/dialog_edit_profile.cpp index ec94972..3684e21 100644 --- a/src/ui/profile/dialog_edit_profile.cpp +++ b/src/ui/profile/dialog_edit_profile.cpp @@ -245,7 +245,7 @@ void DialogEditProfile::typeSelected(const QString &newType) { auto _innerWidget = new EditCustom(this); innerWidget = _innerWidget; innerEditor = _innerWidget; - customType = newEnt ? type : ent->CustomBean()->core; + customType = newEnt ? type : ent->Custom()->type; _innerWidget->preset_core = customType; type = "custom"; ui->apply_to_group->hide(); diff --git a/src/ui/profile/edit_anytls.cpp b/src/ui/profile/edit_anytls.cpp index ca04e93..97e5150 100644 --- a/src/ui/profile/edit_anytls.cpp +++ b/src/ui/profile/edit_anytls.cpp @@ -19,20 +19,20 @@ EditAnyTLS::~EditAnyTLS() { void EditAnyTLS::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->AnyTLSBean(); + auto bean = this->ent->AnyTLS(); ui->password->setText(bean->password); - ui->interval->setText(Int2String(bean->idle_session_check_interval)); - ui->timeout->setText(Int2String(bean->idle_session_timeout)); + ui->interval->setText(bean->idle_session_check_interval); + ui->timeout->setText(bean->idle_session_timeout); ui->min->setText(Int2String(bean->min_idle_session)); } bool EditAnyTLS::onEnd() { - auto bean = this->ent->AnyTLSBean(); + auto bean = this->ent->AnyTLS(); bean->password = ui->password->text(); - bean->idle_session_check_interval = ui->interval->text().toInt(); - bean->idle_session_timeout = ui->timeout->text().toInt(); + bean->idle_session_check_interval = ui->interval->text(); + bean->idle_session_timeout = ui->timeout->text(); bean->min_idle_session = ui->min->text().toInt(); return true; diff --git a/src/ui/profile/edit_chain.cpp b/src/ui/profile/edit_chain.cpp index 48cb1cd..f7342cb 100644 --- a/src/ui/profile/edit_chain.cpp +++ b/src/ui/profile/edit_chain.cpp @@ -16,7 +16,7 @@ EditChain::~EditChain() { void EditChain::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->ChainBean(); + auto bean = this->ent->Chain(); for (auto id: bean->list) { AddProfileToListIfExist(id); @@ -29,7 +29,7 @@ bool EditChain::onEnd() { return false; } - auto bean = this->ent->ChainBean(); + auto bean = this->ent->Chain(); QList idList; for (int i = 0; i < ui->listWidget->count(); i++) { diff --git a/src/ui/profile/edit_custom.cpp b/src/ui/profile/edit_custom.cpp index 910b666..912af93 100644 --- a/src/ui/profile/edit_custom.cpp +++ b/src/ui/profile/edit_custom.cpp @@ -1,9 +1,6 @@ #include "include/ui/profile/edit_custom.h" #include "3rdparty/qv2ray/v2/ui/widgets/editors/w_JsonEditor.hpp" -#include "include/configs/proxy/CustomBean.hpp" -#include "include/configs/proxy/Preset.hpp" -#include "include/configs/ConfigBuilder.hpp" #include "include/dataStore/Database.hpp" #include @@ -26,16 +23,16 @@ EditCustom::~EditCustom() { void EditCustom::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->CustomBean(); + auto bean = this->ent->Custom(); - if (preset_core == "internal") { + if (preset_core == "outbound") { preset_command = preset_config = ""; ui->config_simple->setPlaceholderText( "{\n" " \"type\": \"socks\",\n" " // ...\n" "}"); - } else if (preset_core == "internal-full") { + } else if (preset_core == "fullconfig") { preset_command = preset_config = ""; ui->config_simple->setPlaceholderText( "{\n" @@ -45,18 +42,16 @@ void EditCustom::onStart(std::shared_ptr _ent) { } // load core ui - ui->config_simple->setPlainText(bean->config_simple); + ui->config_simple->setPlainText(bean->config); // custom internal - if (preset_core == "internal" || preset_core == "internal-full") { - if (preset_core == "internal") { - ui->core_l->setText(tr("Outbound JSON, please read the documentation.")); - } else { - ui->core_l->setText(tr("Please fill the complete config.")); - } - ui->w_ext1->hide(); - ui->w_ext2->hide(); + if (preset_core == "outbound") { + ui->core_l->setText(tr("Outbound JSON, please read the documentation.")); + } else { + ui->core_l->setText(tr("Please fill the complete config.")); } + ui->w_ext1->hide(); + ui->w_ext2->hide(); } bool EditCustom::onEnd() { @@ -65,10 +60,10 @@ bool EditCustom::onEnd() { return false; } - auto bean = this->ent->CustomBean(); + auto bean = this->ent->Custom(); - P_SAVE_STRING_PLAIN(config_simple) - bean->core = preset_core; + bean->config = ui->config_simple->toPlainText(); + bean->type = preset_core; return true; } diff --git a/src/ui/profile/edit_extra_core.cpp b/src/ui/profile/edit_extra_core.cpp index fe1e45d..031e252 100644 --- a/src/ui/profile/edit_extra_core.cpp +++ b/src/ui/profile/edit_extra_core.cpp @@ -18,7 +18,7 @@ EditExtraCore::~EditExtraCore() { void EditExtraCore::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = ent->ExtraCoreBean(); + auto bean = ent->ExtraCore(); ui->socks_address->setText(bean->socksAddress); ui->socks_port->setValidator(new QIntValidator(1, 65534)); ui->socks_port->setText(Int2String(bean->socksPort)); @@ -46,7 +46,7 @@ void EditExtraCore::onStart(std::shared_ptr _ent) { } bool EditExtraCore::onEnd() { - auto bean = ent->ExtraCoreBean(); + auto bean = ent->ExtraCore(); bean->socksAddress = ui->socks_address->text(); bean->socksPort = ui->socks_port->text().toInt(); bean->extraCoreConf = ui->config->toPlainText(); diff --git a/src/ui/profile/edit_quic.cpp b/src/ui/profile/edit_quic.cpp index 9ac53b1..049aecd 100644 --- a/src/ui/profile/edit_quic.cpp +++ b/src/ui/profile/edit_quic.cpp @@ -15,126 +15,126 @@ EditQUIC::~EditQUIC() { } void EditQUIC::onStart(std::shared_ptr _ent) { - this->ent = _ent; - auto bean = this->ent->QUICBean(); - - P_LOAD_INT(uploadMbps); - P_LOAD_INT(downloadMbps); - P_LOAD_BOOL(disableMtuDiscovery) - P_LOAD_STRING(obfsPassword); - P_LOAD_STRING(authPayload); - P_LOAD_INT(streamReceiveWindow); - P_LOAD_INT(connectionReceiveWindow); - - P_LOAD_COMBO_INT(authPayloadType); - P_LOAD_STRING(uuid); - P_LOAD_STRING(password); - - P_LOAD_COMBO_STRING(congestionControl); - P_LOAD_COMBO_STRING(udpRelayMode); - P_LOAD_BOOL(zeroRttHandshake); - P_LOAD_STRING(heartbeat); - P_LOAD_BOOL(uos); - - // TLS - P_LOAD_STRING(sni); - P_LOAD_STRING(alpn); - P_C_LOAD_STRING(caText); - P_LOAD_BOOL(allowInsecure); - P_LOAD_BOOL(disableSni); - - if (bean->proxy_type == Configs::QUICBean::proxy_Hysteria || bean->proxy_type == Configs::QUICBean::proxy_Hysteria2) { - ui->uuid->hide(); - ui->uuid_l->hide(); - ui->uuidgen->hide(); - ui->congestionControl->hide(); - ui->congestionControl_l->hide(); - ui->udpRelayMode->hide(); - ui->udpRelayMode_l->hide(); - ui->zeroRttHandshake->hide(); - ui->heartbeat->hide(); - ui->heartbeat_l->hide(); - ui->uos->hide(); - ui->port_range->setText(bean->serverPorts.join(",")); - ui->hop_interval->setText(bean->hop_interval); - - if (bean->proxy_type == Configs::QUICBean::proxy_Hysteria) { // hy1 - ui->password->hide(); - ui->password_l->hide(); - } else { // hy2 - ui->authPayload->hide(); - ui->authPayload_l->hide(); - ui->authPayloadType->hide(); - ui->authPayloadType_l->hide(); - ui->alpn->hide(); - ui->alpn_l->hide(); - ui->TLS->removeItem(ui->alpn_sp); - ui->disableMtuDiscovery->hide(); - ui->connectionReceiveWindow->hide(); - ui->connectionReceiveWindow_l->hide(); - ui->streamReceiveWindow->hide(); - ui->streamReceiveWindow_l->hide(); - } - } else if (bean->proxy_type == Configs::QUICBean::proxy_TUIC) { - ui->uploadMbps->hide(); - ui->uploadMbps_l->hide(); - ui->downloadMbps->hide(); - ui->downloadMbps_l->hide(); - ui->disableMtuDiscovery->hide(); - ui->obfsPassword->hide(); - ui->obfsPassword_l->hide(); - ui->authPayload->hide(); - ui->authPayload_l->hide(); - ui->authPayloadType->hide(); - ui->authPayloadType_l->hide(); - ui->streamReceiveWindow->hide(); - ui->streamReceiveWindow_l->hide(); - ui->connectionReceiveWindow->hide(); - ui->connectionReceiveWindow_l->hide(); - ui->port_range->hide(); - ui->port_range_l->hide(); - ui->hop_interval->hide(); - ui->hop_interval_l->hide(); - } + // this->ent = _ent; + // auto bean = this->ent->QUICBean(); + // + // P_LOAD_INT(uploadMbps); + // P_LOAD_INT(downloadMbps); + // P_LOAD_BOOL(disableMtuDiscovery) + // P_LOAD_STRING(obfsPassword); + // P_LOAD_STRING(authPayload); + // P_LOAD_INT(streamReceiveWindow); + // P_LOAD_INT(connectionReceiveWindow); + // + // P_LOAD_COMBO_INT(authPayloadType); + // P_LOAD_STRING(uuid); + // P_LOAD_STRING(password); + // + // P_LOAD_COMBO_STRING(congestionControl); + // P_LOAD_COMBO_STRING(udpRelayMode); + // P_LOAD_BOOL(zeroRttHandshake); + // P_LOAD_STRING(heartbeat); + // P_LOAD_BOOL(uos); + // + // // TLS + // P_LOAD_STRING(sni); + // P_LOAD_STRING(alpn); + // P_C_LOAD_STRING(caText); + // P_LOAD_BOOL(allowInsecure); + // P_LOAD_BOOL(disableSni); + // + // if (bean->proxy_type == Configs::QUICBean::proxy_Hysteria || bean->proxy_type == Configs::QUICBean::proxy_Hysteria2) { + // ui->uuid->hide(); + // ui->uuid_l->hide(); + // ui->uuidgen->hide(); + // ui->congestionControl->hide(); + // ui->congestionControl_l->hide(); + // ui->udpRelayMode->hide(); + // ui->udpRelayMode_l->hide(); + // ui->zeroRttHandshake->hide(); + // ui->heartbeat->hide(); + // ui->heartbeat_l->hide(); + // ui->uos->hide(); + // ui->port_range->setText(bean->serverPorts.join(",")); + // ui->hop_interval->setText(bean->hop_interval); + // + // if (bean->proxy_type == Configs::QUICBean::proxy_Hysteria) { // hy1 + // ui->password->hide(); + // ui->password_l->hide(); + // } else { // hy2 + // ui->authPayload->hide(); + // ui->authPayload_l->hide(); + // ui->authPayloadType->hide(); + // ui->authPayloadType_l->hide(); + // ui->alpn->hide(); + // ui->alpn_l->hide(); + // ui->TLS->removeItem(ui->alpn_sp); + // ui->disableMtuDiscovery->hide(); + // ui->connectionReceiveWindow->hide(); + // ui->connectionReceiveWindow_l->hide(); + // ui->streamReceiveWindow->hide(); + // ui->streamReceiveWindow_l->hide(); + // } + // } else if (bean->proxy_type == Configs::QUICBean::proxy_TUIC) { + // ui->uploadMbps->hide(); + // ui->uploadMbps_l->hide(); + // ui->downloadMbps->hide(); + // ui->downloadMbps_l->hide(); + // ui->disableMtuDiscovery->hide(); + // ui->obfsPassword->hide(); + // ui->obfsPassword_l->hide(); + // ui->authPayload->hide(); + // ui->authPayload_l->hide(); + // ui->authPayloadType->hide(); + // ui->authPayloadType_l->hide(); + // ui->streamReceiveWindow->hide(); + // ui->streamReceiveWindow_l->hide(); + // ui->connectionReceiveWindow->hide(); + // ui->connectionReceiveWindow_l->hide(); + // ui->port_range->hide(); + // ui->port_range_l->hide(); + // ui->hop_interval->hide(); + // ui->hop_interval_l->hide(); + // } } bool EditQUIC::onEnd() { - auto bean = this->ent->QUICBean(); - - // Hysteria - P_SAVE_INT(uploadMbps); - P_SAVE_INT(downloadMbps); - P_SAVE_BOOL(disableMtuDiscovery) - P_SAVE_STRING(obfsPassword); - P_SAVE_COMBO_INT(authPayloadType); - P_SAVE_STRING(authPayload); - P_SAVE_INT(streamReceiveWindow); - P_SAVE_INT(connectionReceiveWindow); - auto rawPorts = ui->port_range->text(); - QStringList serverPorts; - for (const auto& portRange : rawPorts.split(',')) - { - if (portRange.trimmed().isEmpty()) continue; - serverPorts.append(portRange.trimmed()); - } - bean->serverPorts = serverPorts; - bean->hop_interval = ui->hop_interval->text(); - - // TUIC - P_SAVE_STRING(uuid); - P_SAVE_STRING(password); - P_SAVE_COMBO_STRING(congestionControl); - P_SAVE_COMBO_STRING(udpRelayMode); - P_SAVE_BOOL(zeroRttHandshake); - P_SAVE_STRING(heartbeat); - P_SAVE_BOOL(uos); - - // TLS - P_SAVE_STRING(sni); - P_SAVE_STRING(alpn); - P_SAVE_BOOL(allowInsecure); - P_C_SAVE_STRING(caText); - P_SAVE_BOOL(disableSni); + // auto bean = this->ent->QUICBean(); + // + // // Hysteria + // P_SAVE_INT(uploadMbps); + // P_SAVE_INT(downloadMbps); + // P_SAVE_BOOL(disableMtuDiscovery) + // P_SAVE_STRING(obfsPassword); + // P_SAVE_COMBO_INT(authPayloadType); + // P_SAVE_STRING(authPayload); + // P_SAVE_INT(streamReceiveWindow); + // P_SAVE_INT(connectionReceiveWindow); + // auto rawPorts = ui->port_range->text(); + // QStringList serverPorts; + // for (const auto& portRange : rawPorts.split(',')) + // { + // if (portRange.trimmed().isEmpty()) continue; + // serverPorts.append(portRange.trimmed()); + // } + // bean->serverPorts = serverPorts; + // bean->hop_interval = ui->hop_interval->text(); + // + // // TUIC + // P_SAVE_STRING(uuid); + // P_SAVE_STRING(password); + // P_SAVE_COMBO_STRING(congestionControl); + // P_SAVE_COMBO_STRING(udpRelayMode); + // P_SAVE_BOOL(zeroRttHandshake); + // P_SAVE_STRING(heartbeat); + // P_SAVE_BOOL(uos); + // + // // TLS + // P_SAVE_STRING(sni); + // P_SAVE_STRING(alpn); + // P_SAVE_BOOL(allowInsecure); + // P_C_SAVE_STRING(caText); + // P_SAVE_BOOL(disableSni); return true; } diff --git a/src/ui/profile/edit_shadowsocks.cpp b/src/ui/profile/edit_shadowsocks.cpp index 54929c0..ea2e87d 100644 --- a/src/ui/profile/edit_shadowsocks.cpp +++ b/src/ui/profile/edit_shadowsocks.cpp @@ -1,6 +1,5 @@ #include "include/ui/profile/edit_shadowsocks.h" -#include "include/configs/proxy/ShadowSocksBean.hpp" #include "include/configs/proxy/Preset.hpp" EditShadowSocks::EditShadowSocks(QWidget *parent) : QWidget(parent), @@ -15,7 +14,7 @@ EditShadowSocks::~EditShadowSocks() { void EditShadowSocks::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->ShadowSocksBean(); + auto bean = this->ent->ShadowSocks(); ui->method->setCurrentText(bean->method); ui->uot->setCurrentIndex(bean->uot); @@ -28,7 +27,7 @@ void EditShadowSocks::onStart(std::shared_ptr _ent) { } bool EditShadowSocks::onEnd() { - auto bean = this->ent->ShadowSocksBean(); + auto bean = this->ent->ShadowSocks(); bean->method = ui->method->currentText(); bean->password = ui->password->text(); diff --git a/src/ui/profile/edit_socks_http.cpp b/src/ui/profile/edit_socks_http.cpp index aa3afef..3d0bbe3 100644 --- a/src/ui/profile/edit_socks_http.cpp +++ b/src/ui/profile/edit_socks_http.cpp @@ -1,7 +1,5 @@ #include "include/ui/profile/edit_socks_http.h" -#include "include/configs/proxy/SocksHttpBean.hpp" - EditSocksHttp::EditSocksHttp(QWidget *parent) : QWidget(parent), ui(new Ui::EditSocksHttp) { ui->setupUi(this); @@ -13,35 +11,35 @@ EditSocksHttp::~EditSocksHttp() { void EditSocksHttp::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->SocksHTTPBean(); - - if (bean->socks_http_type == Configs::SocksHttpBean::type_Socks4) { - ui->version->setCurrentIndex(1); - } else { - ui->version->setCurrentIndex(0); - } - if (bean->socks_http_type == Configs::SocksHttpBean::type_HTTP) { - ui->version->setVisible(false); - ui->version_l->setVisible(false); - } - - ui->username->setText(bean->username); - ui->password->setText(bean->password); + // auto bean = this->ent->SocksHTTPBean(); + // + // if (bean->socks_http_type == Configs::SocksHttpBean::type_Socks4) { + // ui->version->setCurrentIndex(1); + // } else { + // ui->version->setCurrentIndex(0); + // } + // if (bean->socks_http_type == Configs::SocksHttpBean::type_HTTP) { + // ui->version->setVisible(false); + // ui->version_l->setVisible(false); + // } + // + // ui->username->setText(bean->username); + // ui->password->setText(bean->password); } bool EditSocksHttp::onEnd() { - auto bean = this->ent->SocksHTTPBean(); - - if (ui->version->isVisible()) { - if (ui->version->currentIndex() == 1) { - bean->socks_http_type = Configs::SocksHttpBean::type_Socks4; - } else { - bean->socks_http_type = Configs::SocksHttpBean::type_Socks5; - } - } - - bean->username = ui->username->text(); - bean->password = ui->password->text(); + // auto bean = this->ent->SocksHTTPBean(); + // + // if (ui->version->isVisible()) { + // if (ui->version->currentIndex() == 1) { + // bean->socks_http_type = Configs::SocksHttpBean::type_Socks4; + // } else { + // bean->socks_http_type = Configs::SocksHttpBean::type_Socks5; + // } + // } + // + // bean->username = ui->username->text(); + // bean->password = ui->password->text(); return true; } diff --git a/src/ui/profile/edit_ssh.cpp b/src/ui/profile/edit_ssh.cpp index 86de0b2..515932b 100644 --- a/src/ui/profile/edit_ssh.cpp +++ b/src/ui/profile/edit_ssh.cpp @@ -13,16 +13,16 @@ EditSSH::~EditSSH() { void EditSSH::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->SSHBean(); + auto bean = this->ent->SSH(); ui->user->setText(bean->user); ui->password->setText(bean->password); - ui->private_key->setText(bean->privateKey); - ui->private_key_path->setText(bean->privateKeyPath); - ui->private_key_pass->setText(bean->privateKeyPass); - ui->host_key->setText(bean->hostKey.join(",")); - ui->host_key_algs->setText(bean->hostKeyAlgs.join(",")); - ui->client_version->setText(bean->clientVersion); + ui->private_key->setText(bean->private_key); + ui->private_key_path->setText(bean->private_key_path); + ui->private_key_pass->setText(bean->private_key_passphrase); + ui->host_key->setText(bean->host_key.join(",")); + ui->host_key_algs->setText(bean->host_key_algorithms.join(",")); + ui->client_version->setText(bean->client_version); connect(ui->choose_pk, &QPushButton::clicked, this, [=,this] { auto fn = QFileDialog::getOpenFileName(this, QObject::tr("Select"), QDir::currentPath(), @@ -34,18 +34,18 @@ void EditSSH::onStart(std::shared_ptr _ent) { } bool EditSSH::onEnd() { - auto bean = this->ent->SSHBean(); + auto bean = this->ent->SSH(); bean->user = ui->user->text(); bean->password = ui->password->text(); - bean->privateKey = ui->private_key->toPlainText(); - bean->privateKeyPath = ui->private_key_path->text(); - bean->privateKeyPass = ui->private_key_pass->text(); - if (!ui->host_key->text().trimmed().isEmpty()) bean->hostKey = ui->host_key->text().split(","); - else bean->hostKey = {}; - if (!ui->host_key_algs->text().trimmed().isEmpty()) bean->hostKeyAlgs = ui->host_key_algs->text().split(","); - else bean->hostKeyAlgs = {}; - bean->clientVersion = ui->client_version->text(); + bean->private_key = ui->private_key->toPlainText(); + bean->private_key_path = ui->private_key_path->text(); + bean->private_key_passphrase = ui->private_key_pass->text(); + if (!ui->host_key->text().trimmed().isEmpty()) bean->host_key = ui->host_key->text().split(","); + else bean->host_key = {}; + if (!ui->host_key_algs->text().trimmed().isEmpty()) bean->host_key_algorithms = ui->host_key_algs->text().split(","); + else bean->host_key_algorithms = {}; + bean->client_version = ui->client_version->text(); return true; } \ No newline at end of file diff --git a/src/ui/profile/edit_tailscale.cpp b/src/ui/profile/edit_tailscale.cpp index 6e4c3f4..6c289ba 100644 --- a/src/ui/profile/edit_tailscale.cpp +++ b/src/ui/profile/edit_tailscale.cpp @@ -12,7 +12,7 @@ EditTailScale::~EditTailScale() { void EditTailScale::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->TailscaleBean(); + auto bean = this->ent->Tailscale(); ui->state_dir->setText(bean->state_directory); ui->auth_key->setText(bean->auth_key); @@ -28,7 +28,7 @@ void EditTailScale::onStart(std::shared_ptr _ent) { } bool EditTailScale::onEnd() { - auto bean = this->ent->TailscaleBean(); + auto bean = this->ent->Tailscale(); bean->state_directory = ui->state_dir->text(); bean->auth_key = ui->auth_key->text(); diff --git a/src/ui/profile/edit_trojan_vless.cpp b/src/ui/profile/edit_trojan_vless.cpp index d77bb03..3c9bf1a 100644 --- a/src/ui/profile/edit_trojan_vless.cpp +++ b/src/ui/profile/edit_trojan_vless.cpp @@ -14,22 +14,22 @@ EditTrojanVLESS::~EditTrojanVLESS() { void EditTrojanVLESS::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->TrojanVLESSBean(); - if (bean->proxy_type == Configs::TrojanVLESSBean::proxy_VLESS) { - ui->label->setText("UUID"); - } - if (bean->proxy_type != Configs::TrojanVLESSBean::proxy_VLESS) { - ui->flow->hide(); - ui->flow_l->hide(); - } - ui->password->setText(bean->password); - ui->flow->addItems(Preset::SingBox::Flows ); - ui->flow->setCurrentText(bean->flow); + // auto bean = this->ent->TrojanVLESSBean(); + // if (bean->proxy_type == Configs::TrojanVLESSBean::proxy_VLESS) { + // ui->label->setText("UUID"); + // } + // if (bean->proxy_type != Configs::TrojanVLESSBean::proxy_VLESS) { + // ui->flow->hide(); + // ui->flow_l->hide(); + // } + // ui->password->setText(bean->password); + // ui->flow->addItems(Preset::SingBox::Flows ); + // ui->flow->setCurrentText(bean->flow); } bool EditTrojanVLESS::onEnd() { - auto bean = this->ent->TrojanVLESSBean(); - bean->password = ui->password->text(); - bean->flow = ui->flow->currentText(); + // auto bean = this->ent->TrojanVLESSBean(); + // bean->password = ui->password->text(); + // bean->flow = ui->flow->currentText(); return true; } diff --git a/src/ui/profile/edit_vmess.cpp b/src/ui/profile/edit_vmess.cpp index a8d87db..445d6e8 100644 --- a/src/ui/profile/edit_vmess.cpp +++ b/src/ui/profile/edit_vmess.cpp @@ -15,18 +15,18 @@ EditVMess::~EditVMess() { void EditVMess::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->VMessBean(); + auto bean = this->ent->VMess(); ui->uuid->setText(bean->uuid); - ui->aid->setText(Int2String(bean->aid)); + ui->aid->setText(Int2String(bean->alter_id)); ui->security->setCurrentText(bean->security); } bool EditVMess::onEnd() { - auto bean = this->ent->VMessBean(); + auto bean = this->ent->VMess(); bean->uuid = ui->uuid->text(); - bean->aid = ui->aid->text().toInt(); + bean->alter_id = ui->aid->text().toInt(); bean->security = ui->security->currentText(); return true; diff --git a/src/ui/profile/edit_wireguard.cpp b/src/ui/profile/edit_wireguard.cpp index 09eeaeb..d0ceb94 100644 --- a/src/ui/profile/edit_wireguard.cpp +++ b/src/ui/profile/edit_wireguard.cpp @@ -1,7 +1,5 @@ #include "include/ui/profile/edit_wireguard.h" -#include "include/configs/proxy/WireguardBean.h" - EditWireguard::EditWireguard(QWidget *parent) : QWidget(parent), ui(new Ui::EditWireguard) { ui->setupUi(this); } @@ -12,22 +10,22 @@ EditWireguard::~EditWireguard() { void EditWireguard::onStart(std::shared_ptr _ent) { this->ent = _ent; - auto bean = this->ent->WireguardBean(); + auto bean = this->ent->Wireguard(); #ifndef Q_OS_LINUX adjustSize(); #endif - ui->private_key->setText(bean->privateKey); - ui->public_key->setText(bean->publicKey); - ui->preshared_key->setText(bean->preSharedKey); - auto reservedStr = bean->FormatReserved().replace("-", ","); - ui->reserved->setText(reservedStr); - ui->persistent_keepalive->setText(Int2String(bean->persistentKeepalive)); - ui->mtu->setText(Int2String(bean->MTU)); - ui->sys_ifc->setChecked(bean->useSystemInterface); - ui->local_addr->setText(bean->localAddress.join(",")); - ui->workers->setText(Int2String(bean->workerCount)); + ui->private_key->setText(bean->private_key); + ui->public_key->setText(bean->peer->public_key); + ui->preshared_key->setText(bean->peer->pre_shared_key); + // auto reservedStr = bean->peer->reserved; + // ui->reserved->setText(reservedStr); + ui->persistent_keepalive->setText(Int2String(bean->peer->persistent_keepalive)); + ui->mtu->setText(Int2String(bean->mtu)); + ui->sys_ifc->setChecked(bean->system); + ui->local_addr->setText(bean->address.join(",")); + ui->workers->setText(Int2String(bean->worker_count)); ui->enable_amnezia->setChecked(bean->enable_amnezia); ui->junk_packet_count->setText(Int2String(bean->junk_packet_count)); @@ -42,22 +40,22 @@ void EditWireguard::onStart(std::shared_ptr _ent) { } bool EditWireguard::onEnd() { - auto bean = this->ent->WireguardBean(); + auto bean = this->ent->Wireguard(); - bean->privateKey = ui->private_key->text(); - bean->publicKey = ui->public_key->text(); - bean->preSharedKey = ui->preshared_key->text(); + bean->private_key = ui->private_key->text(); + bean->peer->public_key = ui->public_key->text(); + bean->peer->pre_shared_key = ui->preshared_key->text(); auto rawReserved = ui->reserved->text(); - bean->reserved = {}; - for (const auto& item: rawReserved.split(",")) { - if (item.trimmed().isEmpty()) continue; - bean->reserved += item.trimmed().toInt(); - } - bean->persistentKeepalive = ui->persistent_keepalive->text().toInt(); - bean->MTU = ui->mtu->text().toInt(); - bean->useSystemInterface = ui->sys_ifc->isChecked(); - bean->localAddress = ui->local_addr->text().replace(" ", "").split(","); - bean->workerCount = ui->workers->text().toInt(); + // bean->reserved = {}; + // for (const auto& item: rawReserved.split(",")) { + // if (item.trimmed().isEmpty()) continue; + // bean->reserved += item.trimmed().toInt(); + // } + bean->peer->persistent_keepalive = ui->persistent_keepalive->text().toInt(); + bean->mtu = ui->mtu->text().toInt(); + bean->system = ui->sys_ifc->isChecked(); + bean->address = ui->local_addr->text().replace(" ", "").split(","); + bean->worker_count = ui->workers->text().toInt(); bean->enable_amnezia = ui->enable_amnezia->isChecked(); bean->junk_packet_count = ui->junk_packet_count->text().toInt();