Ver código fonte

Improve load geosite

世界 3 anos atrás
pai
commit
d45007b501
4 arquivos alterados com 33 adições e 29 exclusões
  1. 1 2
      adapter/router.go
  2. 0 3
      common/sniff/tls.go
  3. 19 2
      route/router.go
  4. 13 22
      route/rule_geosite.go

+ 1 - 2
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)

+ 0 - 3
common/sniff/tls.go

@@ -24,6 +24,3 @@ func TLSClientHello(ctx context.Context, reader io.Reader) (*adapter.InboundCont
 	}
 	return nil, err
 }
-
-func Packet() {
-}

+ 19 - 2
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) {

+ 13 - 22
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))
-	}
-	matcherRule := geosite.Merge(subRules)
-	matcher, err := NewDefaultRule(r.router, r.logger, matcherRule)
-	if err != nil {
-		return E.Cause(err, "compile geosite")
+		matchers = append(matchers, matcher)
 	}
-	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 {