Geodata: Cleanup unneeded matchers & domain: ignore case (#6342)

Completes https://github.com/XTLS/Xray-core/pull/6139
This commit is contained in:
Meow
2026-06-19 20:02:27 +08:00
committed by GitHub
parent 8734774e4a
commit be8009c625
5 changed files with 51 additions and 21 deletions
+1 -1
View File
@@ -220,7 +220,7 @@ func parseDomain(d *Domain) (strmatcher.Matcher, error) {
case Domain_Regex: case Domain_Regex:
return strmatcher.Regex.New(d.Value) return strmatcher.Regex.New(d.Value)
case Domain_Domain: case Domain_Domain:
return strmatcher.Domain.New(d.Value) return strmatcher.Domain.New(strings.ToLower(d.Value))
case Domain_Full: case Domain_Full:
return strmatcher.Full.New(strings.ToLower(d.Value)) return strmatcher.Full.New(strings.ToLower(d.Value))
default: default:
+15 -7
View File
@@ -6,12 +6,14 @@ import (
"sync/atomic" "sync/atomic"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/utils"
"github.com/xtls/xray-core/common/uuid"
) )
type DomainRegistry struct { type DomainRegistry struct {
mu sync.Mutex mu sync.Mutex
factory DomainMatcherFactory factory DomainMatcherFactory
matchers []*DynamicDomainMatcher matchers *utils.WeakCacheMap[uuid.UUID, DynamicDomainMatcher]
} }
func (r *DomainRegistry) BuildDomainMatcher(rules []*DomainRule) (DomainMatcher, error) { func (r *DomainRegistry) BuildDomainMatcher(rules []*DomainRule) (DomainMatcher, error) {
@@ -24,7 +26,7 @@ func (r *DomainRegistry) BuildDomainMatcher(rules []*DomainRule) (DomainMatcher,
} }
d := NewDynamicDomainMatcher(rules, m) d := NewDynamicDomainMatcher(rules, m)
r.matchers = append(r.matchers, d) r.matchers.Store(uuid.New(), d)
return d, nil return d, nil
} }
@@ -32,15 +34,20 @@ func (r *DomainRegistry) Reload() error {
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock() defer r.mu.Unlock()
errors.LogInfo(context.Background(), "reloading GeoSite data for ", len(r.matchers), " domain matcher(s)") var matchers []*DynamicDomainMatcher
r.matchers.Range(func(_ uuid.UUID, matcher *DynamicDomainMatcher) bool {
matchers = append(matchers, matcher)
return true
})
errors.LogInfo(context.Background(), "reloading GeoSite data for ", len(matchers), " domain matcher(s)")
factory := newDomainMatcherFactory() factory := newDomainMatcherFactory()
type reloadEntry struct { type reloadEntry struct {
dynamic *DynamicDomainMatcher dynamic *DynamicDomainMatcher
matcher DomainMatcher matcher DomainMatcher
} }
reloaded := make([]reloadEntry, len(r.matchers)) reloaded := make([]reloadEntry, len(matchers))
for i, d := range r.matchers { for i, d := range matchers {
m, err := factory.BuildMatcher(d.rules) m, err := factory.BuildMatcher(d.rules)
if err != nil { if err != nil {
errors.LogErrorInner(context.Background(), err, "failed to reload GeoSite data for domain matcher ", i) errors.LogErrorInner(context.Background(), err, "failed to reload GeoSite data for domain matcher ", i)
@@ -52,13 +59,14 @@ func (r *DomainRegistry) Reload() error {
entry.dynamic.Reload(entry.matcher) entry.dynamic.Reload(entry.matcher)
} }
r.factory = factory r.factory = factory
errors.LogInfo(context.Background(), "reloaded GeoSite data for ", len(r.matchers), " domain matcher(s)") errors.LogInfo(context.Background(), "reloaded GeoSite data for ", len(matchers), " domain matcher(s)")
return nil return nil
} }
func newDomainRegistry() *DomainRegistry { func newDomainRegistry() *DomainRegistry {
return &DomainRegistry{ return &DomainRegistry{
factory: newDomainMatcherFactory(), factory: newDomainMatcherFactory(),
matchers: utils.NewWeakCacheMap[uuid.UUID, DynamicDomainMatcher](),
} }
} }
+19 -11
View File
@@ -7,25 +7,27 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/utils"
"github.com/xtls/xray-core/common/uuid"
) )
type IPRegistry struct { type IPRegistry struct {
mu sync.Mutex mu sync.Mutex
ipsetFactory *IPSetFactory factory *IPSetFactory
matchers []*DynamicIPMatcher matchers *utils.WeakCacheMap[uuid.UUID, DynamicIPMatcher]
} }
func (r *IPRegistry) BuildIPMatcher(rules []*IPRule) (IPMatcher, error) { func (r *IPRegistry) BuildIPMatcher(rules []*IPRule) (IPMatcher, error) {
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock() defer r.mu.Unlock()
m, err := buildOptimizedIPMatcher(r.ipsetFactory, rules) m, err := buildOptimizedIPMatcher(r.factory, rules)
if err != nil { if err != nil {
return nil, err return nil, err
} }
d := NewDynamicIPMatcher(rules, m) d := NewDynamicIPMatcher(rules, m)
r.matchers = append(r.matchers, d) r.matchers.Store(uuid.New(), d)
return d, nil return d, nil
} }
@@ -33,15 +35,20 @@ func (r *IPRegistry) Reload() error {
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock() defer r.mu.Unlock()
errors.LogInfo(context.Background(), "reloading GeoIP data for ", len(r.matchers), " IP matcher(s)") var matchers []*DynamicIPMatcher
r.matchers.Range(func(_ uuid.UUID, matcher *DynamicIPMatcher) bool {
matchers = append(matchers, matcher)
return true
})
errors.LogInfo(context.Background(), "reloading GeoIP data for ", len(matchers), " IP matcher(s)")
factory := newIPSetFactory() factory := newIPSetFactory()
type reloadEntry struct { type reloadEntry struct {
dynamic *DynamicIPMatcher dynamic *DynamicIPMatcher
matcher IPMatcher matcher IPMatcher
} }
reloaded := make([]reloadEntry, len(r.matchers)) reloaded := make([]reloadEntry, len(matchers))
for i, d := range r.matchers { for i, d := range matchers {
m, err := buildOptimizedIPMatcher(factory, d.rules) m, err := buildOptimizedIPMatcher(factory, d.rules)
if err != nil { if err != nil {
errors.LogErrorInner(context.Background(), err, "failed to reload GeoIP data for IP matcher ", i) errors.LogErrorInner(context.Background(), err, "failed to reload GeoIP data for IP matcher ", i)
@@ -52,14 +59,15 @@ func (r *IPRegistry) Reload() error {
for _, entry := range reloaded { for _, entry := range reloaded {
entry.dynamic.Reload(entry.matcher) entry.dynamic.Reload(entry.matcher)
} }
r.ipsetFactory = factory r.factory = factory
errors.LogInfo(context.Background(), "reloaded GeoIP data for ", len(r.matchers), " IP matcher(s)") errors.LogInfo(context.Background(), "reloaded GeoIP data for ", len(matchers), " IP matcher(s)")
return nil return nil
} }
func newIPRegistry() *IPRegistry { func newIPRegistry() *IPRegistry {
return &IPRegistry{ return &IPRegistry{
ipsetFactory: newIPSetFactory(), factory: newIPSetFactory(),
matchers: utils.NewWeakCacheMap[uuid.UUID, DynamicIPMatcher](),
} }
} }
+2 -2
View File
@@ -138,7 +138,7 @@ func ParseDomainRule(r string, defaultType Domain_Type) (*DomainRule, error) {
} }
prefix := 0 prefix := 0
for _, ext := range [...]string{"ext:", "ext-domain:"} { for _, ext := range [...]string{"ext:", "ext-domain:", "ext-site:"} {
if strings.HasPrefix(r, ext) { if strings.HasPrefix(r, ext) {
prefix = len(ext) prefix = len(ext)
break break
@@ -167,7 +167,7 @@ func ParseDomainRules(rules []string, defaultType Domain_Type) ([]*DomainRule, e
} }
prefix := 0 prefix := 0
for _, ext := range [...]string{"ext:", "ext-domain:"} { for _, ext := range [...]string{"ext:", "ext-domain:", "ext-site:"} {
if strings.HasPrefix(r, ext) { if strings.HasPrefix(r, ext) {
prefix = len(ext) prefix = len(ext)
break break
+14
View File
@@ -1,6 +1,7 @@
package utils package utils
import ( import (
"maps"
"runtime" "runtime"
"sync" "sync"
"weak" "weak"
@@ -43,3 +44,16 @@ func (c *WeakCacheMap[K, V]) Store(key K, value *V) {
} }
}, struct{}{}) }, struct{}{})
} }
func (c *WeakCacheMap[K, V]) Range(f func(K, *V) bool) {
c.mu.Lock()
snapshot := maps.Clone(c.m)
c.mu.Unlock()
for k, v := range snapshot {
if value := v.Value(); value != nil {
if !f(k, value) {
break
}
}
}
}