refactor: remote ruleset support

This commit is contained in:
parhelia512 2025-07-21 18:11:32 +08:00 committed by Mahdi
parent e8615de6b2
commit 706d4d8605
3 changed files with 56 additions and 58 deletions

View File

@ -113,6 +113,7 @@ namespace Configs {
QList<std::shared_ptr<RouteRule>> Rules;
QList<JsonStore*> castedRules;
int defaultOutboundID = proxyID;
std::map<QString, QString> tagMap;
RoutingChain();
@ -124,7 +125,7 @@ namespace Configs {
void FromJson(QJsonObject object);
QJsonArray get_route_rules(bool forView = false, std::map<int, QString> outboundMap = {}, const QStringList& tagList = {});
QJsonArray get_route_rules(bool forView = false, std::map<int, QString> outboundMap = {});
bool isViewOnly() const;
@ -140,8 +141,6 @@ namespace Configs {
std::shared_ptr<QStringList> get_used_rule_sets();
std::shared_ptr<QStringList> get_used_remote_rule_sets();
QStringList get_direct_sites();
QStringList get_direct_ips();

View File

@ -612,7 +612,6 @@ namespace Configs {
}
auto neededOutbounds = routeChain->get_used_outbounds();
auto neededRuleSets = routeChain->get_used_rule_sets();
auto neededRemoteRuleSets = routeChain->get_used_remote_rule_sets();
std::map<int, QString> outboundMap;
outboundMap[-1] = "proxy";
outboundMap[-2] = "direct";
@ -642,6 +641,8 @@ namespace Configs {
needDirectDnsRules = true;
}
}
auto routeRules = routeChain->get_route_rules(false, outboundMap);
routeObj["rules"] = routeRules;
// DNS hijack deps
bool needHijackRules = false;
@ -674,50 +675,38 @@ namespace Configs {
auto ruleSetArray = QJsonArray();
auto geoSitePath = GetCoreAssetDir("geosite.db");
auto geoIpPath = GetCoreAssetDir("geoip.db");
QStringList tagList;
for (const auto &item: *neededRuleSets) {
tagList.push_back(item);
ruleSetArray += QJsonObject{
{"type", "local"},
{"tag", item},
{"format", "binary"},
{"path", RULE_SETS_DIR + QString("/%1.srs").arg(item)},
};
if (QFile(QString(RULE_SETS_DIR + "/%1.srs").arg(item)).exists()) continue;
bool ok;
auto mode = API::GeoRuleSetType::site;
auto geoAssertPath = geoSitePath;
if (item.contains("_IP")) {
mode = API::GeoRuleSetType::ip;
geoAssertPath = geoIpPath;
if(item.startsWith("https://") && item.endsWith(".srs")) {
ruleSetArray += QJsonObject{
{"type", "remote"},
{"tag", routeChain->tagMap[item]},
{"format", "binary"},
{"url", item},
};
}
auto err = API::defaultClient->CompileGeoSet(&ok, mode, item.toStdString(), geoAssertPath);
if (!ok) {
MW_show_log("Failed to generate rule set asset for " + item);
status->result->error = err;
return;
else {
ruleSetArray += QJsonObject{
{"type", "local"},
{"tag", item},
{"format", "binary"},
{"path", RULE_SETS_DIR + QString("/%1.srs").arg(item)},
};
if (QFile(QString(RULE_SETS_DIR + "/%1.srs").arg(item)).exists()) continue;
bool ok;
auto mode = API::GeoRuleSetType::site;
auto geoAssertPath = geoSitePath;
if (item.contains("_IP")) {
mode = API::GeoRuleSetType::ip;
geoAssertPath = geoIpPath;
}
auto err = API::defaultClient->CompileGeoSet(&ok, mode, item.toStdString(), geoAssertPath);
if (!ok) {
MW_show_log("Failed to generate rule set asset for " + item);
status->result->error = err;
return;
}
}
}
for (const auto &item: *neededRemoteRuleSets) {
QString tagRemote, tmp = item.section('/', -1);
tmp.chop(4);
tagRemote = tmp;
int index = 1;
while(tagList.contains(tagRemote))
{
tagRemote = tmp + QString::number(index);
index++;
}
tagList.push_back(tagRemote);
ruleSetArray += QJsonObject{
{"type", "remote"},
{"tag", tagRemote},
{"format", "binary"},
{"url", item},
};
}
auto routeRules = routeChain->get_route_rules(false, outboundMap, tagList);
routeObj["rules"] = routeRules;
routeObj["rule_set"] = ruleSetArray;
// DNS settings

View File

@ -564,8 +564,30 @@ namespace Configs {
return rules;
}
QJsonArray RoutingChain::get_route_rules(bool forView, std::map<int, QString> outboundMap, const QStringList& tagList) {
QJsonArray RoutingChain::get_route_rules(bool forView, std::map<int, QString> outboundMap) {
QJsonArray res;
QStringList tagList;
for (const auto& item: Rules) {
for (const auto& ruleItem: item->rule_set) {
if (!ruleItem.startsWith("https://")) {
tagList.push_back(ruleItem);
}
}
}
for (const auto& item: Rules) {
for (const auto& ruleItem: item->rule_set) {
if (ruleItem.startsWith("https://") && ruleItem.endsWith(".srs")) {
QString tagRemote, tmp = ruleItem.section('/', -1);
tmp.chop(4);
tagRemote = tmp;
int index = 1;
while(tagList.contains(tagRemote))
tagRemote = tmp + QString::number(index++);
tagMap.insert(std::map<QString, QString>::value_type(ruleItem, tagRemote));
tagList.push_back(tagRemote);
}
}
}
for (const auto &item: Rules) {
auto outboundTag = QString();
if (outboundMap.count(item->outboundID)) outboundTag = outboundMap[item->outboundID];
@ -690,19 +712,7 @@ namespace Configs {
auto res = std::make_shared<QStringList>();
for (const auto& item: Rules) {
for (const auto& ruleItem: item->rule_set) {
if (!ruleItem.startsWith("https://"))
res->push_back(ruleItem);
}
}
return res;
}
std::shared_ptr<QStringList> RoutingChain::get_used_remote_rule_sets() {
auto res = std::make_shared<QStringList>();
for (const auto& item: Rules) {
for (const auto& ruleItem: item->rule_set) {
if (ruleItem.startsWith("https://") && ruleItem.endsWith(".srs"))
res->push_back(ruleItem);
res->push_back(ruleItem);
}
}
return res;