cachable domain matcher, step 1

pull/692/merge
Darien Raymond 7 years ago
parent 482793d28a
commit 6b77e14bf6

@ -64,13 +64,35 @@ func (v *AnyCondition) Len() int {
return len(*v)
}
type PlainDomainMatcher string
type CachableDomainMatcher struct {
matchers []domainMatcher
}
func NewPlainDomainMatcher(pattern string) Condition {
return PlainDomainMatcher(pattern)
func NewCachableDomainMatcher() *CachableDomainMatcher {
return &CachableDomainMatcher{
matchers: make([]domainMatcher, 0, 64),
}
}
func (m *CachableDomainMatcher) Add(domain *Domain) error {
switch domain.Type {
case Domain_Plain:
m.matchers = append(m.matchers, NewPlainDomainMatcher(domain.Value))
case Domain_Regex:
rm, err := NewRegexpDomainMatcher(domain.Value)
if err != nil {
return err
}
m.matchers = append(m.matchers, rm)
case Domain_Domain:
m.matchers = append(m.matchers, NewSubDomainMatcher(domain.Value))
default:
return newError("unknown domain type: ", domain.Type).AtError()
}
return nil
}
func (v PlainDomainMatcher) Apply(ctx context.Context) bool {
func (m *CachableDomainMatcher) Apply(ctx context.Context) bool {
dest, ok := proxy.TargetFromContext(ctx)
if !ok {
return false
@ -80,6 +102,27 @@ func (v PlainDomainMatcher) Apply(ctx context.Context) bool {
return false
}
domain := dest.Address.Domain()
for _, matcher := range m.matchers {
if matcher.Apply(domain) {
return true
}
}
return false
}
type domainMatcher interface {
Apply(domain string) bool
}
type PlainDomainMatcher string
func NewPlainDomainMatcher(pattern string) PlainDomainMatcher {
return PlainDomainMatcher(pattern)
}
func (v PlainDomainMatcher) Apply(domain string) bool {
return strings.Contains(domain, string(v))
}
@ -97,33 +140,17 @@ func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
}, nil
}
func (v *RegexpDomainMatcher) Apply(ctx context.Context) bool {
dest, ok := proxy.TargetFromContext(ctx)
if !ok {
return false
}
if !dest.Address.Family().IsDomain() {
return false
}
domain := dest.Address.Domain()
func (v *RegexpDomainMatcher) Apply(domain string) bool {
return v.pattern.MatchString(strings.ToLower(domain))
}
type SubDomainMatcher string
func NewSubDomainMatcher(p string) Condition {
func NewSubDomainMatcher(p string) SubDomainMatcher {
return SubDomainMatcher(p)
}
func (m SubDomainMatcher) Apply(ctx context.Context) bool {
dest, ok := proxy.TargetFromContext(ctx)
if !ok {
return false
}
if !dest.Address.Family().IsDomain() {
return false
}
domain := dest.Address.Domain()
func (m SubDomainMatcher) Apply(domain string) bool {
pattern := string(m)
if !strings.HasSuffix(domain, pattern) {
return false

@ -16,32 +16,32 @@ func TestSubDomainMatcher(t *testing.T) {
cases := []struct {
pattern string
input context.Context
input string
output bool
}{
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v2ray.com"), 80)),
input: "www.v2ray.com",
output: true,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)),
input: "v2ray.com",
output: true,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v3ray.com"), 80)),
input: "www.v3ray.com",
output: false,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("2ray.com"), 80)),
input: "2ray.com",
output: false,
},
{
pattern: "v2ray.com",
input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("xv2ray.com"), 80)),
input: "xv2ray.com",
output: false,
},
}

@ -52,24 +52,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
conds := NewConditionChan()
if len(rr.Domain) > 0 {
anyCond := NewAnyCondition()
matcher := NewCachableDomainMatcher()
for _, domain := range rr.Domain {
switch domain.Type {
case Domain_Plain:
anyCond.Add(NewPlainDomainMatcher(domain.Value))
case Domain_Regex:
matcher, err := NewRegexpDomainMatcher(domain.Value)
if err != nil {
return nil, err
}
anyCond.Add(matcher)
case Domain_Domain:
anyCond.Add(NewSubDomainMatcher(domain.Value))
default:
panic("Unknown domain type.")
}
matcher.Add(domain)
}
conds.Add(anyCond)
conds.Add(matcher)
}
if len(rr.Cidr) > 0 {

Loading…
Cancel
Save