Chore: embed the RuleExtra into Base

This commit is contained in:
yaling888
2022-03-13 01:21:23 +08:00
parent 8fbf93ccc8
commit 46b9a1092d
47 changed files with 1995 additions and 471 deletions

View File

@ -14,6 +14,22 @@ var (
noResolve = "no-resolve"
)
type Base struct {
ruleExtra *C.RuleExtra
}
func (b *Base) RuleExtra() *C.RuleExtra {
return b.ruleExtra
}
func (b *Base) SetRuleExtra(re *C.RuleExtra) {
b.ruleExtra = re
}
func (b *Base) ShouldFindProcess() bool {
return false
}
func HasNoResolve(params []string) bool {
for _, p := range params {
if p == noResolve {

View File

@ -7,9 +7,9 @@ import (
)
type Domain struct {
domain string
adapter string
ruleExtra *C.RuleExtra
*Base
domain string
adapter string
}
func (d *Domain) RuleType() C.RuleType {
@ -35,14 +35,12 @@ func (d *Domain) ShouldResolveIP() bool {
return false
}
func (d *Domain) RuleExtra() *C.RuleExtra {
return d.ruleExtra
}
func NewDomain(domain string, adapter string, ruleExtra *C.RuleExtra) *Domain {
func NewDomain(domain string, adapter string) *Domain {
return &Domain{
domain: strings.ToLower(domain),
adapter: adapter,
ruleExtra: ruleExtra,
Base: &Base{},
domain: strings.ToLower(domain),
adapter: adapter,
}
}
var _ C.Rule = (*Domain)(nil)

View File

@ -7,9 +7,9 @@ import (
)
type DomainKeyword struct {
keyword string
adapter string
ruleExtra *C.RuleExtra
*Base
keyword string
adapter string
}
func (dk *DomainKeyword) RuleType() C.RuleType {
@ -36,14 +36,12 @@ func (dk *DomainKeyword) ShouldResolveIP() bool {
return false
}
func (dk *DomainKeyword) RuleExtra() *C.RuleExtra {
return dk.ruleExtra
}
func NewDomainKeyword(keyword string, adapter string, ruleExtra *C.RuleExtra) *DomainKeyword {
func NewDomainKeyword(keyword string, adapter string) *DomainKeyword {
return &DomainKeyword{
keyword: strings.ToLower(keyword),
adapter: adapter,
ruleExtra: ruleExtra,
Base: &Base{},
keyword: strings.ToLower(keyword),
adapter: adapter,
}
}
var _ C.Rule = (*DomainKeyword)(nil)

View File

@ -7,9 +7,9 @@ import (
)
type DomainSuffix struct {
suffix string
adapter string
ruleExtra *C.RuleExtra
*Base
suffix string
adapter string
}
func (ds *DomainSuffix) RuleType() C.RuleType {
@ -36,14 +36,12 @@ func (ds *DomainSuffix) ShouldResolveIP() bool {
return false
}
func (ds *DomainSuffix) RuleExtra() *C.RuleExtra {
return ds.ruleExtra
}
func NewDomainSuffix(suffix string, adapter string, ruleExtra *C.RuleExtra) *DomainSuffix {
func NewDomainSuffix(suffix string, adapter string) *DomainSuffix {
return &DomainSuffix{
suffix: strings.ToLower(suffix),
adapter: adapter,
ruleExtra: ruleExtra,
Base: &Base{},
suffix: strings.ToLower(suffix),
adapter: adapter,
}
}
var _ C.Rule = (*DomainSuffix)(nil)

View File

@ -5,8 +5,8 @@ import (
)
type Match struct {
adapter string
ruleExtra *C.RuleExtra
*Base
adapter string
}
func (f *Match) RuleType() C.RuleType {
@ -29,16 +29,11 @@ func (f *Match) ShouldResolveIP() bool {
return false
}
func (f *Match) RuleExtra() *C.RuleExtra {
return f.ruleExtra
func NewMatch(adapter string) *Match {
return &Match{
Base: &Base{},
adapter: adapter,
}
}
func NewMatch(adapter string, ruleExtra *C.RuleExtra) *Match {
if ruleExtra.SourceIPs == nil {
ruleExtra = nil
}
return &Match{
adapter: adapter,
ruleExtra: ruleExtra,
}
}
var _ C.Rule = (*Match)(nil)

View File

@ -8,10 +8,10 @@ import (
)
type GEOIP struct {
*Base
country string
adapter string
noResolveIP bool
ruleExtra *C.RuleExtra
}
func (g *GEOIP) RuleType() C.RuleType {
@ -48,21 +48,19 @@ func (g *GEOIP) ShouldResolveIP() bool {
return !g.noResolveIP
}
func (g *GEOIP) RuleExtra() *C.RuleExtra {
return g.ruleExtra
}
func (g *GEOIP) GetCountry() string {
return g.country
}
func NewGEOIP(country string, adapter string, noResolveIP bool, ruleExtra *C.RuleExtra) (*GEOIP, error) {
func NewGEOIP(country string, adapter string, noResolveIP bool) *GEOIP {
geoip := &GEOIP{
Base: &Base{},
country: country,
adapter: adapter,
noResolveIP: noResolveIP,
ruleExtra: ruleExtra,
}
return geoip, nil
return geoip
}
var _ C.Rule = (*GEOIP)(nil)

View File

@ -11,10 +11,10 @@ import (
)
type GEOSITE struct {
country string
adapter string
ruleExtra *C.RuleExtra
matcher *router.DomainMatcher
*Base
country string
adapter string
matcher *router.DomainMatcher
}
func (gs *GEOSITE) RuleType() C.RuleType {
@ -42,15 +42,11 @@ func (gs *GEOSITE) ShouldResolveIP() bool {
return false
}
func (gs *GEOSITE) RuleExtra() *C.RuleExtra {
return gs.ruleExtra
}
func (gs *GEOSITE) GetDomainMatcher() *router.DomainMatcher {
return gs.matcher
}
func NewGEOSITE(country string, adapter string, ruleExtra *C.RuleExtra) (*GEOSITE, error) {
func NewGEOSITE(country string, adapter string) (*GEOSITE, error) {
matcher, recordsCount, err := geodata.LoadGeoSiteMatcher(country)
if err != nil {
return nil, fmt.Errorf("load GeoSite data error, %s", err.Error())
@ -59,11 +55,13 @@ func NewGEOSITE(country string, adapter string, ruleExtra *C.RuleExtra) (*GEOSIT
log.Infoln("Start initial GeoSite rule %s => %s, records: %d", country, adapter, recordsCount)
geoSite := &GEOSITE{
country: country,
adapter: adapter,
ruleExtra: ruleExtra,
matcher: matcher,
Base: &Base{},
country: country,
adapter: adapter,
matcher: matcher,
}
return geoSite, nil
}
var _ C.Rule = (*GEOSITE)(nil)

View File

@ -21,9 +21,9 @@ func WithIPCIDRNoResolve(noResolve bool) IPCIDROption {
}
type IPCIDR struct {
*Base
ipnet *net.IPNet
adapter string
ruleExtra *C.RuleExtra
isSourceIP bool
noResolveIP bool
}
@ -55,20 +55,16 @@ func (i *IPCIDR) ShouldResolveIP() bool {
return !i.noResolveIP
}
func (i *IPCIDR) RuleExtra() *C.RuleExtra {
return i.ruleExtra
}
func NewIPCIDR(s string, adapter string, ruleExtra *C.RuleExtra, opts ...IPCIDROption) (*IPCIDR, error) {
func NewIPCIDR(s string, adapter string, opts ...IPCIDROption) (*IPCIDR, error) {
_, ipnet, err := net.ParseCIDR(s)
if err != nil {
return nil, errPayload
}
ipcidr := &IPCIDR{
ipnet: ipnet,
adapter: adapter,
ruleExtra: ruleExtra,
Base: &Base{},
ipnet: ipnet,
adapter: adapter,
}
for _, o := range opts {
@ -77,3 +73,5 @@ func NewIPCIDR(s string, adapter string, ruleExtra *C.RuleExtra, opts ...IPCIDRO
return ipcidr, nil
}
var _ C.Rule = (*IPCIDR)(nil)

View File

@ -12,40 +12,48 @@ func ParseRule(tp, payload, target string, params []string) (C.Rule, error) {
parsed C.Rule
)
switch tp {
case "DOMAIN":
parsed = NewDomain(payload, target)
case "DOMAIN-SUFFIX":
parsed = NewDomainSuffix(payload, target)
case "DOMAIN-KEYWORD":
parsed = NewDomainKeyword(payload, target)
case "GEOSITE":
parsed, parseErr = NewGEOSITE(payload, target)
case "GEOIP":
noResolve := HasNoResolve(params)
parsed = NewGEOIP(payload, target, noResolve)
case "IP-CIDR", "IP-CIDR6":
noResolve := HasNoResolve(params)
parsed, parseErr = NewIPCIDR(payload, target, WithIPCIDRNoResolve(noResolve))
case "SRC-IP-CIDR":
parsed, parseErr = NewIPCIDR(payload, target, WithIPCIDRSourceIP(true), WithIPCIDRNoResolve(true))
case "SRC-PORT":
parsed, parseErr = NewPort(payload, target, true)
case "DST-PORT":
parsed, parseErr = NewPort(payload, target, false)
case "PROCESS-NAME":
parsed, parseErr = NewProcess(payload, target, true)
case "PROCESS-PATH":
parsed, parseErr = NewProcess(payload, target, false)
case "MATCH":
parsed = NewMatch(target)
default:
parseErr = fmt.Errorf("unsupported rule type %s", tp)
}
if parseErr != nil {
return nil, parseErr
}
ruleExtra := &C.RuleExtra{
Network: findNetwork(params),
SourceIPs: findSourceIPs(params),
ProcessNames: findProcessName(params),
}
switch tp {
case "DOMAIN":
parsed = NewDomain(payload, target, ruleExtra)
case "DOMAIN-SUFFIX":
parsed = NewDomainSuffix(payload, target, ruleExtra)
case "DOMAIN-KEYWORD":
parsed = NewDomainKeyword(payload, target, ruleExtra)
case "GEOSITE":
parsed, parseErr = NewGEOSITE(payload, target, ruleExtra)
case "GEOIP":
noResolve := HasNoResolve(params)
parsed, parseErr = NewGEOIP(payload, target, noResolve, ruleExtra)
case "IP-CIDR", "IP-CIDR6":
noResolve := HasNoResolve(params)
parsed, parseErr = NewIPCIDR(payload, target, ruleExtra, WithIPCIDRNoResolve(noResolve))
case "SRC-IP-CIDR":
parsed, parseErr = NewIPCIDR(payload, target, ruleExtra, WithIPCIDRSourceIP(true), WithIPCIDRNoResolve(true))
case "SRC-PORT":
parsed, parseErr = NewPort(payload, target, true, ruleExtra)
case "DST-PORT":
parsed, parseErr = NewPort(payload, target, false, ruleExtra)
case "PROCESS-NAME":
parsed, parseErr = NewProcess(payload, target, ruleExtra)
case "MATCH":
parsed = NewMatch(target, ruleExtra)
default:
parseErr = fmt.Errorf("unsupported rule type %s", tp)
}
parsed.SetRuleExtra(ruleExtra)
return parsed, parseErr
return parsed, nil
}

View File

@ -14,11 +14,11 @@ type portReal struct {
}
type Port struct {
adapter string
port string
isSource bool
portList []portReal
ruleExtra *C.RuleExtra
*Base
adapter string
port string
isSource bool
portList []portReal
}
func (p *Port) RuleType() C.RuleType {
@ -47,10 +47,6 @@ func (p *Port) ShouldResolveIP() bool {
return false
}
func (p *Port) RuleExtra() *C.RuleExtra {
return p.ruleExtra
}
func (p *Port) matchPortReal(portRef string) bool {
port, _ := strconv.Atoi(portRef)
var rs bool
@ -67,7 +63,7 @@ func (p *Port) matchPortReal(portRef string) bool {
return false
}
func NewPort(port string, adapter string, isSource bool, ruleExtra *C.RuleExtra) (*Port, error) {
func NewPort(port string, adapter string, isSource bool) (*Port, error) {
ports := strings.Split(port, "/")
if len(ports) > 28 {
return nil, fmt.Errorf("%s, too many ports to use, maximum support 28 ports", errPayload.Error())
@ -85,24 +81,25 @@ func NewPort(port string, adapter string, isSource bool, ruleExtra *C.RuleExtra)
return nil, errPayload
}
portStart, err := strconv.Atoi(strings.Trim(subPorts[0], "[ ]"))
if err != nil || portStart < 0 || portStart > 65535 {
portStart, err := strconv.ParseUint(strings.Trim(subPorts[0], "[ ]"), 10, 16)
if err != nil {
return nil, errPayload
}
if subPortsLen == 1 {
portList = append(portList, portReal{portStart, -1})
} else if subPortsLen == 2 {
portEnd, err1 := strconv.Atoi(strings.Trim(subPorts[1], "[ ]"))
if err1 != nil || portEnd < 0 || portEnd > 65535 {
switch subPortsLen {
case 1:
portList = append(portList, portReal{int(portStart), -1})
case 2:
portEnd, err := strconv.ParseUint(strings.Trim(subPorts[1], "[ ]"), 10, 16)
if err != nil {
return nil, errPayload
}
shouldReverse := portStart > portEnd
if shouldReverse {
portList = append(portList, portReal{portEnd, portStart})
portList = append(portList, portReal{int(portEnd), int(portStart)})
} else {
portList = append(portList, portReal{portStart, portEnd})
portList = append(portList, portReal{int(portStart), int(portEnd)})
}
}
}
@ -112,10 +109,12 @@ func NewPort(port string, adapter string, isSource bool, ruleExtra *C.RuleExtra)
}
return &Port{
adapter: adapter,
port: port,
isSource: isSource,
portList: portList,
ruleExtra: ruleExtra,
Base: &Base{},
adapter: adapter,
port: port,
isSource: isSource,
portList: portList,
}, nil
}
var _ C.Rule = (*Port)(nil)

View File

@ -1,27 +1,16 @@
package rules
import (
"fmt"
"net"
"strconv"
"strings"
"github.com/Dreamacro/clash/common/cache"
"github.com/Dreamacro/clash/component/process"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log"
)
var (
processCache = cache.NewLRUCache(cache.WithAge(2), cache.WithSize(64))
localIPs = getLocalIPs()
)
type Process struct {
adapter string
process string
ruleExtra *C.RuleExtra
*Base
adapter string
process string
nameOnly bool
}
func (ps *Process) RuleType() C.RuleType {
@ -29,37 +18,11 @@ func (ps *Process) RuleType() C.RuleType {
}
func (ps *Process) Match(metadata *C.Metadata) bool {
if metadata.Process != "" {
if ps.nameOnly {
return strings.EqualFold(metadata.Process, ps.process)
}
// ignore source IP not on local machine
if !isLocalIP(metadata.SrcIP) {
return false
}
key := fmt.Sprintf("%s:%s:%s", metadata.NetWork.String(), metadata.SrcIP.String(), metadata.SrcPort)
cached, hit := processCache.Get(key)
if !hit {
srcPort, err := strconv.Atoi(metadata.SrcPort)
if err != nil {
processCache.Set(key, "")
return false
}
name, err := process.FindProcessName(metadata.NetWork.String(), metadata.SrcIP, srcPort)
if err != nil {
log.Debugln("[Rule] find process name %s error: %s", C.Process.String(), err.Error())
}
processCache.Set(key, name)
cached = name
}
metadata.Process = cached.(string)
return strings.EqualFold(metadata.Process, ps.process)
return strings.EqualFold(metadata.ProcessPath, ps.process)
}
func (ps *Process) Adapter() string {
@ -74,46 +37,17 @@ func (ps *Process) ShouldResolveIP() bool {
return false
}
func (ps *Process) RuleExtra() *C.RuleExtra {
return ps.ruleExtra
func (ps *Process) ShouldFindProcess() bool {
return true
}
func NewProcess(process string, adapter string, ruleExtra *C.RuleExtra) (*Process, error) {
func NewProcess(process string, adapter string, nameOnly bool) (*Process, error) {
return &Process{
adapter: adapter,
process: process,
ruleExtra: ruleExtra,
Base: &Base{},
adapter: adapter,
process: process,
nameOnly: nameOnly,
}, nil
}
func getLocalIPs() []net.IP {
ips := []net.IP{net.IPv4(198, 18, 0, 1), net.IPv4zero, net.IPv6zero}
netInterfaces, err := net.Interfaces()
if err != nil {
return ips
}
for i := 0; i < len(netInterfaces); i++ {
if (netInterfaces[i].Flags & net.FlagUp) != 0 {
adds, _ := netInterfaces[i].Addrs()
for _, address := range adds {
if ipNet, ok := address.(*net.IPNet); ok {
ips = append(ips, ipNet.IP)
}
}
}
}
return ips
}
func isLocalIP(srcIP net.IP) bool {
for _, ip := range localIPs {
if ip.Equal(srcIP) {
return true
}
}
return false
}
var _ C.Rule = (*Process)(nil)