feat: "!"(not) support for geosite

eg. GEOSITE,!CN,Proxy & dns.fallback-filter.geosite: ['!CN']
This commit is contained in:
adlyq 2022-05-15 13:16:45 +08:00
parent 63917aa020
commit efc7c82cac
4 changed files with 33 additions and 15 deletions

View file

@ -33,9 +33,10 @@ func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) {
type DomainMatcher struct { type DomainMatcher struct {
matchers strmatcher.IndexMatcher matchers strmatcher.IndexMatcher
not bool
} }
func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) { func NewMphMatcherGroup(domains []*Domain, not bool) (*DomainMatcher, error) {
g := strmatcher.NewMphMatcherGroup() g := strmatcher.NewMphMatcherGroup()
for _, d := range domains { for _, d := range domains {
matcherType, f := matcherTypeMap[d.Type] matcherType, f := matcherTypeMap[d.Type]
@ -50,11 +51,12 @@ func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
g.Build() g.Build()
return &DomainMatcher{ return &DomainMatcher{
matchers: g, matchers: g,
not: not,
}, nil }, nil
} }
// NewDomainMatcher new domain matcher. // NewDomainMatcher new domain matcher.
func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) { func NewDomainMatcher(domains []*Domain, not bool) (*DomainMatcher, error) {
g := new(strmatcher.MatcherGroup) g := new(strmatcher.MatcherGroup)
for _, d := range domains { for _, d := range domains {
m, err := domainToMatcher(d) m, err := domainToMatcher(d)
@ -66,11 +68,16 @@ func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
return &DomainMatcher{ return &DomainMatcher{
matchers: g, matchers: g,
not: not,
}, nil }, nil
} }
func (m *DomainMatcher) ApplyDomain(domain string) bool { 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. // CIDRList is an alias of []*CIDR to provide sort.Interface.

View file

@ -1,6 +1,7 @@
package geodata package geodata
import ( import (
"fmt"
"github.com/Dreamacro/clash/component/geodata/router" "github.com/Dreamacro/clash/component/geodata/router"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"strings" "strings"
@ -35,6 +36,16 @@ func Verify(name string) bool {
} }
func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error) { 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) geoLoader, err := GetGeoDataLoader(geoLoaderName)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
@ -50,7 +61,7 @@ func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error)
matcher, err := router.NewDomainMatcher(domains) matcher, err := router.NewDomainMatcher(domains)
mphminimal perfect hash algorithm mphminimal perfect hash algorithm
*/ */
matcher, err := router.NewMphMatcherGroup(domains) matcher, err := router.NewMphMatcherGroup(domains, not)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }

View file

@ -7,7 +7,6 @@ import (
"go.uber.org/atomic" "go.uber.org/atomic"
"math/rand" "math/rand"
"net/netip" "net/netip"
"strings"
"time" "time"
"github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/common/cache"
@ -232,7 +231,7 @@ func (r *Resolver) matchPolicy(m *D.Msg) []dnsClient {
return nil return nil
} }
domain := r.msgToDomain(m) domain := msgToDomain(m)
if domain == "" { if domain == "" {
return nil return nil
} }
@ -251,7 +250,7 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool {
return false return false
} }
domain := r.msgToDomain(m) domain := msgToDomain(m)
if domain == "" { if domain == "" {
return false return false
@ -332,14 +331,6 @@ func (r *Resolver) resolveIP(host string, dnsType uint16) (ips []netip.Addr, err
return 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 { func (r *Resolver) asyncExchange(ctx context.Context, client []dnsClient, msg *D.Msg) <-chan *result {
ch := make(chan *result, 1) ch := make(chan *result, 1)
go func() { go func() {

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net" "net"
"net/netip" "net/netip"
"strings"
"time" "time"
"github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/common/cache"
@ -116,6 +117,14 @@ func msgToIP(msg *D.Msg) []netip.Addr {
return ips return ips
} }
func msgToDomain(msg *D.Msg) string {
if len(msg.Question) > 0 {
return strings.TrimRight(msg.Question[0].Name, ".")
}
return ""
}
type wrapPacketConn struct { type wrapPacketConn struct {
net.PacketConn net.PacketConn
rAddr net.Addr rAddr net.Addr