Files
xray-core/common/geodata/domain_matcher.go

67 lines
1.6 KiB
Go

package geodata
import (
"context"
"strings"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/geodata/strmatcher"
)
type DomainMatcher interface {
Match(input string) []uint32
MatchAny(input string) bool
}
func buildDomainMatcher(rules []*DomainRule) (DomainMatcher, error) {
g := strmatcher.NewMphValueMatcher()
for i, r := range rules {
switch v := r.Value.(type) {
case *DomainRule_Custom:
m, err := parseDomain(v.Custom)
if err != nil {
return nil, err
}
g.Add(m, uint32(i))
case *DomainRule_Geosite:
domains, err := loadSiteWithAttrs(v.Geosite.File, v.Geosite.Code, v.Geosite.Attrs)
if err != nil {
return nil, err
}
for j, d := range domains {
domains[j] = nil // peak mem
m, err := parseDomain(d)
if err != nil {
errors.LogError(context.Background(), "ignore invalid geosite entry in ", v.Geosite.File, ":", v.Geosite.Code, " at index ", j, ", ", err)
continue
}
g.Add(m, uint32(i))
}
default:
panic("unknown domain rule type")
}
}
if err := g.Build(); err != nil {
return nil, err
}
return g, nil
}
func parseDomain(d *Domain) (strmatcher.Matcher, error) {
if d == nil {
return nil, errors.New("domain must not be nil")
}
switch d.Type {
case Domain_Substr:
return strmatcher.Substr.New(strings.ToLower(d.Value))
case Domain_Regex:
return strmatcher.Regex.New(d.Value)
case Domain_Domain:
return strmatcher.Domain.New(d.Value)
case Domain_Full:
return strmatcher.Full.New(strings.ToLower(d.Value))
default:
return nil, errors.New("unknown domain type: ", d.Type)
}
}