forked from v2ray/v2ray-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
condition.go
169 lines (138 loc) · 3.29 KB
/
condition.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package rules
import (
"net"
"regexp"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
)
type Condition interface {
Apply(dest v2net.Destination) bool
}
type ConditionChan []Condition
func NewConditionChan() *ConditionChan {
var condChan ConditionChan = make([]Condition, 0, 8)
return &condChan
}
func (this *ConditionChan) Add(cond Condition) *ConditionChan {
*this = append(*this, cond)
return this
}
func (this *ConditionChan) Apply(dest v2net.Destination) bool {
for _, cond := range *this {
if !cond.Apply(dest) {
return false
}
}
return true
}
func (this *ConditionChan) Len() int {
return len(*this)
}
type AnyCondition []Condition
func NewAnyCondition() *AnyCondition {
var anyCond AnyCondition = make([]Condition, 0, 8)
return &anyCond
}
func (this *AnyCondition) Add(cond Condition) *AnyCondition {
*this = append(*this, cond)
return this
}
func (this *AnyCondition) Apply(dest v2net.Destination) bool {
for _, cond := range *this {
if cond.Apply(dest) {
return true
}
}
return false
}
func (this *AnyCondition) Len() int {
return len(*this)
}
type PlainDomainMatcher struct {
pattern serial.StringLiteral
}
func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
return &PlainDomainMatcher{
pattern: serial.StringLiteral(pattern),
}
}
func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool {
if !dest.Address().IsDomain() {
return false
}
domain := serial.StringLiteral(dest.Address().Domain())
return domain.Contains(this.pattern)
}
type RegexpDomainMatcher struct {
pattern *regexp.Regexp
}
func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
r, err := regexp.Compile(pattern)
if err != nil {
return nil, err
}
return &RegexpDomainMatcher{
pattern: r,
}, nil
}
func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
if !dest.Address().IsDomain() {
return false
}
domain := serial.StringLiteral(dest.Address().Domain())
return this.pattern.MatchString(domain.ToLower().String())
}
type CIDRMatcher struct {
cidr *net.IPNet
}
func NewCIDRMatcher(ipnet string) (*CIDRMatcher, error) {
_, cidr, err := net.ParseCIDR(ipnet)
if err != nil {
return nil, err
}
return &CIDRMatcher{
cidr: cidr,
}, nil
}
func (this *CIDRMatcher) Apply(dest v2net.Destination) bool {
if !dest.Address().IsIPv4() && !dest.Address().IsIPv6() {
return false
}
return this.cidr.Contains(dest.Address().IP())
}
type IPv4Matcher struct {
ipv4net *v2net.IPNet
}
func NewIPv4Matcher(ipnet *v2net.IPNet) *IPv4Matcher {
return &IPv4Matcher{
ipv4net: ipnet,
}
}
func (this *IPv4Matcher) Apply(dest v2net.Destination) bool {
if !dest.Address().IsIPv4() {
return false
}
return this.ipv4net.Contains(dest.Address().IP())
}
type PortMatcher struct {
port v2net.PortRange
}
func NewPortMatcher(portRange v2net.PortRange) *PortMatcher {
return &PortMatcher{
port: portRange,
}
}
func (this *PortMatcher) Apply(dest v2net.Destination) bool {
return this.port.Contains(dest.Port())
}
type NetworkMatcher struct {
network *v2net.NetworkList
}
func NewNetworkMatcher(network *v2net.NetworkList) *NetworkMatcher {
return &NetworkMatcher{
network: network,
}
}
func (this *NetworkMatcher) Apply(dest v2net.Destination) bool {
return this.network.HasNetwork(dest.Network())
}