diff --git a/include/configs/generate.h b/include/configs/generate.h index 735910f..24ce32f 100644 --- a/include/configs/generate.h +++ b/include/configs/generate.h @@ -63,7 +63,6 @@ namespace Configs class BuildPrerequisities { public: - std::shared_ptr extraCoreData = std::make_shared(); std::shared_ptr dnsDeps = std::make_shared(); std::shared_ptr hijackDeps = std::make_shared(); std::shared_ptr tunDeps = std::make_shared(); @@ -74,7 +73,7 @@ namespace Configs public: QString error; QJsonObject coreConfig; - std::shared_ptr extraCoreData; + std::shared_ptr extraCoreData = std::make_shared(); QList> outboundStats; }; diff --git a/include/configs/outbounds/shadowsocks.h b/include/configs/outbounds/shadowsocks.h index a133db6..059a2c6 100644 --- a/include/configs/outbounds/shadowsocks.h +++ b/include/configs/outbounds/shadowsocks.h @@ -38,6 +38,7 @@ namespace Configs // baseConfig overrides bool ParseFromLink(const QString& link) override; bool ParseFromJson(const QJsonObject& object) override; + bool ParseFromSIP008(const QJsonObject& object); QString ExportToLink() override; QJsonObject ExportToJson() override; BuildResult Build() override; diff --git a/include/configs/sub/GroupUpdater.hpp b/include/configs/sub/GroupUpdater.hpp index 08a5291..fb31c9c 100644 --- a/include/configs/sub/GroupUpdater.hpp +++ b/include/configs/sub/GroupUpdater.hpp @@ -11,6 +11,8 @@ namespace Subscription { void updateWireguardFileConfig(const QString &str); + void updateSIP008(const QString &str); + int gid_add_to = -1; QList> updated_order; diff --git a/src/configs/common/TLS.cpp b/src/configs/common/TLS.cpp index 75fddeb..cb322d7 100644 --- a/src/configs/common/TLS.cpp +++ b/src/configs/common/TLS.cpp @@ -46,7 +46,7 @@ namespace Configs { obj["enabled"] = true; obj["fingerprint"] = dataStore->utlsFingerprint; } - return {ExportToJson(), ""}; + return {obj, ""}; } bool ECH::ParseFromLink(const QString& link) @@ -334,9 +334,9 @@ namespace Configs { if (fragment) object["fragment"] = fragment; if (!fragment_fallback_delay.isEmpty()) object["fragment_fallback_delay"] = fragment_fallback_delay; if (record_fragment) object["record_fragment"] = record_fragment; - if (ech->enabled) object["ech"] = ech->Build().object; - if (utls->enabled) object["utls"] = utls->Build().object; - if (reality->enabled) object["reality"] = reality->Build().object; + if (auto obj = ech->Build().object;!obj.isEmpty()) object["ech"] = obj; + if (auto obj = utls->Build().object;!obj.isEmpty()) object["utls"] = obj; + if (auto obj = reality->Build().object;!obj.isEmpty()) object["reality"] = obj; return {object, ""}; } } diff --git a/src/configs/generate.cpp b/src/configs/generate.cpp index 64a768a..79579a6 100644 --- a/src/configs/generate.cpp +++ b/src/configs/generate.cpp @@ -224,11 +224,11 @@ namespace Configs { ctx->error = "failed to cast to extracore, type is: " + ctx->ent->type; return; } - preReqs->extraCoreData->path = QFileInfo(outbound->extraCorePath).canonicalFilePath(); - preReqs->extraCoreData->args = outbound->extraCoreArgs; - preReqs->extraCoreData->config = outbound->extraCoreConf; - preReqs->extraCoreData->configDir = GetBasePath(); - preReqs->extraCoreData->noLog = outbound->noLogs; + ctx->buildConfigResult->extraCoreData->path = QFileInfo(outbound->extraCorePath).canonicalFilePath(); + ctx->buildConfigResult->extraCoreData->args = outbound->extraCoreArgs; + ctx->buildConfigResult->extraCoreData->config = outbound->extraCoreConf; + ctx->buildConfigResult->extraCoreData->configDir = GetBasePath(); + ctx->buildConfigResult->extraCoreData->noLog = outbound->noLogs; } } @@ -789,6 +789,7 @@ namespace Configs { auto ctx = std::make_shared(); ctx->ent = ent; + ctx->buildConfigResult->outboundStats << std::make_shared("direct"); CalculatePrerequisities(ctx); diff --git a/src/configs/outbounds/shadowsocks.cpp b/src/configs/outbounds/shadowsocks.cpp index 3ceb974..175c05c 100644 --- a/src/configs/outbounds/shadowsocks.cpp +++ b/src/configs/outbounds/shadowsocks.cpp @@ -62,6 +62,24 @@ namespace Configs { return true; } + bool shadowsocks::ParseFromSIP008(const QJsonObject& object) + { + if (object.isEmpty()) return false; + outbound::ParseFromJson(object); + if (object.contains("remarks")) name = object["remarks"].toString(); + if (object.contains("method")) method = object["method"].toString(); + if (object.contains("password")) password = object["password"].toString(); + if (object.contains("plugin")) plugin = object["plugin"].toString().replace("simple-obfs", "obfs-local"); + if (object.contains("plugin_opts")) plugin_opts = object["plugin_opts"].toString(); + if (object.contains("uot")) + { + if (object["uot"].isBool()) uot = object["uot"].toBool(); + if (object["uot"].isObject()) uot = object["uot"].toObject()["enabled"].toBool(); + } + if (object.contains("multiplex")) multiplex->ParseFromJson(object["multiplex"].toObject()); + return !(server.isEmpty() || method.isEmpty() || password.isEmpty()); + } + QString shadowsocks::ExportToLink() { QUrl url; @@ -109,6 +127,10 @@ namespace Configs { BuildResult shadowsocks::Build() { + if (plugin.contains(";")) { + plugin_opts = SubStrAfter(plugin, ";"); + plugin = SubStrBefore(plugin, ";"); + } QJsonObject object; object["type"] = "shadowsocks"; mergeJsonObjects(object, outbound::Build().object); diff --git a/src/configs/sub/GroupUpdater.cpp b/src/configs/sub/GroupUpdater.cpp index 6a278dc..cd30530 100644 --- a/src/configs/sub/GroupUpdater.cpp +++ b/src/configs/sub/GroupUpdater.cpp @@ -80,6 +80,13 @@ namespace Subscription { return; } + // SIP008 + if (str.contains("version") && str.contains("servers")) + { + updateSIP008(str); + return; + } + // Multi line if (str.count("\n") > 0 && needParse) { auto list = Disect(str); @@ -327,6 +334,26 @@ namespace Subscription { updated_order += ent; } + void RawUpdater::updateSIP008(const QString& str) + { + auto json = QString2QJsonObject(str); + + for (auto o : json["servers"].toArray()) + { + auto out = o.toObject(); + if (out.isEmpty()) + { + MW_show_log("invalid server object"); + continue; + } + + auto ent = Configs::ProfileManager::NewProxyEntity("shadowsocks"); + auto ok = ent->ShadowSocks()->ParseFromSIP008(out); + if (!ok) continue; + updated_order += ent; + } + } + // 在新的 thread 运行 void GroupUpdater::AsyncUpdate(const QString &str, int _sub_gid, const std::function &finish) { auto content = str.trimmed(); diff --git a/src/dataStore/RouteEntity.cpp b/src/dataStore/RouteEntity.cpp index f9c05ad..0b8fc9d 100644 --- a/src/dataStore/RouteEntity.cpp +++ b/src/dataStore/RouteEntity.cpp @@ -653,7 +653,7 @@ namespace Configs { { auto res = QStringList(); for (const auto& item: Rules) { - if (item->outboundID == -2) { + if (item->outboundID == directID && item->action == "route") { for (const auto& rset: item->rule_set) { if (rset.startsWith("geoip-")) res << QString("ruleset:" + rset); } diff --git a/src/ui/profile/dialog_edit_profile.cpp b/src/ui/profile/dialog_edit_profile.cpp index 73b6490..9400f2a 100644 --- a/src/ui/profile/dialog_edit_profile.cpp +++ b/src/ui/profile/dialog_edit_profile.cpp @@ -452,6 +452,7 @@ bool DialogEditProfile::onEnd() { transport->xhttp_extra = ui->xhttp_extra->text(); tls->reality->public_key = ui->reality_pbk->text(); tls->reality->short_id = ui->reality_sid->text(); + tls->reality->enabled = !tls->reality->public_key.isEmpty(); tls->certificate = CACHE.certificate; } if (ent->outbound->HasMux()) { diff --git a/src/ui/profile/edit_shadowsocks.cpp b/src/ui/profile/edit_shadowsocks.cpp index 265d0d5..bde5005 100644 --- a/src/ui/profile/edit_shadowsocks.cpp +++ b/src/ui/profile/edit_shadowsocks.cpp @@ -16,6 +16,10 @@ void EditShadowSocks::onStart(std::shared_ptr _ent) { this->ent = _ent; auto outbound = this->ent->ShadowSocks(); + if (outbound->plugin.contains(";")) { + outbound->plugin_opts = SubStrAfter(outbound->plugin, ";"); + outbound->plugin = SubStrBefore(outbound->plugin, ";"); + } ui->method->setCurrentText(outbound->method); ui->uot->setCurrentIndex(outbound->uot); ui->password->setText(outbound->password);