1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-11-03 16:57:38 -05:00
v2fly/common/strmatcher/domain_matcher.go

89 lines
1.6 KiB
Go
Raw Normal View History

2018-08-19 15:04:15 -04:00
package strmatcher
import "strings"
func breakDomain(domain string) []string {
return strings.Split(domain, ".")
}
type node struct {
value uint32
sub map[string]*node
}
2018-08-20 09:39:58 -04:00
// DomainMatcherGroup is a IndexMatcher for a large set of Domain matchers.
// Visible for testing only.
2018-08-19 15:04:15 -04:00
type DomainMatcherGroup struct {
root *node
}
func (g *DomainMatcherGroup) Add(domain string, value uint32) {
if g.root == nil {
2018-08-22 16:49:02 -04:00
g.root = new(node)
2018-08-19 15:04:15 -04:00
}
current := g.root
parts := breakDomain(domain)
for i := len(parts) - 1; i >= 0; i-- {
2018-09-08 15:54:09 -04:00
if current.value > 0 {
// if current node is already a match, it is not necessary to match further.
return
}
2018-08-19 15:04:15 -04:00
part := parts[i]
2018-08-22 16:49:02 -04:00
if current.sub == nil {
current.sub = make(map[string]*node)
}
2018-08-19 15:04:15 -04:00
next := current.sub[part]
if next == nil {
2018-08-22 16:49:02 -04:00
next = new(node)
2018-08-19 15:04:15 -04:00
current.sub[part] = next
}
current = next
}
current.value = value
2018-09-08 15:54:09 -04:00
current.sub = nil // shortcut sub nodes as current node is a match.
2018-08-19 15:04:15 -04:00
}
2018-08-20 03:57:06 -04:00
func (g *DomainMatcherGroup) addMatcher(m domainMatcher, value uint32) {
g.Add(string(m), value)
}
2018-08-19 15:04:15 -04:00
func (g *DomainMatcherGroup) Match(domain string) uint32 {
2018-11-02 07:14:41 -04:00
if len(domain) == 0 {
return 0
}
2018-08-19 15:04:15 -04:00
current := g.root
if current == nil {
return 0
}
2018-11-02 07:14:41 -04:00
nextPart := func(idx int) int {
for i := idx - 1; i >= 0; i-- {
if domain[i] == '.' {
return i
}
}
return -1
}
idx := len(domain)
for {
if idx == -1 || current.sub == nil {
2018-08-22 16:49:02 -04:00
break
}
2018-11-02 07:14:41 -04:00
nidx := nextPart(idx)
part := domain[nidx+1 : idx]
2018-08-19 15:04:15 -04:00
next := current.sub[part]
if next == nil {
break
}
current = next
2018-11-02 07:14:41 -04:00
idx = nidx
2018-08-19 15:04:15 -04:00
}
return current.value
}