diff --git a/core/server/gen/libcore.proto b/core/server/gen/libcore.proto index 6dae321..3e40550 100644 --- a/core/server/gen/libcore.proto +++ b/core/server/gen/libcore.proto @@ -13,11 +13,6 @@ service LibcoreService { rpc QueryStats(EmptyReq) returns (QueryStatsResp); rpc ListConnections(EmptyReq) returns (ListConnectionsResp); // - rpc GetGeoIPList(GeoListRequest) returns (GetGeoIPListResponse); - rpc GetGeoSiteList(GeoListRequest) returns (GetGeoSiteListResponse); - rpc CompileGeoIPToSrs(CompileGeoIPToSrsRequest) returns (EmptyResp); - rpc CompileGeoSiteToSrs(CompileGeoSiteToSrsRequest) returns (EmptyResp); - // rpc SetSystemDNS(SetSystemDNSRequest) returns (EmptyResp); // rpc IsPrivileged(EmptyReq) returns (IsPrivilegedResponse); @@ -86,28 +81,6 @@ message ConnectionMetaData { optional string process = 10 [default = ""]; } -message GetGeoIPListResponse { - repeated string items = 1; -} - -message GetGeoSiteListResponse { - repeated string items = 2; -} - -message GeoListRequest { - optional string path = 1 [default = ""]; -} - -message CompileGeoIPToSrsRequest { - optional string item = 1 [default = ""]; - optional string path = 2 [default = ""]; -} - -message CompileGeoSiteToSrsRequest { - optional string item = 1 [default = ""]; - optional string path = 2 [default = ""]; -} - message SetSystemDNSRequest { optional bool clear = 1 [default = false]; } @@ -150,3 +123,7 @@ message QuerySpeedTestResponse { message QueryURLTestResponse { repeated URLTestResp results = 1; } + +message RuleSet{ + map items = 1; +} diff --git a/core/server/go.mod b/core/server/go.mod index 0d09491..138c5de 100644 --- a/core/server/go.mod +++ b/core/server/go.mod @@ -9,7 +9,6 @@ require ( github.com/gofrs/uuid/v5 v5.3.2 github.com/golang/protobuf v1.5.4 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/oschwald/maxminddb-golang v1.13.1 github.com/sagernet/sing v0.7.5 github.com/sagernet/sing-box v1.12.1 github.com/sagernet/sing-tun v0.7.0-beta.1 diff --git a/core/server/go.sum b/core/server/go.sum index c4ea442..6fd022b 100644 --- a/core/server/go.sum +++ b/core/server/go.sum @@ -132,8 +132,6 @@ github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE= -github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/core/server/internal/boxmain/cmd_geoip.go b/core/server/internal/boxmain/cmd_geoip.go deleted file mode 100644 index c237e5d..0000000 --- a/core/server/internal/boxmain/cmd_geoip.go +++ /dev/null @@ -1,24 +0,0 @@ -package boxmain - -import ( - E "github.com/sagernet/sing/common/exceptions" - - "github.com/oschwald/maxminddb-golang" -) - -var ( - geoipReader *maxminddb.Reader -) - -func geoipPreRun(path string) error { - reader, err := maxminddb.Open(path) - if err != nil { - return err - } - if reader.Metadata.DatabaseType != "sing-geoip" { - reader.Close() - return E.New("incorrect database type, expected sing-geoip, got ", reader.Metadata.DatabaseType) - } - geoipReader = reader - return nil -} diff --git a/core/server/internal/boxmain/cmd_geoip_export.go b/core/server/internal/boxmain/cmd_geoip_export.go deleted file mode 100644 index 573f5f1..0000000 --- a/core/server/internal/boxmain/cmd_geoip_export.go +++ /dev/null @@ -1,60 +0,0 @@ -package boxmain - -import ( - "bytes" - "net" - "strings" - - C "github.com/sagernet/sing-box/constant" - "github.com/sagernet/sing-box/option" - E "github.com/sagernet/sing/common/exceptions" - "github.com/sagernet/sing/common/json" - - "github.com/oschwald/maxminddb-golang" -) - -func geoipExport(path string, countryCode string) ([]byte, error) { - if err := geoipPreRun(path); err != nil { - return nil, err - } - - networks := geoipReader.Networks(maxminddb.SkipAliasedNetworks) - countryMap := make(map[string][]*net.IPNet) - var ( - ipNet *net.IPNet - nextCountryCode string - err error - ) - for networks.Next() { - ipNet, err = networks.Network(&nextCountryCode) - if err != nil { - return nil, err - } - countryMap[nextCountryCode] = append(countryMap[nextCountryCode], ipNet) - } - ipNets := countryMap[strings.ToLower(countryCode)] - if len(ipNets) == 0 { - return nil, E.New("country code not found: ", countryCode) - } - - outputWriter := &bytes.Buffer{} - - encoder := json.NewEncoder(outputWriter) - encoder.SetIndent("", " ") - var headlessRule option.DefaultHeadlessRule - headlessRule.IPCIDR = make([]string, 0, len(ipNets)) - for _, cidr := range ipNets { - headlessRule.IPCIDR = append(headlessRule.IPCIDR, cidr.String()) - } - var plainRuleSet option.PlainRuleSetCompat - plainRuleSet.Version = C.RuleSetVersion1 - plainRuleSet.Options.Rules = []option.HeadlessRule{ - { - Type: C.RuleTypeDefault, - DefaultOptions: headlessRule, - }, - } - - err = encoder.Encode(plainRuleSet) - return outputWriter.Bytes(), err -} diff --git a/core/server/internal/boxmain/cmd_geoip_list.go b/core/server/internal/boxmain/cmd_geoip_list.go deleted file mode 100644 index adaba10..0000000 --- a/core/server/internal/boxmain/cmd_geoip_list.go +++ /dev/null @@ -1,9 +0,0 @@ -package boxmain - -func ListGeoip(path string) ([]string, error) { - if err := geoipPreRun(path); err != nil { - return nil, err - } - - return geoipReader.Metadata.Languages, nil -} diff --git a/core/server/internal/boxmain/cmd_geosite.go b/core/server/internal/boxmain/cmd_geosite.go deleted file mode 100644 index e66b61f..0000000 --- a/core/server/internal/boxmain/cmd_geosite.go +++ /dev/null @@ -1,21 +0,0 @@ -package boxmain - -import ( - "github.com/sagernet/sing-box/common/geosite" - E "github.com/sagernet/sing/common/exceptions" -) - -var ( - geositeReader *geosite.Reader - geositeCodeList []string -) - -func geositePreRun(path string) error { - reader, codeList, err := geosite.Open(path) - if err != nil { - return E.Cause(err, "open geosite file ") - } - geositeReader = reader - geositeCodeList = codeList - return nil -} diff --git a/core/server/internal/boxmain/cmd_geosite_export.go b/core/server/internal/boxmain/cmd_geosite_export.go deleted file mode 100644 index 6ad989b..0000000 --- a/core/server/internal/boxmain/cmd_geosite_export.go +++ /dev/null @@ -1,42 +0,0 @@ -package boxmain - -import ( - "bytes" - "github.com/sagernet/sing-box/common/geosite" - C "github.com/sagernet/sing-box/constant" - "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing/common/json" -) - -func geositeExport(path string, category string) ([]byte, error) { - if err := geositePreRun(path); err != nil { - return nil, err - } - - sourceSet, err := geositeReader.Read(category) - if err != nil { - return nil, err - } - - outputWriter := &bytes.Buffer{} - - encoder := json.NewEncoder(outputWriter) - encoder.SetIndent("", " ") - var headlessRule option.DefaultHeadlessRule - defaultRule := geosite.Compile(sourceSet) - headlessRule.Domain = defaultRule.Domain - headlessRule.DomainSuffix = defaultRule.DomainSuffix - headlessRule.DomainKeyword = defaultRule.DomainKeyword - headlessRule.DomainRegex = defaultRule.DomainRegex - var plainRuleSet option.PlainRuleSetCompat - plainRuleSet.Version = C.RuleSetVersion1 - plainRuleSet.Options.Rules = []option.HeadlessRule{ - { - Type: C.RuleTypeDefault, - DefaultOptions: headlessRule, - }, - } - - err = encoder.Encode(plainRuleSet) - return outputWriter.Bytes(), err -} diff --git a/core/server/internal/boxmain/cmd_geosite_list.go b/core/server/internal/boxmain/cmd_geosite_list.go deleted file mode 100644 index 7e18458..0000000 --- a/core/server/internal/boxmain/cmd_geosite_list.go +++ /dev/null @@ -1,9 +0,0 @@ -package boxmain - -func GeositeList(path string) ([]string, error) { - if err := geositePreRun(path); err != nil { - return nil, err - } - - return geositeCodeList, nil -} diff --git a/core/server/internal/boxmain/cmd_rule_set_compile.go b/core/server/internal/boxmain/cmd_rule_set_compile.go deleted file mode 100644 index c7c8c1e..0000000 --- a/core/server/internal/boxmain/cmd_rule_set_compile.go +++ /dev/null @@ -1,56 +0,0 @@ -package boxmain - -import ( - "github.com/sagernet/sing-box/common/srs" - "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing/common/json" - "os" -) - -type RuleSetType int - -const ( - IpRuleSet RuleSetType = iota - SiteRuleSet -) - -func CompileRuleSet(path string, category string, ruleSetType RuleSetType, destPath string) error { - var ( - content []byte - err error - ) - - if ruleSetType == IpRuleSet { - content, err = geoipExport(path, category) - } else { - content, err = geositeExport(path, category) - } - if err != nil { - return err - } - - plainRuleSet, err := json.UnmarshalExtended[option.PlainRuleSetCompat](content) - if err != nil { - return err - } - if err != nil { - return err - } - ruleSet, err := plainRuleSet.Upgrade() - if err != nil { - return err - } - - outputFile, err := os.Create(destPath) - if err != nil { - return err - } - err = srs.Write(outputFile, ruleSet, plainRuleSet.Version) - if err != nil { - outputFile.Close() - os.Remove(destPath) - return err - } - outputFile.Close() - return nil -} diff --git a/core/server/server.go b/core/server/server.go index fa16392..d84388a 100644 --- a/core/server/server.go +++ b/core/server/server.go @@ -296,58 +296,6 @@ func (s *server) ListConnections(in *gen.EmptyReq, out *gen.ListConnectionsResp) return nil } -func (s *server) GetGeoIPList(in *gen.GeoListRequest, out *gen.GetGeoIPListResponse) error { - resp, err := boxmain.ListGeoip(*in.Path + string(os.PathSeparator) + "geoip.db") - if err != nil { - return err - } - - res := make([]string, 0) - for _, r := range resp { - r += "_IP" - res = append(res, r) - } - - out.Items = res - return nil -} - -func (s *server) GetGeoSiteList(in *gen.GeoListRequest, out *gen.GetGeoSiteListResponse) error { - resp, err := boxmain.GeositeList(*in.Path + string(os.PathSeparator) + "geosite.db") - if err != nil { - return err - } - - res := make([]string, 0) - for _, r := range resp { - r += "_SITE" - res = append(res, r) - } - - out.Items = res - return nil -} - -func (s *server) CompileGeoIPToSrs(in *gen.CompileGeoIPToSrsRequest, out *gen.EmptyResp) error { - category := strings.TrimSuffix(*in.Item, "_IP") - err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geoip.db", category, boxmain.IpRuleSet, "./rule_sets/"+*in.Item+".srs") - if err != nil { - return err - } - - return nil -} - -func (s *server) CompileGeoSiteToSrs(in *gen.CompileGeoSiteToSrsRequest, out *gen.EmptyResp) error { - category := strings.TrimSuffix(*in.Item, "_SITE") - err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geosite.db", category, boxmain.SiteRuleSet, "./rule_sets/"+*in.Item+".srs") - if err != nil { - return err - } - - return nil -} - func (s *server) IsPrivileged(in *gen.EmptyReq, out *gen.IsPrivilegedResponse) error { if runtime.GOOS == "windows" { out.HasPrivilege = To(false) diff --git a/include/api/RPC.h b/include/api/RPC.h index a54dd09..8e9297e 100644 --- a/include/api/RPC.h +++ b/include/api/RPC.h @@ -7,8 +7,6 @@ #include "3rdparty/protorpc/rpc_client.h" namespace API { - enum GeoRuleSetType {ip, site}; - class Client { public: explicit Client(std::function onError, const QString &host, int port); @@ -27,10 +25,6 @@ namespace API { libcore::QueryURLTestResponse QueryURLTest(bool *rpcOK); - QStringList GetGeoList(bool *rpcOK, GeoRuleSetType mode, const QString& basePath); - - QString CompileGeoSet(bool *rpcOK, GeoRuleSetType mode, std::string category, const QString& basePath); - QString SetSystemDNS(bool *rpcOK, bool clear) const; libcore::ListConnectionsResp ListConnections(bool *rpcOK) const; diff --git a/include/configs/ConfigBuilder.hpp b/include/configs/ConfigBuilder.hpp index 7cf7e51..d4eff82 100644 --- a/include/configs/ConfigBuilder.hpp +++ b/include/configs/ConfigBuilder.hpp @@ -54,11 +54,11 @@ namespace Configs { bool IsValid(const std::shared_ptr &ent); - std::shared_ptr BuildTestConfig(const QList>& profiles); + std::shared_ptr BuildTestConfig(const QList>& profiles, const std::map& ruleSetMap); - std::shared_ptr BuildConfig(const std::shared_ptr &ent, bool forTest, bool forExport, int chainID = 0); + std::shared_ptr BuildConfig(const std::shared_ptr &ent, const std::map& ruleSetMap, bool forTest, bool forExport, int chainID = 0); - void BuildConfigSingBox(const std::shared_ptr &status); + void BuildConfigSingBox(const std::shared_ptr &status, const std::map& ruleSetMap); QJsonObject BuildDnsObject(QString address, bool tunEnabled); diff --git a/include/global/Configs.hpp b/include/global/Configs.hpp index 0a0b8bc..791eca3 100644 --- a/include/global/Configs.hpp +++ b/include/global/Configs.hpp @@ -13,12 +13,7 @@ namespace Configs { bool IsAdmin(bool forceRenew=false); QString GetBasePath(); - - QString GetCoreAssetDir(const QString &name); - - bool NeedGeoAssets(); } // namespace Configs #define ROUTES_PREFIX_NAME QString("route_profiles") #define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/") -#define RULE_SETS_DIR QString("rule_sets") diff --git a/include/global/Const.hpp b/include/global/Const.hpp index b073f88..da8a1a1 100644 --- a/include/global/Const.hpp +++ b/include/global/Const.hpp @@ -29,12 +29,6 @@ namespace Configs { inline QString SimpleRuleInfo = "You can add rules with the following format:\ndomain:\nsuffix:\nkeyword:\nregex:\nruleset: or ruleset:\nip:\nprocessName:\nprocessPath:\nRules are validated on tab change or when pressing ok.\nImportant: On saving the rules, the previous rules are discarded, meaning\nany changes made to the generated rules in the Advanced tab will be lost."; } -namespace GeoAssets { - inline QStringList GeoIPURLs = {"https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db", "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/release/geoip.db"}; - inline QStringList GeoSiteURLs = {"https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db", "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/release/geosite.db"}; - inline QList ResetAssetsOptions = {0, 86400, 259200, 604800}; - } - namespace TestConfig { enum SpeedTestMode diff --git a/include/global/DataStore.hpp b/include/global/DataStore.hpp index 339a203..26b8411 100644 --- a/include/global/DataStore.hpp +++ b/include/global/DataStore.hpp @@ -94,12 +94,6 @@ namespace Configs { bool sub_insecure = false; int sub_auto_update = -30; - // Assets - QString geoip_download_url = ""; - QString geosite_download_url = ""; - int auto_reset_assets_idx = 0; - long long last_asset_reset_epoch_secs = 0; - // Security bool skip_cert = false; QString utlsFingerprint = ""; diff --git a/include/ui/mainwindow.h b/include/ui/mainwindow.h index 18d6dde..977dfa4 100644 --- a/include/ui/mainwindow.h +++ b/include/ui/mainwindow.h @@ -84,10 +84,6 @@ public: bool StopVPNProcess(); - void DownloadAssets(const QString &geoipUrl, const QString &geositeUrl); - - void ResetAssets(const QString& geoipUrl, const QString& geositeUrl); - void UpdateConnectionList(const QMap& toUpdate, const QMap& toAdd); void UpdateConnectionListWithRecreate(const QList& connections); @@ -196,9 +192,7 @@ private: QSemaphore sem_stopped; int exit_reason = 0; // - QMutex mu_download_assets; QMutex mu_download_update; - QMutex mu_reset_assets; // int toolTipID; // @@ -212,6 +206,8 @@ private: libcore::SpeedTestResult currentTestResult; DownloadProgressReport currentDownloadReport; // could use a list, but don't think can show more than one anyways + std::map ruleSetMap; + QStringList remoteRouteProfiles; QMutex mu_remoteRouteProfiles; diff --git a/include/ui/setting/RouteItem.h b/include/ui/setting/RouteItem.h index 81bf3bf..541d5e6 100644 --- a/include/ui/setting/RouteItem.h +++ b/include/ui/setting/RouteItem.h @@ -20,7 +20,7 @@ class RouteItem : public QDialog { Q_OBJECT public: - explicit RouteItem(QWidget *parent = nullptr, const std::shared_ptr& routeChain = nullptr); + explicit RouteItem(QWidget *parent = nullptr, const std::shared_ptr& routeChain = nullptr, const std::map& ruleSetMap = {}); ~RouteItem() override; std::shared_ptr chain; @@ -66,7 +66,7 @@ private: void updateRulePreview(); void updateRouteItemsView(); - private slots: +private slots: void accept() override; void on_new_route_item_clicked(); diff --git a/include/ui/setting/dialog_basic_settings.ui b/include/ui/setting/dialog_basic_settings.ui index 6c329e2..d5c4687 100644 --- a/include/ui/setting/dialog_basic_settings.ui +++ b/include/ui/setting/dialog_basic_settings.ui @@ -761,108 +761,6 @@ - - - Assets - - - - - - Geo Assets and Rule-sets - - - - - - - 0 - 0 - - - - - Disabled - - - - - Every Day - - - - - Every 3 Days - - - - - Every Week - - - - - - - - Download and Replace Geo files - - - - - - - - - - Auto Reset Assets - - - - - - - - - - GeoSite URL - - - - - - - <html><head/><body><p>Downloads and replaces the geo asstes, and removes all generated rule-sets, then restarts the proxy</p></body></html> - - - Reset All Assets - - - - - - - GeoIP URL - - - - - - - <html><head/><body><p>Remove the - currently generated rule-sets so that they can be regenerated</p></body></html> - - - - Remove Generated Rule-sets - - - - - - - - Security diff --git a/include/ui/setting/dialog_manage_routes.h b/include/ui/setting/dialog_manage_routes.h index 989c730..5c8bae8 100644 --- a/include/ui/setting/dialog_manage_routes.h +++ b/include/ui/setting/dialog_manage_routes.h @@ -18,7 +18,7 @@ class DialogManageRoutes : public QDialog { Q_OBJECT public: - explicit DialogManageRoutes(QWidget *parent = nullptr); + explicit DialogManageRoutes(QWidget *parent = nullptr, const std::map& dataMap = {}); ~DialogManageRoutes() override; @@ -35,6 +35,8 @@ private: int tooltipID = 0; + std::map ruleSetMap; + void set_dns_hijack_enability(bool enable) const; static bool validate_dns_rules(const QString &rawString); diff --git a/src/api/RPC.cpp b/src/api/RPC.cpp index 1ae2d3b..b756a07 100644 --- a/src/api/RPC.cpp +++ b/src/api/RPC.cpp @@ -102,90 +102,6 @@ namespace API { } } - QStringList Client::GetGeoList(bool *rpcOK, GeoRuleSetType mode, const QString& basePath) { - switch (mode) { - case GeoRuleSetType::ip: { - libcore::GeoListRequest request; - libcore::GetGeoIPListResponse reply; - request.path = basePath.toStdString(); - std::string resp, req = spb::pb::serialize(request); - auto err = make_rpc_client()->CallMethod("LibcoreService.GetGeoIPList", &req, &resp); - - if(err.IsNil()) { - QStringList res; - reply = spb::pb::deserialize< libcore::GetGeoIPListResponse >( resp ); - for (const auto & i : reply.items) { - res.append(QString::fromStdString(i)); - } - *rpcOK = true; - return res; - } else { - NOT_OK - return {}; - } - } - case GeoRuleSetType::site: { - libcore::GeoListRequest request; - libcore::GetGeoSiteListResponse reply; - request.path = basePath.toStdString(); - std::string resp, req = spb::pb::serialize(request); - auto err = make_rpc_client()->CallMethod("LibcoreService.GetGeoSiteList", &req, &resp); - - if(err.IsNil()) { - QStringList res; - reply = spb::pb::deserialize< libcore::GetGeoSiteListResponse >( resp ); - for (const auto & i : reply.items) { - res.append(QString::fromStdString(i)); - } - *rpcOK = true; - return res; - } else { - NOT_OK - return {}; - } - } - } - return {}; - } - - QString Client::CompileGeoSet(bool *rpcOK, GeoRuleSetType mode, std::string category, const QString& basePath) { - switch (mode) { - case ip: { - libcore::CompileGeoIPToSrsRequest request; - libcore::EmptyResp reply; - request.item = category; - request.path = basePath.toStdString(); - std::string resp, req = spb::pb::serialize(request); - - auto err = make_rpc_client()->CallMethod("LibcoreService.CompileGeoIPToSrs", &req, &resp); - if(err.IsNil()) { - *rpcOK = true; - return ""; - } else { - NOT_OK - return QString::fromStdString(err.String()); - } - } - case site: { - libcore::CompileGeoSiteToSrsRequest request; - libcore::EmptyResp reply; - request.item = category; - request.path = basePath.toStdString(); - std::string resp, req = spb::pb::serialize(request); - - auto err = make_rpc_client()->CallMethod("LibcoreService.CompileGeoSiteToSrs", &req, &resp); - if(err.IsNil()) { - *rpcOK = true; - return ""; - } else { - NOT_OK - return QString::fromStdString(err.String()); - } - } - } - return ""; - } - QString Client::SetSystemDNS(bool *rpcOK, const bool clear) const { libcore::SetSystemDNSRequest request; request.clear = clear; diff --git a/src/configs/ConfigBuilder.cpp b/src/configs/ConfigBuilder.cpp index 6daae9a..b2f12c2 100644 --- a/src/configs/ConfigBuilder.cpp +++ b/src/configs/ConfigBuilder.cpp @@ -41,7 +41,7 @@ namespace Configs { // Common - std::shared_ptr BuildConfig(const std::shared_ptr &ent, bool forTest, bool forExport, int chainID) { + std::shared_ptr BuildConfig(const std::shared_ptr &ent, const std::map& ruleSetMap, bool forTest, bool forExport, int chainID) { auto result = std::make_shared(); result->extraCoreData = std::make_shared(); auto status = std::make_shared(); @@ -60,7 +60,7 @@ namespace Configs { } result->coreConfig = QString2QJsonObject(customBean->config_simple); } else { - BuildConfigSingBox(status); + BuildConfigSingBox(status, ruleSetMap); } // apply custom config @@ -116,7 +116,7 @@ namespace Configs { } - std::shared_ptr BuildTestConfig(const QList>& profiles) { + std::shared_ptr BuildTestConfig(const QList>& profiles, const std::map& ruleSetMap) { auto results = std::make_shared(); QJsonArray outboundArray = { @@ -140,7 +140,7 @@ namespace Configs { item->latency = -1; continue; } - auto res = BuildConfig(item, true, false, ++index); + auto res = BuildConfig(item, ruleSetMap, true, false, ++index); if (!res->error.isEmpty()) { results->error = res->error; return results; @@ -498,7 +498,7 @@ namespace Configs { } - void BuildConfigSingBox(const std::shared_ptr &status) { + void BuildConfigSingBox(const std::shared_ptr &status, const std::map& ruleSetMap) { // Prefetch auto routeChain = profileManager->GetRouteChain(dataStore->routing->current_route_id); if (routeChain == nullptr) { @@ -656,12 +656,6 @@ namespace Configs { // custom inbound if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray()) - // Routing - if (NeedGeoAssets()) { - status->result->error = "Geo Assets are missing, please download them through Basic Settings -> Assets"; - return; - } - // manage routing section auto routeObj = QJsonObject(); if (dataStore->spmode_vpn) { @@ -749,8 +743,6 @@ namespace Configs { } auto ruleSetArray = QJsonArray(); - auto geoSitePath = GetCoreAssetDir("geosite.db"); - auto geoIpPath = GetCoreAssetDir("geoip.db"); for (const auto &item: *neededRuleSets) { if(auto url = QUrl(item); url.isValid() && url.fileName().contains(".srs")) { ruleSetArray += QJsonObject{ @@ -761,26 +753,13 @@ namespace Configs { }; } else { + QString srsUrl = QString::fromStdString(ruleSetMap.at(item.toStdString())); ruleSetArray += QJsonObject{ - {"type", "local"}, - {"tag", item}, + {"type", "remote"}, + {"tag", get_rule_set_name(srsUrl)}, {"format", "binary"}, - {"path", RULE_SETS_DIR + QString("/%1.srs").arg(item)}, + {"url", srsUrl}, }; - 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; - } } } routeObj["rule_set"] = ruleSetArray; diff --git a/src/global/Configs.cpp b/src/global/Configs.cpp index 7791e54..ebee7b3 100644 --- a/src/global/Configs.cpp +++ b/src/global/Configs.cpp @@ -291,10 +291,6 @@ namespace Configs { _add(new configItem("ntp_server_address", &ntp_server_address, itemType::string)); _add(new configItem("ntp_server_port", &ntp_server_port, itemType::integer)); _add(new configItem("ntp_interval", &ntp_interval, itemType::string)); - _add(new configItem("geoip_download_url", &geoip_download_url, itemType::string)); - _add(new configItem("geosite_download_url", &geosite_download_url, itemType::string)); - _add(new configItem("auto_reset_assets_idx", &auto_reset_assets_idx, itemType::integer)); - _add(new configItem("last_asset_reset_unix_secs", &last_asset_reset_epoch_secs, itemType::integer64)); _add(new configItem("enable_dns_server", &enable_dns_server, itemType::boolean)); _add(new configItem("dns_server_listen_lan", &dns_server_listen_lan, itemType::boolean)); _add(new configItem("dns_server_listen_port", &dns_server_listen_port, itemType::integer)); @@ -389,27 +385,4 @@ namespace Configs { QStandardPaths::AppConfigLocation); return qApp->applicationDirPath(); } - - QString GetCoreAssetDir(const QString &name) { - QStringList search = { - GetBasePath(), - QString("/usr/share/sing-geoip"), - QString("/usr/share/sing-geosite"), - QString("/usr/share/sing-box"), - }; - - for (const auto &dir: search) { - if (dir.isEmpty()) - continue; - - if (QFile(QString("%1/%2").arg(dir, name)).exists()) - return dir; - } - - return ""; - } - - bool NeedGeoAssets(){ - return GetCoreAssetDir("geoip.db").isEmpty() || GetCoreAssetDir("geosite.db").isEmpty(); - } } // namespace Configs diff --git a/src/main.cpp b/src/main.cpp index 69b36ac..e8fdbd8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -139,9 +139,6 @@ int main(int argc, char* argv[]) { if (!dir.exists(ROUTES_PREFIX_NAME)) { dir_success &= dir.mkdir(ROUTES_PREFIX_NAME); } - if (!dir.exists(RULE_SETS_DIR)) { - dir_success &= dir.mkdir(RULE_SETS_DIR); - } if (!dir_success) { QMessageBox::critical(nullptr, "Error", "No permission to write " + dir.absolutePath()); return 1; diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 856e6c8..e8bdb15 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -417,6 +417,25 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi } }); + auto getRuleSet = [=,this] + { + QString err; + for(int retry = 0; retry < 3; retry++) { + auto resp = NetworkRequestHelper::HttpGet("https://raw.githubusercontent.com/throneproj/routeprofiles/rule-set/list"); + if (resp.error.isEmpty()) { + std::vector respvec; + respvec.assign(resp.data.begin(), resp.data.end()); + auto reply = spb::pb::deserialize(respvec); + ruleSetMap = reply.items; + return; + } + else + err = resp.error; + } + MW_show_log(QObject::tr("Requesting rule-set error: %1").arg(err)); + }; + runOnNewThread(getRuleSet); + auto getRemoteRouteProfiles = [=,this] { auto resp = NetworkRequestHelper::HttpGet("https://api.github.com/repos/throneproj/routeprofiles/releases/latest"); @@ -439,8 +458,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi connect(ui->menuRouting_Menu, &QMenu::aboutToShow, this, [=,this]() { - // refresh it on every menu show - runOnNewThread(getRemoteRouteProfiles); + if(remoteRouteProfiles.isEmpty()) + runOnNewThread(getRemoteRouteProfiles); ui->menuRouting_Menu->clear(); ui->menuRouting_Menu->addAction(ui->menu_routing_settings); mu_remoteRouteProfiles.lock(); @@ -562,33 +581,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi connect(TM_auto_update_subsctiption, &QTimer::timeout, this, [&] { UI_update_all_groups(true); }); TM_auto_update_subsctiption_Reset_Minute(Configs::dataStore->sub_auto_update); - // asset updater timer - auto TM_auto_reset_assets = new QTimer(this); - connect(TM_auto_reset_assets, &QTimer::timeout, this, [&]() - { - auto reset_interval = Configs::GeoAssets::ResetAssetsOptions[Configs::dataStore->auto_reset_assets_idx]; - if (reset_interval > 0 && QDateTime::currentSecsSinceEpoch() - Configs::dataStore->last_asset_reset_epoch_secs > reset_interval) - { - runOnNewThread([=,this] - { - ResetAssets(Configs::dataStore->geoip_download_url, Configs::dataStore->geosite_download_url); - }); - } - }); - TM_auto_reset_assets->start(1000 * 60 * 5); // check every 5 minutes - if (!Configs::dataStore->flag_tray) show(); - if (Configs::NeedGeoAssets()) { - auto n = QMessageBox::warning(GetMessageBoxParent(), software_name, tr("Geo Assets are missing, want to download them now?"), QMessageBox::Yes | QMessageBox::No); - if (n == QMessageBox::Yes) { - runOnNewThread([=,this] - { - DownloadAssets(!Configs::dataStore->geoip_download_url.isEmpty() ? Configs::dataStore->geoip_download_url : Configs::GeoAssets::GeoIPURLs[0], - !Configs::dataStore->geosite_download_url.isEmpty() ? Configs::dataStore->geosite_download_url : Configs::GeoAssets::GeoSiteURLs[0]); - }); - } - } ui->data_view->setStyleSheet("background: transparent; border: none;"); } @@ -721,19 +715,6 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info) on_menu_exit_triggered(); } } - if (info.contains("DownloadAssets")) { - auto splitted = info.split(";"); - runOnNewThread([=,this](){ - DownloadAssets(splitted[1], splitted[2]); - }); - } - if (info.contains("ResetAssets")) - { - auto splitted = info.split(";"); - runOnNewThread([=,this](){ - ResetAssets(splitted[1], splitted[2]); - }); - } // if (info == "RestartProgram") { this->exit_reason = 2; @@ -822,7 +803,14 @@ void MainWindow::on_menu_manage_groups_triggered() { } void MainWindow::on_menu_routing_settings_triggered() { - USE_DIALOG(DialogManageRoutes) + if (dialog_is_using) return; + dialog_is_using = true; + auto dialog = new DialogManageRoutes(this, ruleSetMap); + connect(dialog, &QDialog::finished, this, [=,this] { + dialog->deleteLater(); + dialog_is_using = false; + }); + dialog->show(); } void MainWindow::on_menu_vpn_settings_triggered() { @@ -1642,7 +1630,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 = BuildConfig(ent, ruleSetMap, false, true); QString config_core = QJsonObject2QString(result->coreConfig, true); QApplication::clipboard()->setText(config_core); @@ -1654,11 +1642,11 @@ void MainWindow::on_menu_export_config_triggered() { msg.setDefaultButton(QMessageBox::Ok); msg.exec(); if (msg.clickedButton() == button_1) { - result = BuildConfig(ent, false, false); + result = BuildConfig(ent, ruleSetMap, false, false); config_core = QJsonObject2QString(result->coreConfig, true); QApplication::clipboard()->setText(config_core); } else if (msg.clickedButton() == button_2) { - result = BuildConfig(ent, true, false); + result = BuildConfig(ent, ruleSetMap, true, false); config_core = QJsonObject2QString(result->coreConfig, true); QApplication::clipboard()->setText(config_core); } @@ -2298,62 +2286,6 @@ bool MainWindow::StopVPNProcess() { return true; } -void MainWindow::DownloadAssets(const QString &geoipUrl, const QString &geositeUrl) { - if (!mu_download_assets.tryLock()) { - runOnUiThread([=,this](){ - MessageBoxWarning(tr("Cannot start"), tr("Last download request has not finished yet")); - }); - return; - } - MW_show_log("Start downloading..."); - QString errors; - if (!geoipUrl.isEmpty()) { - auto resp = NetworkRequestHelper::DownloadAsset(geoipUrl, "geoip.db"); - if (!resp.isEmpty()) { - MW_show_log(QString(tr("Failed to download geoip: %1")).arg(resp)); - errors += "geoip: " + resp; - } - } - if (!geositeUrl.isEmpty()) { - auto resp = NetworkRequestHelper::DownloadAsset(geositeUrl, "geosite.db"); - if (!resp.isEmpty()) { - MW_show_log(QString(tr("Failed to download geosite: %1")).arg(resp)); - errors += "\ngeosite: " + resp; - } - } - mu_download_assets.unlock(); - if (!errors.isEmpty()) { - runOnUiThread([=,this](){ - MessageBoxWarning(tr("Failed to download geo assets"), errors); - }); - } - MW_show_log(tr("Geo Asset update completed!")); -} - -void MainWindow::ResetAssets(const QString& geoipUrl, const QString& geositeUrl) -{ - if (!mu_reset_assets.try_lock()) - { - MW_show_log(tr("A reset of assets is already in progress")); - return; - } - DownloadAssets(geoipUrl, geositeUrl); - auto entries = QDir(RULE_SETS_DIR).entryList(QDir::Files); - for (const auto &item: entries) { - if (!QFile(RULE_SETS_DIR + "/" + item).remove()) { - MW_show_log("Failed to remove " + item + ", stop the core then try again"); - } - } - MW_show_log(tr("Removed all rule-set files")); - - runOnUiThread([=,this] - { - if (Configs::dataStore->started_id >= 0) profile_start(Configs::dataStore->started_id); - }); - Configs::dataStore->last_asset_reset_epoch_secs = QDateTime::currentSecsSinceEpoch(); - mu_reset_assets.unlock(); -} - bool isNewer(QString assetName) { if (QString(NKR_VERSION).isEmpty()) return false; assetName = assetName.mid(7); // take out Throne- diff --git a/src/ui/mainwindow_grpc.cpp b/src/ui/mainwindow_grpc.cpp index e36b0f5..766d2d8 100644 --- a/src/ui/mainwindow_grpc.cpp +++ b/src/ui/mainwindow_grpc.cpp @@ -141,7 +141,7 @@ void MainWindow::urltest_current_group(const QListerror.isEmpty()) { MW_show_log(tr("Failed to build test config: ") + buildObject->error); speedtestRunning.unlock(); @@ -236,7 +236,7 @@ void MainWindow::speedtest_current_group(const QListerror.isEmpty()) { MW_show_log(tr("Failed to build test config: ") + buildObject->error); speedtestRunning.unlock(); @@ -420,7 +420,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 = BuildConfig(ent, ruleSetMap, false, false); if (!result->error.isEmpty()) { MessageBoxWarning(tr("BuildConfig return error"), result->error); return; diff --git a/src/ui/setting/RouteItem.cpp b/src/ui/setting/RouteItem.cpp index f2d4c25..fca733d 100644 --- a/src/ui/setting/RouteItem.cpp +++ b/src/ui/setting/RouteItem.cpp @@ -47,7 +47,7 @@ QStringList get_all_outbounds() { return res; } -RouteItem::RouteItem(QWidget *parent, const std::shared_ptr& routeChain) +RouteItem::RouteItem(QWidget *parent, const std::shared_ptr& routeChain, const std::map& ruleSetMap) : QDialog(parent), ui(new Ui::RouteItem) { ui->setupUi(this); @@ -64,10 +64,9 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptrGetGeoList(&ok, API::GeoRuleSetType::ip, Configs::GetCoreAssetDir("geoip.db")); - auto geoSiteList = API::defaultClient->GetGeoList(&ok, API::GeoRuleSetType::site, Configs::GetCoreAssetDir("geosite.db")); - geo_items << geoIpList << geoSiteList; + for (const auto& item : ruleSetMap) { + geo_items.append("ruleset:" + QString::fromStdString(item.first)); + } rule_set_editor = new AutoCompleteTextEdit("", geo_items, this); ui->rule_attr_data->layout()->addWidget(rule_set_editor); ui->rule_attr_data->adjustSize(); @@ -124,11 +123,8 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptrgroupBox_core->setTitle(software_core_name); - // Assets - ui->geoip_url->setEditable(true); - ui->geosite_url->setEditable(true); - ui->geoip_url->addItems(Configs::GeoAssets::GeoIPURLs); - ui->geosite_url->addItems(Configs::GeoAssets::GeoSiteURLs); - ui->geoip_url->setCurrentText(Configs::dataStore->geoip_download_url); - ui->geosite_url->setCurrentText(Configs::dataStore->geosite_download_url); - ui->auto_reset->setCurrentIndex(Configs::dataStore->auto_reset_assets_idx); - - connect(ui->download_geo_btn, &QPushButton::clicked, this, [=,this]() { - MW_dialog_message(Dialog_DialogBasicSettings, "DownloadAssets;"+ui->geoip_url->currentText()+";"+ui->geosite_url->currentText()); - }); - connect(ui->remove_srs_btn, &QPushButton::clicked, this, [=,this](){ - auto rsDir = QDir(RULE_SETS_DIR); - auto entries = rsDir.entryList(QDir::Files); - for (const auto &item: entries) { - if (!QFile(RULE_SETS_DIR + "/" + item).remove()) { - MW_show_log("Failed to remove " + item + ", stop the core then try again"); - } - } - MW_show_log(tr("Removed all rule-set files")); - }); - connect(ui->reset_assets, &QPushButton::clicked, this, [=,this]() - { - MW_dialog_message(Dialog_DialogBasicSettings, "ResetAssets;"+ui->geoip_url->currentText()+";"+ui->geosite_url->currentText()); - }); - // Mux D_LOAD_INT(mux_concurrency) D_LOAD_COMBO_STRING(mux_protocol) @@ -230,11 +203,6 @@ void DialogBasicSettings::accept() { // Core Configs::dataStore->disable_traffic_stats = ui->disable_stats->isChecked(); - // Assets - Configs::dataStore->geoip_download_url = ui->geoip_url->currentText(); - Configs::dataStore->geosite_download_url = ui->geosite_url->currentText(); - Configs::dataStore->auto_reset_assets_idx = ui->auto_reset->currentIndex(); - // Mux D_SAVE_INT(mux_concurrency) D_SAVE_COMBO_STRING(mux_protocol) diff --git a/src/ui/setting/dialog_manage_routes.cpp b/src/ui/setting/dialog_manage_routes.cpp index 4402eb4..fea2574 100644 --- a/src/ui/setting/dialog_manage_routes.cpp +++ b/src/ui/setting/dialog_manage_routes.cpp @@ -59,7 +59,7 @@ bool DialogManageRoutes::validate_dns_rules(const QString &rawString) { return true; } -DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(new Ui::DialogManageRoutes) { +DialogManageRoutes::DialogManageRoutes(QWidget *parent, const std::map& dataMap) : QDialog(parent), ui(new Ui::DialogManageRoutes) { ui->setupUi(this); auto profiles = Configs::profileManager->routes; for (const auto &item: profiles) { @@ -139,15 +139,10 @@ DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(ne MessageBoxInfo("What is this?", Configs::Information::HijackInfo); }); - bool ok; - auto geoIpList = API::defaultClient->GetGeoList(&ok, API::GeoRuleSetType::ip, Configs::GetCoreAssetDir("geoip.db")); - auto geoSiteList = API::defaultClient->GetGeoList(&ok, API::GeoRuleSetType::site, Configs::GetCoreAssetDir("geosite.db")); + ruleSetMap = dataMap; QStringList ruleItems = {"domain:", "suffix:", "regex:"}; - for (const auto& geoIP : geoIpList) { - ruleItems.append("ruleset:"+geoIP); - } - for (const auto& geoSite: geoSiteList) { - ruleItems.append("ruleset:"+geoSite); + for (const auto& item : ruleSetMap) { + ruleItems.append("ruleset:" + QString::fromStdString(item.first)); } rule_editor = new AutoCompleteTextEdit("", ruleItems, this); ui->hijack_box->layout()->replaceWidget(ui->dnshijack_rules, rule_editor); @@ -235,7 +230,7 @@ void DialogManageRoutes::accept() { } void DialogManageRoutes::on_new_route_clicked() { - routeChainWidget = new RouteItem(this, Configs::ProfileManager::NewRouteChain()); + routeChainWidget = new RouteItem(this, Configs::ProfileManager::NewRouteChain(), ruleSetMap); routeChainWidget->setWindowModality(Qt::ApplicationModal); routeChainWidget->show(); connect(routeChainWidget, &RouteItem::settingsChanged, this, [=,this](const std::shared_ptr& chain) {