package router import ( "fmt" "net" "strings" "github.com/Dreamacro/clash/component/geodata/strmatcher" ) var matcherTypeMap = map[Domain_Type]strmatcher.Type{ Domain_Plain: strmatcher.Substr, Domain_Regex: strmatcher.Regex, Domain_Domain: strmatcher.Domain, Domain_Full: strmatcher.Full, } func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) { matcherType, f := matcherTypeMap[domain.Type] if !f { return nil, fmt.Errorf("unsupported domain type %v", domain.Type) } matcher, err := matcherType.New(domain.Value) if err != nil { return nil, fmt.Errorf("failed to create domain matcher, base error: %s", err.Error()) } return matcher, nil } type DomainMatcher struct { matchers strmatcher.IndexMatcher } func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) { g := strmatcher.NewMphMatcherGroup() for _, d := range domains { matcherType, f := matcherTypeMap[d.Type] if !f { return nil, fmt.Errorf("unsupported domain type %v", d.Type) } _, err := g.AddPattern(d.Value, matcherType) if err != nil { return nil, err } } g.Build() return &DomainMatcher{ matchers: g, }, nil } // NewDomainMatcher new domain matcher. func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) { g := new(strmatcher.MatcherGroup) for _, d := range domains { m, err := domainToMatcher(d) if err != nil { return nil, err } g.Add(m) } return &DomainMatcher{ matchers: g, }, nil } func (m *DomainMatcher) ApplyDomain(domain string) bool { return len(m.matchers.Match(strings.ToLower(domain))) > 0 } type MultiGeoIPMatcher struct { matchers []*GeoIPMatcher } func NewGeoIPMatcher(geoip *GeoIP) (*GeoIPMatcher, error) { matcher, err := globalGeoIPContainer.Add(geoip) if err != nil { return nil, err } return matcher, nil } func (m *MultiGeoIPMatcher) ApplyIp(ip net.IP) bool { for _, matcher := range m.matchers { if matcher.Match(ip) { return true } } return false } func NewMultiGeoIPMatcher(geoips []*GeoIP) (*MultiGeoIPMatcher, error) { var matchers []*GeoIPMatcher for _, geoip := range geoips { matcher, err := globalGeoIPContainer.Add(geoip) if err != nil { return nil, err } matchers = append(matchers, matcher) } matcher := &MultiGeoIPMatcher{ matchers: matchers, } return matcher, nil }