simplify router

pull/314/head
Darien Raymond 2016-10-12 16:11:13 +02:00
parent 63f3108737
commit 22ef12a456
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
28 changed files with 8021 additions and 8138 deletions

View File

@ -13,7 +13,7 @@ import (
type DefaultDispatcher struct { type DefaultDispatcher struct {
ohm proxyman.OutboundHandlerManager ohm proxyman.OutboundHandlerManager
router router.Router router *router.Router
} }
func NewDefaultDispatcher(space app.Space) *DefaultDispatcher { func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
@ -33,7 +33,7 @@ func (this *DefaultDispatcher) Initialize(space app.Space) error {
this.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager) this.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
if space.HasApp(router.APP_ID) { if space.HasApp(router.APP_ID) {
this.router = space.GetApp(router.APP_ID).(router.Router) this.router = space.GetApp(router.APP_ID).(*router.Router)
} }
return nil return nil

View File

@ -1,3 +1,3 @@
package rules package router
//go:generate go run chinaip_gen.go //go:generate go run chinaip_gen.go

View File

@ -67,7 +67,7 @@ func main() {
} }
defer file.Close() defer file.Close()
fmt.Fprintln(file, "package rules") fmt.Fprintln(file, "package router")
fmt.Fprintln(file, "var chinaIPs []*IP") fmt.Fprintln(file, "var chinaIPs []*IP")

7634
app/router/chinaip_init.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// +build json // +build json
package rules package router
import ( import (
"encoding/json" "encoding/json"

View File

@ -1,12 +1,12 @@
// +build json // +build json
package rules_test package router_test
import ( import (
"net" "net"
"testing" "testing"
. "v2ray.com/core/app/router/rules" . "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
) )

View File

@ -1,4 +1,4 @@
package rules package router
const ( const (
anySubDomain = "^(.*\\.)?" anySubDomain = "^(.*\\.)?"

View File

@ -1,6 +1,6 @@
// +build json // +build json
package rules package router
import ( import (
"encoding/json" "encoding/json"

View File

@ -1,11 +1,11 @@
// +build json // +build json
package rules_test package router_test
import ( import (
"testing" "testing"
. "v2ray.com/core/app/router/rules" . "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
) )

View File

@ -1,4 +1,4 @@
package rules package router
import ( import (
"net" "net"

View File

@ -1,6 +1,85 @@
package router package router
type Config struct { import (
Strategy string "errors"
Settings interface{} "net"
v2net "v2ray.com/core/common/net"
)
type Rule struct {
Tag string
Condition Condition
}
func (this *Rule) Apply(dest v2net.Destination) bool {
return this.Condition.Apply(dest)
}
func (this *RoutingRule) BuildCondition() (Condition, error) {
conds := NewConditionChan()
if len(this.Domain) > 0 {
anyCond := NewAnyCondition()
for _, domain := range this.Domain {
if domain.Type == Domain_Plain {
anyCond.Add(NewPlainDomainMatcher(domain.Value))
} else {
matcher, err := NewRegexpDomainMatcher(domain.Value)
if err != nil {
return nil, err
}
anyCond.Add(matcher)
}
}
conds.Add(anyCond)
}
if len(this.Ip) > 0 {
ipv4Net := make(map[uint32]byte)
ipv6Cond := NewAnyCondition()
hasIpv6 := false
for _, ip := range this.Ip {
switch len(ip.Ip) {
case net.IPv4len:
k := (uint32(ip.Ip[0]) << 24) + (uint32(ip.Ip[1]) << 16) + (uint32(ip.Ip[2]) << 8) + uint32(ip.Ip[3])
ipv4Net[k] = byte(32 - ip.UnmatchingBits)
case net.IPv6len:
hasIpv6 = true
matcher, err := NewCIDRMatcher(ip.Ip, uint32(32)-ip.UnmatchingBits)
if err != nil {
return nil, err
}
ipv6Cond.Add(matcher)
default:
return nil, errors.New("Router: Invalid IP length.")
}
}
if len(ipv4Net) > 0 && hasIpv6 {
cond := NewAnyCondition()
cond.Add(NewIPv4Matcher(v2net.NewIPNetInitialValue(ipv4Net)))
cond.Add(ipv6Cond)
conds.Add(cond)
} else if len(ipv4Net) > 0 {
conds.Add(NewIPv4Matcher(v2net.NewIPNetInitialValue(ipv4Net)))
} else if hasIpv6 {
conds.Add(ipv6Cond)
}
}
if this.PortRange != nil {
conds.Add(NewPortMatcher(*this.PortRange))
}
if this.NetworkList != nil {
conds.Add(NewNetworkMatcher(this.NetworkList))
}
if conds.Len() == 0 {
return nil, errors.New("Router: This rule has no effective fields.")
}
return conds, nil
} }

View File

@ -1,12 +1,12 @@
// Code generated by protoc-gen-go. // Code generated by protoc-gen-go.
// source: v2ray.com/core/app/router/rules/config.proto // source: v2ray.com/core/app/router/config.proto
// DO NOT EDIT! // DO NOT EDIT!
/* /*
Package rules is a generated protocol buffer package. Package router is a generated protocol buffer package.
It is generated from these files: It is generated from these files:
v2ray.com/core/app/router/rules/config.proto v2ray.com/core/app/router/config.proto
It has these top-level messages: It has these top-level messages:
Domain Domain
@ -14,7 +14,7 @@ It has these top-level messages:
RoutingRule RoutingRule
Config Config
*/ */
package rules package router
import proto "github.com/golang/protobuf/proto" import proto "github.com/golang/protobuf/proto"
import fmt "fmt" import fmt "fmt"
@ -84,7 +84,7 @@ func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) { return fileDescr
// Domain for routing decision. // Domain for routing decision.
type Domain struct { type Domain struct {
// Domain matching type. // Domain matching type.
Type Domain_Type `protobuf:"varint,1,opt,name=type,enum=v2ray.core.app.router.rules.Domain_Type" json:"type,omitempty"` Type Domain_Type `protobuf:"varint,1,opt,name=type,enum=v2ray.core.app.router.Domain_Type" json:"type,omitempty"`
// Domain value. // Domain value.
Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
} }
@ -151,7 +151,7 @@ func (m *RoutingRule) GetNetworkList() *v2ray_core_common_net1.NetworkList {
} }
type Config struct { type Config struct {
DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,enum=v2ray.core.app.router.rules.Config_DomainStrategy" json:"domain_strategy,omitempty"` DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,enum=v2ray.core.app.router.Config_DomainStrategy" json:"domain_strategy,omitempty"`
Rule []*RoutingRule `protobuf:"bytes,2,rep,name=rule" json:"rule,omitempty"` Rule []*RoutingRule `protobuf:"bytes,2,rep,name=rule" json:"rule,omitempty"`
} }
@ -168,46 +168,45 @@ func (m *Config) GetRule() []*RoutingRule {
} }
func init() { func init() {
proto.RegisterType((*Domain)(nil), "v2ray.core.app.router.rules.Domain") proto.RegisterType((*Domain)(nil), "v2ray.core.app.router.Domain")
proto.RegisterType((*IP)(nil), "v2ray.core.app.router.rules.IP") proto.RegisterType((*IP)(nil), "v2ray.core.app.router.IP")
proto.RegisterType((*RoutingRule)(nil), "v2ray.core.app.router.rules.RoutingRule") proto.RegisterType((*RoutingRule)(nil), "v2ray.core.app.router.RoutingRule")
proto.RegisterType((*Config)(nil), "v2ray.core.app.router.rules.Config") proto.RegisterType((*Config)(nil), "v2ray.core.app.router.Config")
proto.RegisterEnum("v2ray.core.app.router.rules.Domain_Type", Domain_Type_name, Domain_Type_value) proto.RegisterEnum("v2ray.core.app.router.Domain_Type", Domain_Type_name, Domain_Type_value)
proto.RegisterEnum("v2ray.core.app.router.rules.Config_DomainStrategy", Config_DomainStrategy_name, Config_DomainStrategy_value) proto.RegisterEnum("v2ray.core.app.router.Config_DomainStrategy", Config_DomainStrategy_name, Config_DomainStrategy_value)
} }
func init() { proto.RegisterFile("v2ray.com/core/app/router/rules/config.proto", fileDescriptor0) } func init() { proto.RegisterFile("v2ray.com/core/app/router/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 472 bytes of a gzipped FileDescriptorProto // 462 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x52, 0x4f, 0x8b, 0xd5, 0x3e, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x92, 0x5f, 0x6b, 0xd5, 0x30,
0x14, 0xfd, 0xb5, 0xef, 0x0f, 0xbf, 0x77, 0xdf, 0xb3, 0x53, 0x82, 0x8b, 0x32, 0x0a, 0x53, 0xaa, 0x18, 0xc6, 0x6d, 0x77, 0x4e, 0xf1, 0xbc, 0x3d, 0x76, 0x25, 0x28, 0x74, 0x43, 0xa1, 0x14, 0x71,
0x30, 0x5d, 0x48, 0x0a, 0x15, 0x71, 0xa1, 0x22, 0x3e, 0x75, 0x51, 0xd0, 0xa1, 0x44, 0xdd, 0xe8, 0x47, 0x90, 0x54, 0x8e, 0xa8, 0x57, 0x22, 0x1e, 0xf5, 0xa2, 0xa0, 0xa3, 0x44, 0x77, 0xe3, 0xcd,
0xe2, 0x91, 0xe9, 0x64, 0x6a, 0xb0, 0x4d, 0x42, 0x9a, 0x8e, 0x3e, 0xbf, 0x87, 0xdf, 0xce, 0x0f, 0x21, 0xeb, 0xb2, 0x1a, 0x6c, 0x93, 0x90, 0xa6, 0xd3, 0xf3, 0x11, 0xfc, 0x76, 0x7e, 0x24, 0x69,
0x23, 0x4d, 0x3a, 0xcc, 0x8c, 0x30, 0xc5, 0xdd, 0xbd, 0xe1, 0x9c, 0x93, 0x7b, 0xef, 0x39, 0xf0, 0xd2, 0xb1, 0x4d, 0x56, 0xef, 0xf2, 0x86, 0xdf, 0xf3, 0xfe, 0x7d, 0xe0, 0xc9, 0xc5, 0x5a, 0xd3,
0xe8, 0x22, 0xd7, 0x74, 0x8f, 0x2b, 0xd9, 0x66, 0x95, 0xd4, 0x2c, 0xa3, 0x4a, 0x65, 0x5a, 0xf6, 0x1d, 0xae, 0x64, 0x9b, 0x57, 0x52, 0xb3, 0x9c, 0x2a, 0x95, 0x6b, 0xd9, 0x1b, 0xa6, 0xf3, 0x4a,
0x86, 0xe9, 0x4c, 0xf7, 0x0d, 0xeb, 0xb2, 0x4a, 0x8a, 0x73, 0x5e, 0x63, 0xa5, 0xa5, 0x91, 0xe8, 0x8a, 0x73, 0x5e, 0x63, 0xa5, 0xa5, 0x91, 0xe8, 0xc1, 0x25, 0xa7, 0x19, 0xa6, 0x4a, 0x61, 0xc7,
0xde, 0x25, 0x5a, 0x33, 0x4c, 0x95, 0xc2, 0x0e, 0x89, 0x2d, 0xf2, 0xf0, 0xe1, 0x5f, 0x52, 0x95, 0x1c, 0x3e, 0xfe, 0x47, 0x5e, 0xc9, 0xb6, 0x95, 0x22, 0x17, 0xcc, 0xe4, 0x4a, 0x6a, 0xe3, 0xc4,
0x6c, 0x5b, 0x29, 0x32, 0xc1, 0x4c, 0xa6, 0xa4, 0x36, 0x4e, 0xe2, 0xf0, 0xf8, 0x76, 0x94, 0x60, 0x87, 0x47, 0xd3, 0x94, 0x60, 0xe6, 0xa7, 0xd4, 0x3f, 0x1c, 0x98, 0x19, 0x08, 0x3e, 0xc8, 0x96,
0xe6, 0xbb, 0xd4, 0xdf, 0x1c, 0x30, 0xf9, 0x09, 0xcb, 0x37, 0xb2, 0xa5, 0x5c, 0xa0, 0xe7, 0x30, 0x72, 0x81, 0x5e, 0xc1, 0xcc, 0xec, 0x14, 0x4b, 0xbc, 0xd4, 0x5b, 0x45, 0xeb, 0x0c, 0xdf, 0x5a,
0x37, 0x7b, 0xc5, 0x22, 0x2f, 0xf6, 0xd2, 0x20, 0x4f, 0xf1, 0xc4, 0x10, 0xd8, 0x51, 0xf0, 0xc7, 0x1e, 0x3b, 0x18, 0x7f, 0xdd, 0x29, 0x46, 0x2c, 0x8f, 0xee, 0xc3, 0xfc, 0x82, 0x36, 0x3d, 0x4b,
0xbd, 0x62, 0xc4, 0xb2, 0xd0, 0x5d, 0x58, 0x5c, 0xd0, 0xa6, 0x67, 0x91, 0x1f, 0x7b, 0xe9, 0x8a, 0xfc, 0xd4, 0x5b, 0x2d, 0x88, 0x0b, 0xb2, 0x87, 0x30, 0x1b, 0x18, 0xb4, 0x80, 0x79, 0xd9, 0x50,
0xb8, 0x26, 0xb9, 0x0f, 0xf3, 0x01, 0x83, 0x56, 0xb0, 0x28, 0x1b, 0xca, 0x45, 0xf8, 0xdf, 0x50, 0x2e, 0xe2, 0x3b, 0xc3, 0x93, 0xb0, 0x9a, 0xfd, 0x8a, 0xbd, 0xec, 0x0d, 0xf8, 0x45, 0x89, 0x22,
0x12, 0x56, 0xb3, 0x1f, 0xa1, 0x97, 0xbc, 0x00, 0xbf, 0x28, 0x51, 0x00, 0x3e, 0x57, 0xf6, 0xd7, 0xf0, 0xb9, 0xb2, 0xf5, 0x96, 0xc4, 0xe7, 0x0a, 0x1d, 0xc1, 0x7e, 0x2f, 0x5a, 0x6a, 0xaa, 0xef,
0x0d, 0xf1, 0xb9, 0x42, 0xc7, 0x70, 0xd0, 0x8b, 0x96, 0x9a, 0xea, 0x2b, 0x17, 0xf5, 0xee, 0x94, 0x5c, 0xd4, 0xdb, 0x53, 0x6e, 0x3a, 0x9b, 0xf3, 0x1e, 0x89, 0xae, 0xbe, 0x37, 0xdc, 0x74, 0xd9,
0x9b, 0xce, 0x6a, 0xde, 0x21, 0xc1, 0xd5, 0xf3, 0x96, 0x9b, 0x2e, 0xf9, 0xe5, 0xc3, 0x9a, 0xc8, 0x6f, 0x1f, 0x42, 0x22, 0x7b, 0xc3, 0x45, 0x4d, 0xfa, 0x86, 0xa1, 0x18, 0xf6, 0x0c, 0xad, 0x6d,
0xde, 0x70, 0x51, 0x93, 0xbe, 0x61, 0x28, 0x84, 0x99, 0xa1, 0xb5, 0x55, 0x5a, 0x91, 0xa1, 0x44, 0xa6, 0x05, 0x19, 0x9e, 0xe8, 0x25, 0x04, 0x67, 0xb6, 0xd3, 0xc4, 0x4f, 0xf7, 0x56, 0xe1, 0xfa,
0xcf, 0x60, 0x79, 0x66, 0x27, 0x8d, 0xfc, 0x78, 0x96, 0xae, 0xf3, 0x07, 0xff, 0xb0, 0x14, 0x19, 0xd1, 0x7f, 0xc7, 0x21, 0x23, 0x8c, 0x9e, 0xda, 0x8e, 0xf6, 0xac, 0xe4, 0x60, 0x42, 0x52, 0x94,
0x29, 0x28, 0xb3, 0x73, 0xcd, 0x2c, 0xf1, 0x68, 0x92, 0x58, 0x94, 0x76, 0xf0, 0x97, 0x00, 0x83, 0xb6, 0xd9, 0xb7, 0x00, 0xc3, 0xbe, 0xb7, 0x9a, 0x8a, 0x9a, 0x25, 0xb3, 0xd4, 0x5b, 0x85, 0xeb,
0x03, 0x3b, 0x4d, 0x45, 0xcd, 0xa2, 0x79, 0xec, 0xa5, 0xeb, 0x3c, 0xbe, 0x4e, 0x74, 0x26, 0x60, 0xf4, 0xba, 0xc4, 0xad, 0x1c, 0x0b, 0x66, 0x70, 0x29, 0xb5, 0x21, 0x03, 0x47, 0x16, 0xea, 0xf2,
0xc1, 0x0c, 0x2e, 0xa5, 0x36, 0x64, 0xc0, 0x91, 0x95, 0xba, 0x2c, 0xd1, 0x5b, 0xd8, 0x8c, 0xe6, 0x89, 0x3e, 0xc2, 0x72, 0x3c, 0xc5, 0xb6, 0xe1, 0x9d, 0x49, 0xe6, 0x36, 0x45, 0x36, 0x91, 0xe2,
0xec, 0x1a, 0xde, 0x99, 0x68, 0x61, 0x25, 0x92, 0x5b, 0x24, 0x4e, 0x1c, 0xf4, 0x1d, 0xef, 0x0c, 0xd8, 0xa1, 0x9f, 0x78, 0x67, 0x48, 0x28, 0xae, 0x82, 0xec, 0x8f, 0x07, 0xc1, 0x7b, 0xeb, 0x1b,
0x59, 0x8b, 0xab, 0x26, 0xf9, 0xed, 0xc1, 0xf2, 0xb5, 0xcd, 0x13, 0xfa, 0x02, 0x07, 0x6e, 0x9b, 0x74, 0x02, 0xfb, 0x6e, 0x8e, 0x6d, 0x67, 0x34, 0x35, 0xac, 0xde, 0x8d, 0xc7, 0x7c, 0x36, 0x31,
0x5d, 0x67, 0x34, 0x35, 0xac, 0xde, 0x8f, 0xf6, 0xe6, 0x93, 0x0b, 0x39, 0xf6, 0x78, 0x90, 0x0f, 0x8a, 0xd3, 0x8d, 0x4b, 0xf8, 0x32, 0x6a, 0x48, 0x74, 0x76, 0x23, 0x1e, 0x8c, 0xa1, 0xfb, 0x86,
0x23, 0x93, 0x04, 0x67, 0x37, 0xfa, 0x21, 0x30, 0x03, 0x7c, 0xbc, 0xed, 0x74, 0x60, 0xae, 0xf9, 0x8d, 0x9b, 0x9c, 0x32, 0xc6, 0xb5, 0x7b, 0x10, 0xcb, 0x67, 0xaf, 0x21, 0xba, 0x99, 0x19, 0xdd,
0x44, 0x2c, 0x2b, 0x79, 0x0a, 0xc1, 0x4d, 0x7d, 0xf4, 0x3f, 0xcc, 0x5f, 0x75, 0x45, 0xe7, 0x32, 0x85, 0xd9, 0xbb, 0xae, 0xe8, 0x9c, 0x17, 0x4e, 0x3a, 0x56, 0xa8, 0xd8, 0x43, 0x31, 0x2c, 0x0b,
0xf2, 0xa9, 0x63, 0x85, 0x0a, 0x3d, 0x14, 0xc2, 0xa6, 0x50, 0xc5, 0xf9, 0x89, 0x14, 0xef, 0x07, 0x55, 0x9c, 0x1f, 0x4b, 0xf1, 0x79, 0xb8, 0x71, 0xec, 0x6f, 0x9e, 0xc3, 0x41, 0x25, 0xdb, 0xdb,
0xef, 0x43, 0x7f, 0xfb, 0x04, 0x8e, 0x2a, 0xd9, 0x4e, 0xfd, 0xb6, 0x5d, 0xbb, 0x05, 0xca, 0x21, 0xeb, 0x6c, 0x42, 0xd7, 0x74, 0x39, 0xb8, 0xf7, 0x5b, 0xe0, 0x3e, 0x4f, 0x03, 0x6b, 0xe6, 0x17,
0xe1, 0x9f, 0x17, 0xf6, 0xed, 0x74, 0x69, 0xf3, 0xfe, 0xf8, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x93, 0xed, 0x34, 0x36, 0x5c, 0x03, 0x00, 0x00,
0x00, 0xa8, 0x7d, 0x12, 0x8b, 0x03, 0x00, 0x00,
} }

View File

@ -1,8 +1,8 @@
syntax = "proto3"; syntax = "proto3";
package v2ray.core.app.router.rules; package v2ray.core.app.router;
option go_package = "rules"; option go_package = "router";
option java_package = "com.v2ray.core.app.router.rules"; option java_package = "com.v2ray.core.app.router";
option java_outer_classname = "ConfigProto"; option java_outer_classname = "ConfigProto";
import "v2ray.com/core/common/net/port.proto"; import "v2ray.com/core/common/net/port.proto";

View File

@ -1,29 +0,0 @@
package router
import (
"v2ray.com/core/common"
)
type ConfigObjectCreator func([]byte) (interface{}, error)
var (
configCache map[string]ConfigObjectCreator
)
func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
// TODO: check strategy
configCache[strategy] = creator
return nil
}
func CreateRouterConfig(strategy string, data []byte) (interface{}, error) {
creator, found := configCache[strategy]
if !found {
return nil, common.ErrObjectNotFound
}
return creator(data)
}
func init() {
configCache = make(map[string]ConfigObjectCreator)
}

View File

@ -4,25 +4,165 @@ package router
import ( import (
"encoding/json" "encoding/json"
"errors"
"strconv"
"strings"
"v2ray.com/core/common/collect"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
) )
type JsonRule struct {
Type string `json:"type"`
OutboundTag string `json:"outboundTag"`
}
func parseIP(s string) *IP {
var addr, mask string
i := strings.Index(s, "/")
if i < 0 {
addr = s
} else {
addr = s[:i]
mask = s[i+1:]
}
ip := v2net.ParseAddress(addr)
if !ip.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
return nil
}
bits := uint32(32)
if len(mask) > 0 {
bits64, err := strconv.ParseUint(mask, 10, 32)
if err != nil {
return nil
}
bits = uint32(bits64)
}
if bits > 32 {
log.Warning("Router: invalid network mask: ", bits)
return nil
}
return &IP{
Ip: []byte(ip.IP()),
UnmatchingBits: 32 - bits,
}
}
func parseFieldRule(msg json.RawMessage) (*RoutingRule, error) {
type RawFieldRule struct {
JsonRule
Domain *collect.StringList `json:"domain"`
IP *collect.StringList `json:"ip"`
Port *v2net.PortRange `json:"port"`
Network *v2net.NetworkList `json:"network"`
}
rawFieldRule := new(RawFieldRule)
err := json.Unmarshal(msg, rawFieldRule)
if err != nil {
return nil, err
}
rule := new(RoutingRule)
rule.Tag = rawFieldRule.OutboundTag
if rawFieldRule.Domain != nil {
for _, domain := range *rawFieldRule.Domain {
domainRule := new(Domain)
if strings.HasPrefix(domain, "regexp:") {
domainRule.Type = Domain_Regex
domainRule.Value = domain[7:]
} else {
domainRule.Type = Domain_Plain
domainRule.Value = domain
}
rule.Domain = append(rule.Domain, domainRule)
}
}
if rawFieldRule.IP != nil {
for _, ip := range *rawFieldRule.IP {
ipRule := parseIP(ip)
if ipRule != nil {
rule.Ip = append(rule.Ip, ipRule)
}
}
}
if rawFieldRule.Port != nil {
rule.PortRange = rawFieldRule.Port
}
if rawFieldRule.Network != nil {
rule.NetworkList = rawFieldRule.Network
}
return rule, nil
}
func ParseRule(msg json.RawMessage) *RoutingRule {
rawRule := new(JsonRule)
err := json.Unmarshal(msg, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
return nil
}
if rawRule.Type == "field" {
fieldrule, err := parseFieldRule(msg)
if err != nil {
log.Error("Invalid field rule: ", err)
return nil
}
return fieldrule
}
if rawRule.Type == "chinaip" {
chinaiprule, err := parseChinaIPRule(msg)
if err != nil {
log.Error("Router: Invalid chinaip rule: ", err)
return nil
}
return chinaiprule
}
if rawRule.Type == "chinasites" {
chinasitesrule, err := parseChinaSitesRule(msg)
if err != nil {
log.Error("Invalid chinasites rule: ", err)
return nil
}
return chinasitesrule
}
log.Error("Unknown router rule type: ", rawRule.Type)
return nil
}
func (this *Config) UnmarshalJSON(data []byte) error { func (this *Config) UnmarshalJSON(data []byte) error {
type JsonRulesConfig struct {
RuleList []json.RawMessage `json:"rules"`
DomainStrategy string `json:"domainStrategy"`
}
type JsonConfig struct { type JsonConfig struct {
Strategy string `json:"strategy"` Settings *JsonRulesConfig `json:"settings"`
Settings json.RawMessage `json:"settings"`
} }
jsonConfig := new(JsonConfig) jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil { if err := json.Unmarshal(data, jsonConfig); err != nil {
return err return err
} }
settings, err := CreateRouterConfig(jsonConfig.Strategy, []byte(jsonConfig.Settings)) if jsonConfig.Settings == nil {
if err != nil { return errors.New("Router settings is not specified.")
log.Error("Router: Failed to load router settings: ", err) }
return err settings := jsonConfig.Settings
this.DomainStrategy = Config_AsIs
this.Rule = make([]*RoutingRule, len(settings.RuleList))
domainStrategy := strings.ToLower(settings.DomainStrategy)
if domainStrategy == "alwaysip" {
this.DomainStrategy = Config_UseIp
} else if domainStrategy == "ipifnonmatch" {
this.DomainStrategy = Config_IpIfNonMatch
}
for idx, rawRule := range settings.RuleList {
rule := ParseRule(rawRule)
this.Rule[idx] = rule
} }
this.Strategy = jsonConfig.Strategy
this.Settings = settings
return nil return nil
} }

View File

@ -1,11 +1,11 @@
// +build json // +build json
package rules_test package router_test
import ( import (
"testing" "testing"
. "v2ray.com/core/app/router/rules" . "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
) )

View File

@ -1,8 +1,10 @@
package router package router
import ( import (
"errors"
"v2ray.com/core/app" "v2ray.com/core/app"
"v2ray.com/core/common" "v2ray.com/core/app/dns"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
) )
@ -11,31 +13,97 @@ const (
APP_ID = app.ID(3) APP_ID = app.ID(3)
) )
type Router interface {
common.Releasable
TakeDetour(v2net.Destination) (string, error)
}
type RouterFactory interface {
Create(rawConfig interface{}, space app.Space) (Router, error)
}
var ( var (
routerCache = make(map[string]RouterFactory) ErrInvalidRule = errors.New("Invalid Rule")
ErrNoRuleApplicable = errors.New("No rule applicable")
) )
func RegisterRouter(name string, factory RouterFactory) error { type Router struct {
if _, found := routerCache[name]; found { domainStrategy Config_DomainStrategy
return common.ErrDuplicatedName rules []Rule
} cache *RoutingTable
routerCache[name] = factory dnsServer dns.Server
return nil
} }
func CreateRouter(name string, rawConfig interface{}, space app.Space) (Router, error) { func NewRouter(config *Config, space app.Space) *Router {
if factory, found := routerCache[name]; found { r := &Router{
return factory.Create(rawConfig, space) domainStrategy: config.DomainStrategy,
cache: NewRoutingTable(),
rules: make([]Rule, len(config.Rule)),
} }
log.Error("Router: not found: ", name)
return nil, common.ErrObjectNotFound space.InitializeApplication(func() error {
for idx, rule := range config.Rule {
r.rules[idx].Tag = rule.Tag
cond, err := rule.BuildCondition()
if err != nil {
return err
}
r.rules[idx].Condition = cond
}
if !space.HasApp(dns.APP_ID) {
log.Error("DNS: Router is not found in the space.")
return app.ErrMissingApplication
}
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
return nil
})
return r
}
func (this *Router) Release() {
}
// Private: Visible for testing.
func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
ips := this.dnsServer.Get(dest.Address.Domain())
if len(ips) == 0 {
return nil
}
dests := make([]v2net.Destination, len(ips))
for idx, ip := range ips {
if dest.Network == v2net.Network_TCP {
dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port)
} else {
dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port)
}
}
return dests
}
func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) {
for _, rule := range this.rules {
if rule.Apply(dest) {
return rule.Tag, nil
}
}
if this.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() {
log.Info("Router: Looking up IP for ", dest)
ipDests := this.ResolveIP(dest)
if ipDests != nil {
for _, ipDest := range ipDests {
log.Info("Router: Trying IP ", ipDest)
for _, rule := range this.rules {
if rule.Apply(ipDest) {
return rule.Tag, nil
}
}
}
}
}
return "", ErrNoRuleApplicable
}
func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
destStr := dest.String()
found, tag, err := this.cache.Get(destStr)
if !found {
tag, err := this.takeDetourWithoutCache(dest)
this.cache.Set(destStr, tag, err)
return tag, err
}
return tag, err
} }

View File

@ -1,4 +1,4 @@
package rules_test package router_test
import ( import (
"testing" "testing"
@ -8,8 +8,7 @@ import (
dispatchers "v2ray.com/core/app/dispatcher/impl" dispatchers "v2ray.com/core/app/dispatcher/impl"
"v2ray.com/core/app/dns" "v2ray.com/core/app/dns"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/router" . "v2ray.com/core/app/router"
. "v2ray.com/core/app/router/rules"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
) )
@ -33,7 +32,7 @@ func TestSimpleRouter(t *testing.T) {
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager()) space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager())
r := NewRouter(config, space) r := NewRouter(config, space)
space.BindApp(router.APP_ID, r) space.BindApp(APP_ID, r)
assert.Error(space.Initialize()).IsNil() assert.Error(space.Initialize()).IsNil()
tag, err := r.TakeDetour(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80)) tag, err := r.TakeDetour(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80))

View File

@ -1,4 +1,4 @@
package rules package router
import ( import (
"sync" "sync"

File diff suppressed because it is too large Load Diff

View File

@ -1,85 +0,0 @@
package rules
import (
"errors"
"net"
v2net "v2ray.com/core/common/net"
)
type Rule struct {
Tag string
Condition Condition
}
func (this *Rule) Apply(dest v2net.Destination) bool {
return this.Condition.Apply(dest)
}
func (this *RoutingRule) BuildCondition() (Condition, error) {
conds := NewConditionChan()
if len(this.Domain) > 0 {
anyCond := NewAnyCondition()
for _, domain := range this.Domain {
if domain.Type == Domain_Plain {
anyCond.Add(NewPlainDomainMatcher(domain.Value))
} else {
matcher, err := NewRegexpDomainMatcher(domain.Value)
if err != nil {
return nil, err
}
anyCond.Add(matcher)
}
}
conds.Add(anyCond)
}
if len(this.Ip) > 0 {
ipv4Net := make(map[uint32]byte)
ipv6Cond := NewAnyCondition()
hasIpv6 := false
for _, ip := range this.Ip {
switch len(ip.Ip) {
case net.IPv4len:
k := (uint32(ip.Ip[0]) << 24) + (uint32(ip.Ip[1]) << 16) + (uint32(ip.Ip[2]) << 8) + uint32(ip.Ip[3])
ipv4Net[k] = byte(32 - ip.UnmatchingBits)
case net.IPv6len:
hasIpv6 = true
matcher, err := NewCIDRMatcher(ip.Ip, uint32(32)-ip.UnmatchingBits)
if err != nil {
return nil, err
}
ipv6Cond.Add(matcher)
default:
return nil, errors.New("Router: Invalid IP length.")
}
}
if len(ipv4Net) > 0 && hasIpv6 {
cond := NewAnyCondition()
cond.Add(NewIPv4Matcher(v2net.NewIPNetInitialValue(ipv4Net)))
cond.Add(ipv6Cond)
conds.Add(cond)
} else if len(ipv4Net) > 0 {
conds.Add(NewIPv4Matcher(v2net.NewIPNetInitialValue(ipv4Net)))
} else if hasIpv6 {
conds.Add(ipv6Cond)
}
}
if this.PortRange != nil {
conds.Add(NewPortMatcher(*this.PortRange))
}
if this.NetworkList != nil {
conds.Add(NewNetworkMatcher(this.NetworkList))
}
if conds.Len() == 0 {
return nil, errors.New("Router: This rule has no effective fields.")
}
return conds, nil
}

View File

@ -1,165 +0,0 @@
// +build json
package rules
import (
"encoding/json"
"strconv"
"strings"
router "v2ray.com/core/app/router"
"v2ray.com/core/common/collect"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
)
type JsonRule struct {
Type string `json:"type"`
OutboundTag string `json:"outboundTag"`
}
func parseIP(s string) *IP {
var addr, mask string
i := strings.Index(s, "/")
if i < 0 {
addr = s
} else {
addr = s[:i]
mask = s[i+1:]
}
ip := v2net.ParseAddress(addr)
if !ip.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
return nil
}
bits := uint32(32)
if len(mask) > 0 {
bits64, err := strconv.ParseUint(mask, 10, 32)
if err != nil {
return nil
}
bits = uint32(bits64)
}
if bits > 32 {
log.Warning("Router: invalid network mask: ", bits)
return nil
}
return &IP{
Ip: []byte(ip.IP()),
UnmatchingBits: 32 - bits,
}
}
func parseFieldRule(msg json.RawMessage) (*RoutingRule, error) {
type RawFieldRule struct {
JsonRule
Domain *collect.StringList `json:"domain"`
IP *collect.StringList `json:"ip"`
Port *v2net.PortRange `json:"port"`
Network *v2net.NetworkList `json:"network"`
}
rawFieldRule := new(RawFieldRule)
err := json.Unmarshal(msg, rawFieldRule)
if err != nil {
return nil, err
}
rule := new(RoutingRule)
rule.Tag = rawFieldRule.OutboundTag
if rawFieldRule.Domain != nil {
for _, domain := range *rawFieldRule.Domain {
domainRule := new(Domain)
if strings.HasPrefix(domain, "regexp:") {
domainRule.Type = Domain_Regex
domainRule.Value = domain[7:]
} else {
domainRule.Type = Domain_Plain
domainRule.Value = domain
}
rule.Domain = append(rule.Domain, domainRule)
}
}
if rawFieldRule.IP != nil {
for _, ip := range *rawFieldRule.IP {
ipRule := parseIP(ip)
if ipRule != nil {
rule.Ip = append(rule.Ip, ipRule)
}
}
}
if rawFieldRule.Port != nil {
rule.PortRange = rawFieldRule.Port
}
if rawFieldRule.Network != nil {
rule.NetworkList = rawFieldRule.Network
}
return rule, nil
}
func ParseRule(msg json.RawMessage) *RoutingRule {
rawRule := new(JsonRule)
err := json.Unmarshal(msg, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
return nil
}
if rawRule.Type == "field" {
fieldrule, err := parseFieldRule(msg)
if err != nil {
log.Error("Invalid field rule: ", err)
return nil
}
return fieldrule
}
if rawRule.Type == "chinaip" {
chinaiprule, err := parseChinaIPRule(msg)
if err != nil {
log.Error("Router: Invalid chinaip rule: ", err)
return nil
}
return chinaiprule
}
if rawRule.Type == "chinasites" {
chinasitesrule, err := parseChinaSitesRule(msg)
if err != nil {
log.Error("Invalid chinasites rule: ", err)
return nil
}
return chinasitesrule
}
log.Error("Unknown router rule type: ", rawRule.Type)
return nil
}
func init() {
router.RegisterRouterConfig("rules", func(data []byte) (interface{}, error) {
type JsonConfig struct {
RuleList []json.RawMessage `json:"rules"`
DomainStrategy string `json:"domainStrategy"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return nil, err
}
config := &Config{
Rule: make([]*RoutingRule, len(jsonConfig.RuleList)),
DomainStrategy: Config_AsIs,
}
domainStrategy := strings.ToLower(jsonConfig.DomainStrategy)
if domainStrategy == "alwaysip" {
config.DomainStrategy = Config_UseIp
} else if domainStrategy == "ipifnonmatch" {
config.DomainStrategy = Config_IpIfNonMatch
}
for idx, rawRule := range jsonConfig.RuleList {
rule := ParseRule(rawRule)
config.Rule[idx] = rule
}
return config, nil
})
}

View File

@ -1,117 +0,0 @@
package rules
import (
"errors"
"v2ray.com/core/app"
"v2ray.com/core/app/dns"
"v2ray.com/core/app/router"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
)
var (
ErrInvalidRule = errors.New("Invalid Rule")
ErrNoRuleApplicable = errors.New("No rule applicable")
)
type Router struct {
domainStrategy Config_DomainStrategy
rules []Rule
cache *RoutingTable
dnsServer dns.Server
}
func NewRouter(config *Config, space app.Space) *Router {
r := &Router{
domainStrategy: config.DomainStrategy,
cache: NewRoutingTable(),
rules: make([]Rule, len(config.Rule)),
}
space.InitializeApplication(func() error {
for idx, rule := range config.Rule {
r.rules[idx].Tag = rule.Tag
cond, err := rule.BuildCondition()
if err != nil {
return err
}
r.rules[idx].Condition = cond
}
if !space.HasApp(dns.APP_ID) {
log.Error("DNS: Router is not found in the space.")
return app.ErrMissingApplication
}
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
return nil
})
return r
}
func (this *Router) Release() {
}
// Private: Visible for testing.
func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
ips := this.dnsServer.Get(dest.Address.Domain())
if len(ips) == 0 {
return nil
}
dests := make([]v2net.Destination, len(ips))
for idx, ip := range ips {
if dest.Network == v2net.Network_TCP {
dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port)
} else {
dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port)
}
}
return dests
}
func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) {
for _, rule := range this.rules {
if rule.Apply(dest) {
return rule.Tag, nil
}
}
if this.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() {
log.Info("Router: Looking up IP for ", dest)
ipDests := this.ResolveIP(dest)
if ipDests != nil {
for _, ipDest := range ipDests {
log.Info("Router: Trying IP ", ipDest)
for _, rule := range this.rules {
if rule.Apply(ipDest) {
return rule.Tag, nil
}
}
}
}
}
return "", ErrNoRuleApplicable
}
func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
destStr := dest.String()
found, tag, err := this.cache.Get(destStr)
if !found {
tag, err := this.takeDetourWithoutCache(dest)
this.cache.Set(destStr, tag, err)
return tag, err
}
return tag, err
}
type RouterFactory struct {
}
func (this *RouterFactory) Create(rawConfig interface{}, space app.Space) (router.Router, error) {
return NewRouter(rawConfig.(*Config), space), nil
}
func init() {
router.RegisterRouter("rules", &RouterFactory{})
}

View File

@ -9,7 +9,6 @@ import (
"v2ray.com/core/app/dns" "v2ray.com/core/app/dns"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/app/router" "v2ray.com/core/app/router"
"v2ray.com/core/app/router/rules"
"v2ray.com/core/common/alloc" "v2ray.com/core/common/alloc"
v2net "v2ray.com/core/common/net" v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
@ -86,7 +85,7 @@ func TestIPResolution(t *testing.T) {
space := app.NewSpace() space := app.NewSpace()
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager()) space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager())
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
r, _ := router.CreateRouter("rules", &rules.RouterRuleConfig{}, space) r := router.NewRouter(&router.Config{}, space)
space.BindApp(router.APP_ID, r) space.BindApp(router.APP_ID, r)
dnsServer := dns.NewCacheServer(space, &dns.Config{ dnsServer := dns.NewCacheServer(space, &dns.Config{
Hosts: map[string]*v2net.AddressPB{ Hosts: map[string]*v2net.AddressPB{

View File

@ -9,7 +9,6 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
_ "v2ray.com/core/app/router/rules"
. "v2ray.com/core/shell/point" . "v2ray.com/core/shell/point"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"

View File

@ -10,7 +10,6 @@ import (
"syscall" "syscall"
"v2ray.com/core" "v2ray.com/core"
_ "v2ray.com/core/app/router/rules"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
"v2ray.com/core/shell/point" "v2ray.com/core/shell/point"

View File

@ -28,7 +28,7 @@ type Point struct {
idh []InboundDetourHandler idh []InboundDetourHandler
taggedIdh map[string]InboundDetourHandler taggedIdh map[string]InboundDetourHandler
odh map[string]proxy.OutboundHandler odh map[string]proxy.OutboundHandler
router router.Router router *router.Router
space app.Space space app.Space
} }
@ -67,11 +67,7 @@ func NewPoint(pConfig *Config) (*Point, error) {
routerConfig := pConfig.RouterConfig routerConfig := pConfig.RouterConfig
if routerConfig != nil { if routerConfig != nil {
r, err := router.CreateRouter(routerConfig.Strategy, routerConfig.Settings, vpoint.space) r := router.NewRouter(routerConfig, vpoint.space)
if err != nil {
log.Error("Failed to create router: ", err)
return nil, common.ErrBadConfiguration
}
vpoint.space.BindApp(router.APP_ID, r) vpoint.space.BindApp(router.APP_ID, r)
vpoint.router = r vpoint.router = r
} }

View File

@ -7,7 +7,6 @@ import (
"runtime" "runtime"
"time" "time"
_ "v2ray.com/core/app/router/rules"
"v2ray.com/core/common/log" "v2ray.com/core/common/log"
// The following are necessary as they register handlers in their init functions. // The following are necessary as they register handlers in their init functions.