From d45007b501050632de0e235b27c532d0d63addfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Fri, 8 Jul 2022 11:00:46 +0800 Subject: [PATCH] Improve load geosite --- adapter/router.go | 3 +-- common/sniff/tls.go | 3 --- route/router.go | 21 +++++++++++++++++++-- route/rule_geosite.go | 35 +++++++++++++---------------------- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/adapter/router.go b/adapter/router.go index f6d0c8e3..446d815c 100644 --- a/adapter/router.go +++ b/adapter/router.go @@ -8,7 +8,6 @@ import ( N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing-box/common/geoip" - "github.com/sagernet/sing-box/common/geosite" C "github.com/sagernet/sing-box/constant" "golang.org/x/net/dns/dnsmessage" @@ -21,7 +20,7 @@ type Router interface { RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error GeoIPReader() *geoip.Reader - GeositeReader() *geosite.Reader + LoadGeosite(code string) (Rule, error) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) Lookup(ctx context.Context, domain string, strategy C.DomainStrategy) ([]netip.Addr, error) LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error) diff --git a/common/sniff/tls.go b/common/sniff/tls.go index e7b45b76..a65f547e 100644 --- a/common/sniff/tls.go +++ b/common/sniff/tls.go @@ -24,6 +24,3 @@ func TLSClientHello(ctx context.Context, reader io.Reader) (*adapter.InboundCont } return nil, err } - -func Packet() { -} diff --git a/route/router.go b/route/router.go index a1035850..83bf4e69 100644 --- a/route/router.go +++ b/route/router.go @@ -53,6 +53,7 @@ type Router struct { geositeOptions option.GeositeOptions geoIPReader *geoip.Reader geositeReader *geosite.Reader + geositeCache map[string]adapter.Rule dnsClient adapter.DNSClient defaultDomainStrategy C.DomainStrategy @@ -75,6 +76,7 @@ func NewRouter(ctx context.Context, logger log.Logger, options option.RouteOptio needGeositeDatabase: hasGeoRule(options.Rules, isGeositeRule) || hasGeoDNSRule(dnsOptions.Rules, isGeositeDNSRule), geoIPOptions: common.PtrValueOrDefault(options.GeoIP), geositeOptions: common.PtrValueOrDefault(options.Geosite), + geositeCache: make(map[string]adapter.Rule), defaultDetour: options.Final, dnsClient: dns.NewClient(dnsOptions.DNSClientOptions), defaultDomainStrategy: C.DomainStrategy(dnsOptions.Strategy), @@ -285,6 +287,8 @@ func (r *Router) Start() error { if err != nil { return err } + r.geositeCache = nil + r.geositeReader = nil } return nil } @@ -311,8 +315,21 @@ func (r *Router) GeoIPReader() *geoip.Reader { return r.geoIPReader } -func (r *Router) GeositeReader() *geosite.Reader { - return r.geositeReader +func (r *Router) LoadGeosite(code string) (adapter.Rule, error) { + rule, cached := r.geositeCache[code] + if cached { + return rule, nil + } + items, err := r.geositeReader.Read(code) + if err != nil { + return nil, err + } + rule, err = NewDefaultRule(r, nil, geosite.Compile(items)) + if err != nil { + return nil, err + } + r.geositeCache[code] = rule + return rule, nil } func (r *Router) Outbound(tag string) (adapter.Outbound, bool) { diff --git a/route/rule_geosite.go b/route/rule_geosite.go index 4fe120b7..d334c08a 100644 --- a/route/rule_geosite.go +++ b/route/rule_geosite.go @@ -6,18 +6,16 @@ import ( E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/geosite" "github.com/sagernet/sing-box/log" - "github.com/sagernet/sing-box/option" ) var _ RuleItem = (*GeositeItem)(nil) type GeositeItem struct { - router adapter.Router - logger log.Logger - codes []string - matcher *DefaultRule + router adapter.Router + logger log.Logger + codes []string + matchers []adapter.Rule } func NewGeositeItem(router adapter.Router, logger log.Logger, codes []string) *GeositeItem { @@ -29,32 +27,25 @@ func NewGeositeItem(router adapter.Router, logger log.Logger, codes []string) *G } func (r *GeositeItem) Update() error { - geositeReader := r.router.GeositeReader() - if geositeReader == nil { - return E.New("geosite reader is not initialized") - } - var subRules []option.DefaultRule + var matchers []adapter.Rule for _, code := range r.codes { - items, err := geositeReader.Read(code) + matcher, err := r.router.LoadGeosite(code) if err != nil { return E.Cause(err, "read geosite") } - subRules = append(subRules, geosite.Compile(items)) + matchers = append(matchers, matcher) } - matcherRule := geosite.Merge(subRules) - matcher, err := NewDefaultRule(r.router, r.logger, matcherRule) - if err != nil { - return E.Cause(err, "compile geosite") - } - r.matcher = matcher + r.matchers = matchers return nil } func (r *GeositeItem) Match(metadata *adapter.InboundContext) bool { - if r.matcher == nil { - return false + for _, matcher := range r.matchers { + if matcher.Match(metadata) { + return true + } } - return r.matcher.Match(metadata) + return false } func (r *GeositeItem) String() string {