From efc7c82cacc330f1be0ffa274d2d3140d6881bbe Mon Sep 17 00:00:00 2001 From: adlyq Date: Sun, 15 May 2022 13:16:45 +0800 Subject: [PATCH] feat: "!"(not) support for geosite eg. GEOSITE,!CN,Proxy & dns.fallback-filter.geosite: ['!CN'] --- component/geodata/router/condition.go | 13 ++++++++++--- component/geodata/utils.go | 13 ++++++++++++- dns/resolver.go | 13 ++----------- dns/util.go | 9 +++++++++ 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/component/geodata/router/condition.go b/component/geodata/router/condition.go index 3f620f64..4e0ad46c 100644 --- a/component/geodata/router/condition.go +++ b/component/geodata/router/condition.go @@ -33,9 +33,10 @@ func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) { type DomainMatcher struct { matchers strmatcher.IndexMatcher + not bool } -func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) { +func NewMphMatcherGroup(domains []*Domain, not bool) (*DomainMatcher, error) { g := strmatcher.NewMphMatcherGroup() for _, d := range domains { matcherType, f := matcherTypeMap[d.Type] @@ -50,11 +51,12 @@ func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) { g.Build() return &DomainMatcher{ matchers: g, + not: not, }, nil } // NewDomainMatcher new domain matcher. -func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) { +func NewDomainMatcher(domains []*Domain, not bool) (*DomainMatcher, error) { g := new(strmatcher.MatcherGroup) for _, d := range domains { m, err := domainToMatcher(d) @@ -66,11 +68,16 @@ func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) { return &DomainMatcher{ matchers: g, + not: not, }, nil } func (m *DomainMatcher) ApplyDomain(domain string) bool { - return len(m.matchers.Match(strings.ToLower(domain))) > 0 + isMatched := len(m.matchers.Match(strings.ToLower(domain))) > 0 + if m.not { + isMatched = !isMatched + } + return isMatched } // CIDRList is an alias of []*CIDR to provide sort.Interface. diff --git a/component/geodata/utils.go b/component/geodata/utils.go index 83ad84b8..840e54d0 100644 --- a/component/geodata/utils.go +++ b/component/geodata/utils.go @@ -1,6 +1,7 @@ package geodata import ( + "fmt" "github.com/Dreamacro/clash/component/geodata/router" C "github.com/Dreamacro/clash/constant" "strings" @@ -35,6 +36,16 @@ func Verify(name string) bool { } func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error) { + if len(countryCode) == 0 { + return nil, 0, fmt.Errorf("country code could not be empty") + } + + not := false + if countryCode[0] == '!' { + not = true + countryCode = countryCode[1:] + } + geoLoader, err := GetGeoDataLoader(geoLoaderName) if err != nil { return nil, 0, err @@ -50,7 +61,7 @@ func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error) matcher, err := router.NewDomainMatcher(domains) mph:minimal perfect hash algorithm */ - matcher, err := router.NewMphMatcherGroup(domains) + matcher, err := router.NewMphMatcherGroup(domains, not) if err != nil { return nil, 0, err } diff --git a/dns/resolver.go b/dns/resolver.go index b92b500f..e1fc90a5 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -7,7 +7,6 @@ import ( "go.uber.org/atomic" "math/rand" "net/netip" - "strings" "time" "github.com/Dreamacro/clash/common/cache" @@ -232,7 +231,7 @@ func (r *Resolver) matchPolicy(m *D.Msg) []dnsClient { return nil } - domain := r.msgToDomain(m) + domain := msgToDomain(m) if domain == "" { return nil } @@ -251,7 +250,7 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool { return false } - domain := r.msgToDomain(m) + domain := msgToDomain(m) if domain == "" { return false @@ -332,14 +331,6 @@ func (r *Resolver) resolveIP(host string, dnsType uint16) (ips []netip.Addr, err return } -func (r *Resolver) msgToDomain(msg *D.Msg) string { - if len(msg.Question) > 0 { - return strings.TrimRight(msg.Question[0].Name, ".") - } - - return "" -} - func (r *Resolver) asyncExchange(ctx context.Context, client []dnsClient, msg *D.Msg) <-chan *result { ch := make(chan *result, 1) go func() { diff --git a/dns/util.go b/dns/util.go index bc86d4fa..a0ac3d01 100644 --- a/dns/util.go +++ b/dns/util.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "net/netip" + "strings" "time" "github.com/Dreamacro/clash/common/cache" @@ -116,6 +117,14 @@ func msgToIP(msg *D.Msg) []netip.Addr { return ips } +func msgToDomain(msg *D.Msg) string { + if len(msg.Question) > 0 { + return strings.TrimRight(msg.Question[0].Name, ".") + } + + return "" +} + type wrapPacketConn struct { net.PacketConn rAddr net.Addr