Compare commits

..

14 Commits
v4.2 ... v4.3

Author SHA1 Message Date
Darien Raymond
df2d5b5d75 fix broken tests 2018-11-08 01:01:53 +01:00
Darien Raymond
58221ebae1 optimize multi-geoip matcher 2018-11-07 23:57:06 +01:00
Darien Raymond
2cc92920fa test case for balancer 2018-11-07 21:25:43 +01:00
Darien Raymond
73d3be424b prototype for balancing rules 2018-11-07 21:08:20 +01:00
Darien Raymond
874fc87498 test long header 2018-11-07 17:16:57 +01:00
Darien Raymond
440cf090d6 notify remote peer to close session 2018-11-07 12:46:20 +01:00
Darien Raymond
9f56d48297 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2018-11-07 09:12:07 +01:00
Victoria Raymond
c98019a9c3 Merge pull request #1366 from wuxiangzhou2010/patch-1
fix a typo
2018-11-07 07:03:24 +01:00
Wuxiang
557330808d fix a typo 2018-11-07 11:15:47 +08:00
Darien Raymond
90b132b434 update ci machine type 2018-11-06 22:02:52 +01:00
Darien Raymond
9d91a97926 golang 1.11.2 2018-11-06 20:54:17 +01:00
Darien Raymond
4b2ee1185d update config file 2018-11-05 22:13:45 +01:00
Darien Raymond
03386f958d update release ci 2018-11-05 17:13:35 +01:00
Darien Raymond
425ac88133 Update version 2018-11-05 16:13:08 +01:00
25 changed files with 732 additions and 109 deletions

View File

@@ -4,6 +4,7 @@ package outbound
import (
"context"
"strings"
"sync"
"v2ray.com/core"
@@ -134,6 +135,28 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
return nil
}
func (m *Manager) Select(selectors []string) []string {
m.access.RLock()
defer m.access.RUnlock()
tags := make([]string, 0, len(selectors))
for tag := range m.taggedHandler {
match := false
for _, selector := range selectors {
if strings.HasPrefix(tag, selector) {
match = true
break
}
}
if match {
tags = append(tags, tag)
}
}
return tags
}
func init() {
common.Must(common.RegisterConfig((*proxyman.OutboundConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*proxyman.OutboundConfig))

44
app/router/balancing.go Normal file
View File

@@ -0,0 +1,44 @@
package router
import (
"v2ray.com/core/common/dice"
"v2ray.com/core/features/outbound"
)
type BalancingStrategy interface {
PickOutbound([]string) string
}
type RandomStrategy struct {
}
func (s *RandomStrategy) PickOutbound(tags []string) string {
n := len(tags)
if n == 0 {
panic("0 tags")
}
return tags[dice.Roll(n)]
}
type Balancer struct {
selectors []string
strategy BalancingStrategy
ohm outbound.Manager
}
func (b *Balancer) PickOutbound() (string, error) {
hs, ok := b.ohm.(outbound.HandlerSelector)
if !ok {
return "", newError("outbound.Manager is not a HandlerSelector")
}
tags := hs.Select(b.selectors)
if len(tags) == 0 {
return "", newError("no available outbounds selected")
}
tag := b.strategy.PickOutbound(tags)
if len(tag) == 0 {
return "", newError("balancing strategy returns empty tag")
}
return tag, nil
}

View File

@@ -113,7 +113,7 @@ func targetFromContent(ctx context.Context) net.Destination {
type MultiGeoIPMatcher struct {
matchers []*GeoIPMatcher
onSource bool
destFunc func(context.Context) net.Destination
}
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
@@ -126,32 +126,33 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, e
matchers = append(matchers, matcher)
}
var destFunc func(context.Context) net.Destination
if onSource {
destFunc = sourceFromContext
} else {
destFunc = targetFromContent
}
return &MultiGeoIPMatcher{
matchers: matchers,
onSource: onSource,
destFunc: destFunc,
}, nil
}
func (m *MultiGeoIPMatcher) Apply(ctx context.Context) bool {
ips := make([]net.IP, 0, 4)
if resolver, ok := ResolvedIPsFromContext(ctx); ok {
dest := m.destFunc(ctx)
if dest.IsValid() && (dest.Address.Family().IsIPv4() || dest.Address.Family().IsIPv6()) {
ips = append(ips, dest.Address.IP())
} else if resolver, ok := ResolvedIPsFromContext(ctx); ok {
resolvedIPs := resolver.Resolve()
for _, rip := range resolvedIPs {
ips = append(ips, rip.IP())
}
}
var dest net.Destination
if m.onSource {
dest = sourceFromContext(ctx)
} else {
dest = targetFromContent(ctx)
}
if dest.IsValid() && (dest.Address.Family().IsIPv4() || dest.Address.Family().IsIPv6()) {
ips = append(ips, dest.Address.IP())
}
for _, ip := range ips {
for _, matcher := range m.matchers {
if matcher.Match(ip) {

View File

@@ -285,3 +285,56 @@ func TestChinaSites(t *testing.T) {
assert(matcher.ApplyDomain(strconv.Itoa(i)+".not-exists.com"), IsFalse)
}
}
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "release", "config", "geoip.dat")))
var geoips []*GeoIP
{
ips, err := loadGeoIP("CN")
common.Must(err)
geoips = append(geoips, &GeoIP{
CountryCode: "CN",
Cidr: ips,
})
}
{
ips, err := loadGeoIP("JP")
common.Must(err)
geoips = append(geoips, &GeoIP{
CountryCode: "JP",
Cidr: ips,
})
}
{
ips, err := loadGeoIP("CA")
common.Must(err)
geoips = append(geoips, &GeoIP{
CountryCode: "CA",
Cidr: ips,
})
}
{
ips, err := loadGeoIP("US")
common.Must(err)
geoips = append(geoips, &GeoIP{
CountryCode: "US",
Cidr: ips,
})
}
matcher, err := NewMultiGeoIPMatcher(geoips, false)
common.Must(err)
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = matcher.Apply(ctx)
}
}

View File

@@ -2,6 +2,8 @@ package router
import (
"context"
"v2ray.com/core/features/outbound"
)
// CIDRList is an alias of []*CIDR to provide sort.Interface.
@@ -45,9 +47,17 @@ func (l *CIDRList) Swap(i int, j int) {
type Rule struct {
Tag string
Balancer *Balancer
Condition Condition
}
func (r *Rule) GetTag() (string, error) {
if r.Balancer != nil {
return r.Balancer.PickOutbound()
}
return r.Tag, nil
}
func (r *Rule) Apply(ctx context.Context) bool {
return r.Condition.Apply(ctx)
}
@@ -117,3 +127,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
return conds, nil
}
func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
return &Balancer{
selectors: br.OutboundSelector,
strategy: &RandomStrategy{},
ohm: ohm,
}, nil
}

View File

@@ -86,7 +86,7 @@ func (x Config_DomainStrategy) String() string {
}
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_6b1608360690c5fc, []int{7, 0}
return fileDescriptor_6b1608360690c5fc, []int{8, 0}
}
// Domain for routing decision.
@@ -362,8 +362,10 @@ func (m *GeoSiteList) GetEntry() []*GeoSite {
}
type RoutingRule struct {
// Tag of outbound that this rule is pointing to.
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
// Types that are valid to be assigned to TargetTag:
// *RoutingRule_Tag
// *RoutingRule_BalancingTag
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
// List of domains for target domain matching.
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
// List of CIDRs for target IP address matching.
@@ -412,9 +414,39 @@ func (m *RoutingRule) XXX_DiscardUnknown() {
var xxx_messageInfo_RoutingRule proto.InternalMessageInfo
func (m *RoutingRule) GetTag() string {
type isRoutingRule_TargetTag interface {
isRoutingRule_TargetTag()
}
type RoutingRule_Tag struct {
Tag string `protobuf:"bytes,1,opt,name=tag,proto3,oneof"`
}
type RoutingRule_BalancingTag struct {
BalancingTag string `protobuf:"bytes,12,opt,name=balancing_tag,json=balancingTag,proto3,oneof"`
}
func (*RoutingRule_Tag) isRoutingRule_TargetTag() {}
func (*RoutingRule_BalancingTag) isRoutingRule_TargetTag() {}
func (m *RoutingRule) GetTargetTag() isRoutingRule_TargetTag {
if m != nil {
return m.Tag
return m.TargetTag
}
return nil
}
func (m *RoutingRule) GetTag() string {
if x, ok := m.GetTargetTag().(*RoutingRule_Tag); ok {
return x.Tag
}
return ""
}
func (m *RoutingRule) GetBalancingTag() string {
if x, ok := m.GetTargetTag().(*RoutingRule_BalancingTag); ok {
return x.BalancingTag
}
return ""
}
@@ -491,9 +523,123 @@ func (m *RoutingRule) GetProtocol() []string {
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*RoutingRule) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _RoutingRule_OneofMarshaler, _RoutingRule_OneofUnmarshaler, _RoutingRule_OneofSizer, []interface{}{
(*RoutingRule_Tag)(nil),
(*RoutingRule_BalancingTag)(nil),
}
}
func _RoutingRule_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*RoutingRule)
// target_tag
switch x := m.TargetTag.(type) {
case *RoutingRule_Tag:
b.EncodeVarint(1<<3 | proto.WireBytes)
b.EncodeStringBytes(x.Tag)
case *RoutingRule_BalancingTag:
b.EncodeVarint(12<<3 | proto.WireBytes)
b.EncodeStringBytes(x.BalancingTag)
case nil:
default:
return fmt.Errorf("RoutingRule.TargetTag has unexpected type %T", x)
}
return nil
}
func _RoutingRule_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*RoutingRule)
switch tag {
case 1: // target_tag.tag
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeStringBytes()
m.TargetTag = &RoutingRule_Tag{x}
return true, err
case 12: // target_tag.balancing_tag
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeStringBytes()
m.TargetTag = &RoutingRule_BalancingTag{x}
return true, err
default:
return false, nil
}
}
func _RoutingRule_OneofSizer(msg proto.Message) (n int) {
m := msg.(*RoutingRule)
// target_tag
switch x := m.TargetTag.(type) {
case *RoutingRule_Tag:
n += 1 // tag and wire
n += proto.SizeVarint(uint64(len(x.Tag)))
n += len(x.Tag)
case *RoutingRule_BalancingTag:
n += 1 // tag and wire
n += proto.SizeVarint(uint64(len(x.BalancingTag)))
n += len(x.BalancingTag)
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
type BalancingRule struct {
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
OutboundSelector []string `protobuf:"bytes,2,rep,name=outbound_selector,json=outboundSelector,proto3" json:"outbound_selector,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BalancingRule) Reset() { *m = BalancingRule{} }
func (m *BalancingRule) String() string { return proto.CompactTextString(m) }
func (*BalancingRule) ProtoMessage() {}
func (*BalancingRule) Descriptor() ([]byte, []int) {
return fileDescriptor_6b1608360690c5fc, []int{7}
}
func (m *BalancingRule) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BalancingRule.Unmarshal(m, b)
}
func (m *BalancingRule) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BalancingRule.Marshal(b, m, deterministic)
}
func (m *BalancingRule) XXX_Merge(src proto.Message) {
xxx_messageInfo_BalancingRule.Merge(m, src)
}
func (m *BalancingRule) XXX_Size() int {
return xxx_messageInfo_BalancingRule.Size(m)
}
func (m *BalancingRule) XXX_DiscardUnknown() {
xxx_messageInfo_BalancingRule.DiscardUnknown(m)
}
var xxx_messageInfo_BalancingRule proto.InternalMessageInfo
func (m *BalancingRule) GetTag() string {
if m != nil {
return m.Tag
}
return ""
}
func (m *BalancingRule) GetOutboundSelector() []string {
if m != nil {
return m.OutboundSelector
}
return nil
}
type Config struct {
DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=v2ray.core.app.router.Config_DomainStrategy" json:"domain_strategy,omitempty"`
Rule []*RoutingRule `protobuf:"bytes,2,rep,name=rule,proto3" json:"rule,omitempty"`
BalancingRule []*BalancingRule `protobuf:"bytes,3,rep,name=balancing_rule,json=balancingRule,proto3" json:"balancing_rule,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -503,7 +649,7 @@ func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) {
return fileDescriptor_6b1608360690c5fc, []int{7}
return fileDescriptor_6b1608360690c5fc, []int{8}
}
func (m *Config) XXX_Unmarshal(b []byte) error {
@@ -538,6 +684,13 @@ func (m *Config) GetRule() []*RoutingRule {
return nil
}
func (m *Config) GetBalancingRule() []*BalancingRule {
if m != nil {
return m.BalancingRule
}
return nil
}
func init() {
proto.RegisterEnum("v2ray.core.app.router.Domain_Type", Domain_Type_name, Domain_Type_value)
proto.RegisterEnum("v2ray.core.app.router.Config_DomainStrategy", Config_DomainStrategy_name, Config_DomainStrategy_value)
@@ -548,6 +701,7 @@ func init() {
proto.RegisterType((*GeoSite)(nil), "v2ray.core.app.router.GeoSite")
proto.RegisterType((*GeoSiteList)(nil), "v2ray.core.app.router.GeoSiteList")
proto.RegisterType((*RoutingRule)(nil), "v2ray.core.app.router.RoutingRule")
proto.RegisterType((*BalancingRule)(nil), "v2ray.core.app.router.BalancingRule")
proto.RegisterType((*Config)(nil), "v2ray.core.app.router.Config")
}
@@ -556,49 +710,54 @@ func init() {
}
var fileDescriptor_6b1608360690c5fc = []byte{
// 691 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xd3, 0x4c,
0x10, 0xfd, 0xec, 0xfc, 0xb4, 0x1e, 0xe7, 0x0b, 0xd6, 0x8a, 0x22, 0x53, 0x28, 0x04, 0x0b, 0x41,
0x2e, 0x90, 0x23, 0xa5, 0xc0, 0x1d, 0x2a, 0x6d, 0x5a, 0xa2, 0x48, 0x50, 0xa2, 0x6d, 0xcb, 0x05,
0x5c, 0x44, 0xae, 0xb3, 0x35, 0x16, 0xce, 0xee, 0x6a, 0xbd, 0x2e, 0xcd, 0x2b, 0xf0, 0x20, 0x5c,
0xf0, 0x54, 0x3c, 0x0a, 0xda, 0x9f, 0x40, 0x8b, 0x1a, 0x88, 0xb8, 0xdb, 0x59, 0x9f, 0x33, 0x73,
0xe6, 0x78, 0x76, 0xe0, 0xd1, 0x79, 0x5f, 0x24, 0xf3, 0x38, 0x65, 0xb3, 0x5e, 0xca, 0x04, 0xe9,
0x25, 0x9c, 0xf7, 0x04, 0xab, 0x24, 0x11, 0xbd, 0x94, 0xd1, 0xb3, 0x3c, 0x8b, 0xb9, 0x60, 0x92,
0xa1, 0x8d, 0x05, 0x4e, 0x90, 0x38, 0xe1, 0x3c, 0x36, 0x98, 0xcd, 0x87, 0xbf, 0xd1, 0x53, 0x36,
0x9b, 0x31, 0xda, 0xa3, 0x44, 0xf6, 0x38, 0x13, 0xd2, 0x90, 0x37, 0x1f, 0x2f, 0x47, 0x51, 0x22,
0x3f, 0x33, 0xf1, 0xc9, 0x00, 0xa3, 0x2f, 0x0e, 0x34, 0xf7, 0xd9, 0x2c, 0xc9, 0x29, 0x7a, 0x0e,
0x75, 0x39, 0xe7, 0x24, 0x74, 0x3a, 0x4e, 0xb7, 0xdd, 0x8f, 0xe2, 0x6b, 0xeb, 0xc7, 0x06, 0x1c,
0x1f, 0xcf, 0x39, 0xc1, 0x1a, 0x8f, 0x6e, 0x42, 0xe3, 0x3c, 0x29, 0x2a, 0x12, 0xba, 0x1d, 0xa7,
0xeb, 0x61, 0x13, 0x44, 0x7d, 0xa8, 0x2b, 0x0c, 0xf2, 0xa0, 0x31, 0x2e, 0x92, 0x9c, 0x06, 0xff,
0xa9, 0x23, 0x26, 0x19, 0xb9, 0x08, 0x1c, 0x04, 0x8b, 0xaa, 0x81, 0x8b, 0xd6, 0xa1, 0xfe, 0xaa,
0x2a, 0x8a, 0xa0, 0x16, 0xc5, 0x50, 0x1f, 0x8c, 0xf6, 0x31, 0x6a, 0x83, 0x9b, 0x73, 0xad, 0xa3,
0x85, 0xdd, 0x9c, 0xa3, 0x5b, 0xd0, 0xe4, 0x82, 0x9c, 0xe5, 0x17, 0xba, 0xc4, 0xff, 0xd8, 0x46,
0xd1, 0x07, 0x68, 0x0c, 0x09, 0x1b, 0x8d, 0xd1, 0x03, 0x68, 0xa5, 0xac, 0xa2, 0x52, 0xcc, 0x27,
0x29, 0x9b, 0x9a, 0x16, 0x3c, 0xec, 0xdb, 0xbb, 0x01, 0x9b, 0x12, 0xd4, 0x83, 0x7a, 0x9a, 0x4f,
0x45, 0xe8, 0x76, 0x6a, 0x5d, 0xbf, 0x7f, 0x67, 0x49, 0x77, 0xaa, 0x3c, 0xd6, 0xc0, 0x68, 0x07,
0x3c, 0x9d, 0xfc, 0x75, 0x5e, 0x4a, 0xd4, 0x87, 0x06, 0x51, 0xa9, 0x42, 0x47, 0xd3, 0xef, 0x2e,
0xa1, 0x6b, 0x02, 0x36, 0xd0, 0x28, 0x85, 0xb5, 0x21, 0x61, 0x47, 0xb9, 0x24, 0xab, 0xe8, 0x7b,
0x06, 0xcd, 0xa9, 0x76, 0xc4, 0x2a, 0xdc, 0xfa, 0xa3, 0xff, 0xd8, 0x82, 0xa3, 0x01, 0xf8, 0xb6,
0x88, 0xd6, 0xf9, 0xf4, 0xaa, 0xce, 0x7b, 0xcb, 0x75, 0x2a, 0xca, 0x42, 0xe9, 0xd7, 0x3a, 0xf8,
0x98, 0x55, 0x32, 0xa7, 0x19, 0xae, 0x0a, 0x82, 0x02, 0xa8, 0xc9, 0x24, 0xb3, 0x2a, 0xd5, 0xf1,
0x1f, 0xd5, 0xa1, 0x6d, 0x6b, 0x7a, 0xed, 0xaf, 0xa6, 0xef, 0xb9, 0xa1, 0x63, 0x8c, 0x57, 0x5e,
0x67, 0x84, 0xe5, 0x3c, 0x84, 0x55, 0xbc, 0xd6, 0x50, 0xb4, 0x03, 0xa0, 0xa6, 0x7f, 0x22, 0x12,
0x9a, 0x91, 0xb0, 0xde, 0x71, 0xba, 0x7e, 0xbf, 0x73, 0x99, 0x68, 0x1e, 0x40, 0x4c, 0x89, 0x8c,
0xc7, 0x4c, 0x48, 0xac, 0x70, 0xd8, 0xe3, 0x8b, 0x23, 0x3a, 0x80, 0x96, 0x7d, 0x18, 0x93, 0x22,
0x2f, 0x65, 0xd8, 0xd0, 0x29, 0xa2, 0x25, 0x29, 0x0e, 0x0d, 0x54, 0x59, 0x8e, 0x7d, 0xfa, 0x2b,
0x40, 0x2f, 0xc1, 0x2f, 0x59, 0x25, 0x52, 0x32, 0xd1, 0x7d, 0x37, 0x57, 0xeb, 0x1b, 0x0c, 0x67,
0xa0, 0xba, 0xdf, 0x81, 0x96, 0xcd, 0x60, 0x4c, 0xf0, 0x57, 0x30, 0xc1, 0xd6, 0x1c, 0x6a, 0x2b,
0xb6, 0x00, 0xaa, 0x92, 0x88, 0x09, 0x99, 0x25, 0x79, 0x11, 0xae, 0x75, 0x6a, 0x5d, 0x0f, 0x7b,
0xea, 0xe6, 0x40, 0x5d, 0xa0, 0xfb, 0xe0, 0xe7, 0xf4, 0x94, 0x55, 0x74, 0x3a, 0x51, 0xff, 0x78,
0x5d, 0x7f, 0x07, 0x7b, 0x75, 0x9c, 0x64, 0x68, 0x13, 0xd6, 0xf5, 0x6a, 0x48, 0x59, 0x11, 0x7a,
0xfa, 0xeb, 0xcf, 0x38, 0xfa, 0xee, 0x40, 0x73, 0xa0, 0x97, 0x14, 0x3a, 0x81, 0x1b, 0xe6, 0x27,
0x4f, 0x4a, 0x29, 0x12, 0x49, 0xb2, 0xb9, 0x5d, 0x1c, 0x4f, 0x96, 0x75, 0x6b, 0x96, 0x9b, 0x99,
0x90, 0x23, 0xcb, 0xc1, 0xed, 0xe9, 0x95, 0x58, 0x2d, 0x21, 0x51, 0x15, 0xc4, 0x8e, 0xd9, 0xb2,
0x25, 0x74, 0x69, 0x58, 0xb1, 0xc6, 0x47, 0x43, 0x68, 0x5f, 0xcd, 0xac, 0xd6, 0xca, 0x6e, 0x39,
0x2a, 0xcd, 0xde, 0x39, 0x29, 0xc9, 0x88, 0x07, 0x0e, 0x0a, 0xa0, 0x35, 0xe2, 0xa3, 0xb3, 0x43,
0x46, 0xdf, 0x24, 0x32, 0xfd, 0x18, 0xb8, 0xa8, 0x0d, 0x30, 0xe2, 0x6f, 0xe9, 0x3e, 0x99, 0x25,
0x74, 0x1a, 0xd4, 0xf6, 0x5e, 0xc0, 0xed, 0x94, 0xcd, 0xae, 0xaf, 0x3b, 0x76, 0xde, 0x37, 0xcd,
0xe9, 0x9b, 0xbb, 0xf1, 0xae, 0x8f, 0x93, 0x79, 0x3c, 0x50, 0x88, 0x5d, 0xce, 0xb5, 0x24, 0x22,
0x4e, 0x9b, 0xda, 0xab, 0xed, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x42, 0x5b, 0xf4, 0x78, 0xe6,
0x05, 0x00, 0x00,
// 776 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xeb, 0x44,
0x10, 0x3e, 0x76, 0x7e, 0x4e, 0x3d, 0x76, 0x83, 0x59, 0x71, 0x90, 0x29, 0x14, 0x82, 0x55, 0x20,
0x12, 0xc8, 0x91, 0x52, 0xe0, 0x0e, 0x95, 0x26, 0x2d, 0x21, 0x02, 0x4a, 0xb4, 0x6d, 0xb9, 0x80,
0x8b, 0x68, 0xeb, 0x6c, 0x8d, 0x85, 0xb3, 0xbb, 0x5a, 0xaf, 0x4b, 0xf3, 0x0a, 0x3c, 0x0a, 0x12,
0x8f, 0xc4, 0xbb, 0xa0, 0xdd, 0x75, 0xda, 0x06, 0xd5, 0x10, 0x9d, 0xbb, 0x9d, 0xd9, 0x6f, 0x66,
0xbe, 0xf9, 0x85, 0x8f, 0xef, 0x46, 0x92, 0xac, 0x93, 0x94, 0xaf, 0x86, 0x29, 0x97, 0x74, 0x48,
0x84, 0x18, 0x4a, 0x5e, 0x29, 0x2a, 0x87, 0x29, 0x67, 0xb7, 0x79, 0x96, 0x08, 0xc9, 0x15, 0x47,
0xaf, 0x36, 0x38, 0x49, 0x13, 0x22, 0x44, 0x62, 0x31, 0x07, 0x47, 0xff, 0x32, 0x4f, 0xf9, 0x6a,
0xc5, 0xd9, 0x90, 0x51, 0x35, 0x14, 0x5c, 0x2a, 0x6b, 0x7c, 0xf0, 0x49, 0x33, 0x8a, 0x51, 0xf5,
0x3b, 0x97, 0xbf, 0x59, 0x60, 0xfc, 0x87, 0x03, 0xdd, 0x33, 0xbe, 0x22, 0x39, 0x43, 0x5f, 0x42,
0x5b, 0xad, 0x05, 0x8d, 0x9c, 0xbe, 0x33, 0xe8, 0x8d, 0xe2, 0xe4, 0xd9, 0xf8, 0x89, 0x05, 0x27,
0x57, 0x6b, 0x41, 0xb1, 0xc1, 0xa3, 0xb7, 0xa0, 0x73, 0x47, 0x8a, 0x8a, 0x46, 0x6e, 0xdf, 0x19,
0x78, 0xd8, 0x0a, 0xf1, 0x08, 0xda, 0x1a, 0x83, 0x3c, 0xe8, 0xcc, 0x0b, 0x92, 0xb3, 0xf0, 0x85,
0x7e, 0x62, 0x9a, 0xd1, 0xfb, 0xd0, 0x41, 0xb0, 0x89, 0x1a, 0xba, 0x68, 0x0f, 0xda, 0xdf, 0x54,
0x45, 0x11, 0xb6, 0xe2, 0x04, 0xda, 0x93, 0xd9, 0x19, 0x46, 0x3d, 0x70, 0x73, 0x61, 0x78, 0x04,
0xd8, 0xcd, 0x05, 0x7a, 0x1b, 0xba, 0x42, 0xd2, 0xdb, 0xfc, 0xde, 0x84, 0xd8, 0xc7, 0xb5, 0x14,
0xff, 0x02, 0x9d, 0x29, 0xe5, 0xb3, 0x39, 0xfa, 0x10, 0x82, 0x94, 0x57, 0x4c, 0xc9, 0xf5, 0x22,
0xe5, 0x4b, 0x9b, 0x82, 0x87, 0xfd, 0x5a, 0x37, 0xe1, 0x4b, 0x8a, 0x86, 0xd0, 0x4e, 0xf3, 0xa5,
0x8c, 0xdc, 0x7e, 0x6b, 0xe0, 0x8f, 0xde, 0x6d, 0xc8, 0x4e, 0x87, 0xc7, 0x06, 0x18, 0x9f, 0x80,
0x67, 0x9c, 0x7f, 0x9f, 0x97, 0x0a, 0x8d, 0xa0, 0x43, 0xb5, 0xab, 0xc8, 0x31, 0xe6, 0xef, 0x35,
0x98, 0x1b, 0x03, 0x6c, 0xa1, 0x71, 0x0a, 0x2f, 0xa7, 0x94, 0x5f, 0xe6, 0x8a, 0xee, 0xc2, 0xef,
0x0b, 0xe8, 0x2e, 0x4d, 0x45, 0x6a, 0x86, 0x87, 0xff, 0x59, 0x7f, 0x5c, 0x83, 0xe3, 0x09, 0xf8,
0x75, 0x10, 0xc3, 0xf3, 0xf3, 0x6d, 0x9e, 0xef, 0x37, 0xf3, 0xd4, 0x26, 0x1b, 0xa6, 0x7f, 0xb7,
0xc1, 0xc7, 0xbc, 0x52, 0x39, 0xcb, 0x70, 0x55, 0x50, 0x84, 0xa0, 0xa5, 0x48, 0x66, 0x59, 0x7e,
0xfb, 0x02, 0x6b, 0x01, 0x7d, 0x04, 0xfb, 0x37, 0xa4, 0x20, 0x2c, 0xcd, 0x59, 0xb6, 0xd0, 0xbf,
0x41, 0xfd, 0x1b, 0x3c, 0xa8, 0xaf, 0x48, 0xf6, 0x9a, 0x69, 0xa0, 0xe3, 0xba, 0x3b, 0xad, 0xff,
0xed, 0xce, 0xd8, 0x8d, 0x1c, 0xdb, 0x21, 0xdd, 0x94, 0x8c, 0xf2, 0x5c, 0x44, 0xb0, 0x4b, 0x53,
0x0c, 0x14, 0x9d, 0x00, 0xe8, 0x35, 0x59, 0x48, 0xc2, 0x32, 0x1a, 0xb5, 0xfb, 0xce, 0xc0, 0x1f,
0xf5, 0x9f, 0x1a, 0xda, 0x4d, 0x49, 0x18, 0x55, 0xc9, 0x9c, 0x4b, 0x85, 0x35, 0x0e, 0x7b, 0x62,
0xf3, 0x44, 0xe7, 0x10, 0xd4, 0x1b, 0xb4, 0x28, 0xf2, 0x52, 0x45, 0x1d, 0xe3, 0x22, 0x6e, 0x70,
0x71, 0x61, 0xa1, 0xba, 0x37, 0xd8, 0x67, 0x8f, 0x02, 0xfa, 0x1a, 0xfc, 0x92, 0x57, 0x32, 0xa5,
0x0b, 0x93, 0x77, 0x77, 0xb7, 0xbc, 0xc1, 0xda, 0x4c, 0x74, 0xf6, 0x27, 0x10, 0xd4, 0x1e, 0x6c,
0x11, 0xfc, 0x1d, 0x8a, 0x50, 0xc7, 0x9c, 0x9a, 0x52, 0x1c, 0x02, 0x54, 0x25, 0x95, 0x0b, 0xba,
0x22, 0x79, 0x11, 0xbd, 0xec, 0xb7, 0x06, 0x1e, 0xf6, 0xb4, 0xe6, 0x5c, 0x2b, 0xd0, 0x07, 0xe0,
0xe7, 0xec, 0x86, 0x57, 0x6c, 0x69, 0xda, 0xbd, 0x67, 0xfe, 0xa1, 0x56, 0xe9, 0x56, 0x1f, 0xc0,
0x9e, 0xb9, 0x21, 0x29, 0x2f, 0x22, 0xcf, 0xfc, 0x3e, 0xc8, 0xe3, 0x00, 0x40, 0x11, 0x99, 0x51,
0xa5, 0x6d, 0xe3, 0x0b, 0xd8, 0x1f, 0x6f, 0x86, 0xc4, 0x0c, 0x58, 0xf8, 0x64, 0xc0, 0xec, 0x78,
0x7d, 0x0a, 0x6f, 0xf2, 0x4a, 0xd9, 0x70, 0x25, 0x2d, 0x68, 0xaa, 0xb8, 0xdd, 0x55, 0x0f, 0x87,
0x9b, 0x8f, 0xcb, 0x5a, 0x1f, 0xff, 0xe5, 0x42, 0x77, 0x62, 0x6e, 0x25, 0xba, 0x86, 0x37, 0xec,
0x08, 0x2d, 0x4a, 0x25, 0x89, 0xa2, 0xd9, 0xba, 0xbe, 0x5f, 0x9f, 0x35, 0xd5, 0xd2, 0xde, 0x58,
0x3b, 0x7f, 0x97, 0xb5, 0x0d, 0xee, 0x2d, 0xb7, 0x64, 0x7d, 0x0b, 0x65, 0x55, 0xd0, 0x7a, 0x88,
0x9b, 0x6e, 0xe1, 0x93, 0x9d, 0xc1, 0x06, 0x8f, 0xbe, 0x83, 0xde, 0xe3, 0x96, 0x18, 0x0f, 0x76,
0xa2, 0x8f, 0x1a, 0x3c, 0x6c, 0x95, 0x05, 0x3f, 0x6e, 0x98, 0x16, 0xe3, 0x29, 0xf4, 0xb6, 0x69,
0xea, 0x53, 0x79, 0x5a, 0xce, 0x4a, 0x7b, 0x4b, 0xaf, 0x4b, 0x3a, 0x13, 0xa1, 0x83, 0x42, 0x08,
0x66, 0x62, 0x76, 0x7b, 0xc1, 0xd9, 0x0f, 0x44, 0xa5, 0xbf, 0x86, 0x2e, 0xea, 0x01, 0xcc, 0xc4,
0x8f, 0xec, 0x8c, 0xae, 0x08, 0x5b, 0x86, 0xad, 0xf1, 0x57, 0xf0, 0x4e, 0xca, 0x57, 0xcf, 0x53,
0x98, 0x3b, 0x3f, 0x77, 0xed, 0xeb, 0x4f, 0xf7, 0xd5, 0x4f, 0x23, 0x4c, 0xd6, 0xc9, 0x44, 0x23,
0x4e, 0x85, 0x30, 0xf9, 0x51, 0x79, 0xd3, 0x35, 0x6d, 0x3d, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff,
0x7c, 0x01, 0x52, 0xfa, 0xba, 0x06, 0x00, 0x00,
}

View File

@@ -58,8 +58,14 @@ message GeoSiteList{
}
message RoutingRule {
// Tag of outbound that this rule is pointing to.
string tag = 1;
oneof target_tag {
// Tag of outbound that this rule is pointing to.
string tag = 1;
// Tag of routing balancer.
string balancing_tag = 12;
}
// List of domains for target domain matching.
repeated Domain domain = 2;
@@ -87,6 +93,11 @@ message RoutingRule {
repeated string protocol = 9;
}
message BalancingRule {
string tag = 1;
repeated string outbound_selector = 2;
}
message Config {
enum DomainStrategy {
// Use domain as is.
@@ -103,4 +114,5 @@ message Config {
}
DomainStrategy domain_strategy = 1;
repeated RoutingRule rule = 2;
repeated BalancingRule balancing_rule = 3;
}

View File

@@ -10,6 +10,7 @@ import (
"v2ray.com/core/common/net"
"v2ray.com/core/common/session"
"v2ray.com/core/features/dns"
"v2ray.com/core/features/outbound"
"v2ray.com/core/features/routing"
)
@@ -35,8 +36,8 @@ func ResolvedIPsFromContext(ctx context.Context) (IPResolver, bool) {
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
r := new(Router)
if err := core.RequireFeatures(ctx, func(d dns.Client) error {
return r.Init(config.(*Config), d)
if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error {
return r.Init(config.(*Config), d, ohm)
}); err != nil {
return nil, err
}
@@ -47,23 +48,44 @@ func init() {
// Router is an implementation of routing.Router.
type Router struct {
domainStrategy Config_DomainStrategy
rules []Rule
rules []*Rule
balancers map[string]*Balancer
dns dns.Client
}
// Init initializes the Router.
func (r *Router) Init(config *Config, d dns.Client) error {
func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error {
r.domainStrategy = config.DomainStrategy
r.rules = make([]Rule, len(config.Rule))
r.dns = d
for idx, rule := range config.Rule {
r.rules[idx].Tag = rule.Tag
r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
for _, rule := range config.BalancingRule {
balancer, err := rule.Build(ohm)
if err != nil {
return err
}
r.balancers[rule.Tag] = balancer
}
r.rules = make([]*Rule, 0, len(config.Rule))
for _, rule := range config.Rule {
cond, err := rule.BuildCondition()
if err != nil {
return err
}
r.rules[idx].Condition = cond
rr := &Rule{
Condition: cond,
Tag: rule.GetTag(),
}
btag := rule.GetBalancingTag()
if len(btag) > 0 {
brule, found := r.balancers[btag]
if !found {
return newError("balancer ", btag, " not found")
}
rr.Balancer = brule
}
r.rules = append(r.rules, rr)
}
return nil
@@ -97,8 +119,16 @@ func (r *ipResolver) Resolve() []net.Address {
return r.ip
}
// PickRoute implements routing.Router.
func (r *Router) PickRoute(ctx context.Context) (string, error) {
rule, err := r.pickRouteInternal(ctx)
if err != nil {
return "", err
}
return rule.GetTag()
}
// PickRoute implements routing.Router.
func (r *Router) pickRouteInternal(ctx context.Context) (*Rule, error) {
resolver := &ipResolver{
dns: r.dns,
}
@@ -113,12 +143,12 @@ func (r *Router) PickRoute(ctx context.Context) (string, error) {
for _, rule := range r.rules {
if rule.Apply(ctx) {
return rule.Tag, nil
return rule, nil
}
}
if outbound == nil || !outbound.Target.IsValid() {
return "", common.ErrNoClue
return nil, common.ErrNoClue
}
dest := outbound.Target
@@ -129,13 +159,13 @@ func (r *Router) PickRoute(ctx context.Context) (string, error) {
ctx = ContextWithResolveIPs(ctx, resolver)
for _, rule := range r.rules {
if rule.Apply(ctx) {
return rule.Tag, nil
return rule, nil
}
}
}
}
return "", common.ErrNoClue
return nil, common.ErrNoClue
}
// Start implements common.Runnable.

View File

@@ -8,14 +8,22 @@ import (
"v2ray.com/core/common"
"v2ray.com/core/common/net"
"v2ray.com/core/common/session"
"v2ray.com/core/features/outbound"
"v2ray.com/core/testing/mocks"
)
type mockOutboundManager struct {
outbound.Manager
outbound.HandlerSelector
}
func TestSimpleRouter(t *testing.T) {
config := &Config{
Rule: []*RoutingRule{
{
Tag: "test",
TargetTag: &RoutingRule_Tag{
Tag: "test",
},
NetworkList: &net.NetworkList{
Network: []net.Network{net.Network_TCP},
},
@@ -27,9 +35,57 @@ func TestSimpleRouter(t *testing.T) {
defer mockCtl.Finish()
mockDns := mocks.NewDNSClient(mockCtl)
mockOhm := mocks.NewOutboundManager(mockCtl)
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
r := new(Router)
common.Must(r.Init(config, mockDns))
common.Must(r.Init(config, mockDns, &mockOutboundManager{
Manager: mockOhm,
HandlerSelector: mockHs,
}))
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
tag, err := r.PickRoute(ctx)
common.Must(err)
if tag != "test" {
t.Error("expect tag 'test', bug actually ", tag)
}
}
func TestSimpleBalancer(t *testing.T) {
config := &Config{
Rule: []*RoutingRule{
{
TargetTag: &RoutingRule_BalancingTag{
BalancingTag: "balance",
},
NetworkList: &net.NetworkList{
Network: []net.Network{net.Network_TCP},
},
},
},
BalancingRule: []*BalancingRule{
{
Tag: "balance",
OutboundSelector: []string{"test-"},
},
},
}
mockCtl := gomock.NewController(t)
defer mockCtl.Finish()
mockDns := mocks.NewDNSClient(mockCtl)
mockOhm := mocks.NewOutboundManager(mockCtl)
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"})
r := new(Router)
common.Must(r.Init(config, mockDns, &mockOutboundManager{
Manager: mockOhm,
HandlerSelector: mockHs,
}))
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
tag, err := r.PickRoute(ctx)
@@ -44,7 +100,9 @@ func TestIPOnDemand(t *testing.T) {
DomainStrategy: Config_IpOnDemand,
Rule: []*RoutingRule{
{
Tag: "test",
TargetTag: &RoutingRule_Tag{
Tag: "test",
},
Cidr: []*CIDR{
{
Ip: []byte{192, 168, 0, 0},
@@ -62,7 +120,7 @@ func TestIPOnDemand(t *testing.T) {
mockDns.EXPECT().LookupIP(gomock.Eq("v2ray.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
r := new(Router)
common.Must(r.Init(config, mockDns))
common.Must(r.Init(config, mockDns, nil))
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
tag, err := r.PickRoute(ctx)

View File

@@ -322,6 +322,10 @@ func (m *ClientWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
s, found := m.sessionManager.Get(meta.SessionID)
if !found {
// Notify remote peer to close this session.
closingWriter := NewResponseWriter(meta.SessionID, m.link.Writer, protocol.TransferTypeStream)
closingWriter.Close()
return buf.Copy(NewStreamReader(reader), buf.Discard)
}
@@ -330,6 +334,10 @@ func (m *ClientWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
if err != nil && buf.IsWriteError(err) {
newError("failed to write to downstream. closing session ", s.ID).Base(err).WriteToLog()
// Notify remote peer to close this session.
closingWriter := NewResponseWriter(meta.SessionID, m.link.Writer, protocol.TransferTypeStream)
closingWriter.Close()
drainErr := buf.Copy(rr, buf.Discard)
pipe.CloseError(s.input)
s.Close()

View File

@@ -159,6 +159,10 @@ func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
s, found := w.sessionManager.Get(meta.SessionID)
if !found {
// Notify remote peer to close this session.
closingWriter := NewResponseWriter(meta.SessionID, w.link.Writer, protocol.TransferTypeStream)
closingWriter.Close()
return buf.Copy(NewStreamReader(reader), buf.Discard)
}
@@ -166,7 +170,11 @@ func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
err := buf.Copy(rr, s.output)
if err != nil && buf.IsWriteError(err) {
newError("failed to write to downstream writer. closing session ", s.ID).Base(err)
newError("failed to write to downstream writer. closing session ", s.ID).Base(err).WriteToLog()
// Notify remote peer to close this session.
closingWriter := NewResponseWriter(meta.SessionID, w.link.Writer, protocol.TransferTypeStream)
closingWriter.Close()
drainErr := buf.Copy(rr, buf.Discard)
pipe.CloseError(s.input)

View File

@@ -5,7 +5,7 @@ import (
"strings"
)
// ToString serialize an abitrary value into string.
// ToString serialize an arbitrary value into string.
func ToString(v interface{}) string {
if v == nil {
return " "

View File

@@ -17,7 +17,7 @@ import (
)
const (
version = "4.2"
version = "4.3"
build = "Custom"
codename = "Po"
intro = "A unified platform for anti-censorship."

View File

@@ -15,6 +15,10 @@ type Handler interface {
Dispatch(ctx context.Context, link *transport.Link)
}
type HandlerSelector interface {
Select([]string) []string
}
// Manager is a feature that manages outbound.Handlers.
type Manager interface {
features.Feature

View File

@@ -6,4 +6,5 @@ package core
//go:generate mockgen -package mocks -destination testing/mocks/io.go -mock_names Reader=Reader,Writer=Writer io Reader,Writer
//go:generate mockgen -package mocks -destination testing/mocks/mux.go -mock_names ClientWorkerFactory=MuxClientWorkerFactory v2ray.com/core/common/mux ClientWorkerFactory
//go:generate mockgen -package mocks -destination testing/mocks/dns.go -mock_names Client=DNSClient v2ray.com/core/features/dns Client
//go:generate mockgen -package mocks -destination testing/mocks/outbound.go -mock_names Manager=OutboundManager,HandlerSelector=OutboundHandlerSelector v2ray.com/core/features/outbound Manager,HandlerSelector
//go:generate mockgen -package mocks -destination testing/mocks/proxy.go -mock_names Inbound=ProxyInbound,Outbound=ProxyOutbound v2ray.com/core/proxy Inbound,Outbound

View File

@@ -72,13 +72,15 @@
},
"servers": [
{
"address": "1.1.1.1",
"address": "114.114.114.114",
"port": 53,
// List of domains that use this DNS first.
"domains": [
"domain:v2ray.com"
]
},
"8.8.8.8",
"1.1.1.1",
"localhost"
]
},

View File

@@ -44,7 +44,7 @@ echo "Launching build machine."
DIR="$(dirname "$0")"
RAND="$(openssl rand -hex 5)"
gcloud compute instances create "v2raycore-${RAND}" \
--machine-type=n1-highcpu-2 \
--machine-type=n1-standard-2 \
--metadata=release_tag=v${VER},prerelease=${PRE} \
--metadata-from-file=startup-script=${DIR}/release-ci.sh \
--zone=europe-west4-c \

View File

@@ -32,13 +32,13 @@ chmod +x bazel-${BAZEL_VER}-installer-linux-x86_64.sh
./bazel-${BAZEL_VER}-installer-linux-x86_64.sh
popd
gsutil cp ${SIGN_KEY_PATH} /v2ray/build/sign_key.asc
echo ${SIGN_KEY_PASS} | gpg --passphrase-fd 0 --batch --import /v2ray/build/sign_key.asc
gsutil cp ${SIGN_KEY_PATH} /v2/build/sign_key.asc
echo ${SIGN_KEY_PASS} | gpg --passphrase-fd 0 --batch --import /v2/build/sign_key.asc
curl -L -o /v2ray/build/releases https://api.github.com/repos/v2ray/v2ray-core/releases
curl -L -o /v2/build/releases https://api.github.com/repos/v2ray/v2ray-core/releases
GO_INSTALL=golang.tar.gz
curl -L -o ${GO_INSTALL} https://storage.googleapis.com/golang/go1.11.1.linux-amd64.tar.gz
curl -L -o ${GO_INSTALL} https://storage.googleapis.com/golang/go1.11.2.linux-amd64.tar.gz
tar -C /usr/local -xzf ${GO_INSTALL}
export PATH=$PATH:/usr/local/go/bin

154
testing/mocks/outbound.go Normal file
View File

@@ -0,0 +1,154 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: v2ray.com/core/features/outbound (interfaces: Manager,HandlerSelector)
// Package mocks is a generated GoMock package.
package mocks
import (
context "context"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
outbound "v2ray.com/core/features/outbound"
)
// OutboundManager is a mock of Manager interface
type OutboundManager struct {
ctrl *gomock.Controller
recorder *OutboundManagerMockRecorder
}
// OutboundManagerMockRecorder is the mock recorder for OutboundManager
type OutboundManagerMockRecorder struct {
mock *OutboundManager
}
// NewOutboundManager creates a new mock instance
func NewOutboundManager(ctrl *gomock.Controller) *OutboundManager {
mock := &OutboundManager{ctrl: ctrl}
mock.recorder = &OutboundManagerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *OutboundManager) EXPECT() *OutboundManagerMockRecorder {
return m.recorder
}
// AddHandler mocks base method
func (m *OutboundManager) AddHandler(arg0 context.Context, arg1 outbound.Handler) error {
ret := m.ctrl.Call(m, "AddHandler", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// AddHandler indicates an expected call of AddHandler
func (mr *OutboundManagerMockRecorder) AddHandler(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddHandler", reflect.TypeOf((*OutboundManager)(nil).AddHandler), arg0, arg1)
}
// Close mocks base method
func (m *OutboundManager) Close() error {
ret := m.ctrl.Call(m, "Close")
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close
func (mr *OutboundManagerMockRecorder) Close() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*OutboundManager)(nil).Close))
}
// GetDefaultHandler mocks base method
func (m *OutboundManager) GetDefaultHandler() outbound.Handler {
ret := m.ctrl.Call(m, "GetDefaultHandler")
ret0, _ := ret[0].(outbound.Handler)
return ret0
}
// GetDefaultHandler indicates an expected call of GetDefaultHandler
func (mr *OutboundManagerMockRecorder) GetDefaultHandler() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultHandler", reflect.TypeOf((*OutboundManager)(nil).GetDefaultHandler))
}
// GetHandler mocks base method
func (m *OutboundManager) GetHandler(arg0 string) outbound.Handler {
ret := m.ctrl.Call(m, "GetHandler", arg0)
ret0, _ := ret[0].(outbound.Handler)
return ret0
}
// GetHandler indicates an expected call of GetHandler
func (mr *OutboundManagerMockRecorder) GetHandler(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0)
}
// RemoveHandler mocks base method
func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error {
ret := m.ctrl.Call(m, "RemoveHandler", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// RemoveHandler indicates an expected call of RemoveHandler
func (mr *OutboundManagerMockRecorder) RemoveHandler(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveHandler", reflect.TypeOf((*OutboundManager)(nil).RemoveHandler), arg0, arg1)
}
// Start mocks base method
func (m *OutboundManager) Start() error {
ret := m.ctrl.Call(m, "Start")
ret0, _ := ret[0].(error)
return ret0
}
// Start indicates an expected call of Start
func (mr *OutboundManagerMockRecorder) Start() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*OutboundManager)(nil).Start))
}
// Type mocks base method
func (m *OutboundManager) Type() interface{} {
ret := m.ctrl.Call(m, "Type")
ret0, _ := ret[0].(interface{})
return ret0
}
// Type indicates an expected call of Type
func (mr *OutboundManagerMockRecorder) Type() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*OutboundManager)(nil).Type))
}
// OutboundHandlerSelector is a mock of HandlerSelector interface
type OutboundHandlerSelector struct {
ctrl *gomock.Controller
recorder *OutboundHandlerSelectorMockRecorder
}
// OutboundHandlerSelectorMockRecorder is the mock recorder for OutboundHandlerSelector
type OutboundHandlerSelectorMockRecorder struct {
mock *OutboundHandlerSelector
}
// NewOutboundHandlerSelector creates a new mock instance
func NewOutboundHandlerSelector(ctrl *gomock.Controller) *OutboundHandlerSelector {
mock := &OutboundHandlerSelector{ctrl: ctrl}
mock.recorder = &OutboundHandlerSelectorMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *OutboundHandlerSelector) EXPECT() *OutboundHandlerSelectorMockRecorder {
return m.recorder
}
// Select mocks base method
func (m *OutboundHandlerSelector) Select(arg0 []string) []string {
ret := m.ctrl.Call(m, "Select", arg0)
ret0, _ := ret[0].([]string)
return ret0
}
// Select indicates an expected call of Select
func (mr *OutboundHandlerSelectorMockRecorder) Select(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*OutboundHandlerSelector)(nil).Select), arg0)
}

View File

@@ -56,7 +56,9 @@ func TestCommanderRemoveHandler(t *testing.T) {
Rule: []*router.RoutingRule{
{
InboundTag: []string{"api"},
Tag: "api",
TargetTag: &router.RoutingRule_Tag{
Tag: "api",
},
},
},
}),
@@ -173,7 +175,9 @@ func TestCommanderAddRemoveUser(t *testing.T) {
Rule: []*router.RoutingRule{
{
InboundTag: []string{"api"},
Tag: "api",
TargetTag: &router.RoutingRule_Tag{
Tag: "api",
},
},
},
}),
@@ -381,7 +385,9 @@ func TestCommanderStats(t *testing.T) {
Rule: []*router.RoutingRule{
{
InboundTag: []string{"api"},
Tag: "api",
TargetTag: &router.RoutingRule_Tag{
Tag: "api",
},
},
},
}),

View File

@@ -46,7 +46,9 @@ func TestResolveIP(t *testing.T) {
Prefix: 8,
},
},
Tag: "direct",
TargetTag: &router.RoutingRule_Tag{
Tag: "direct",
},
},
},
}),

View File

@@ -475,7 +475,9 @@ func TestBlackhole(t *testing.T) {
serial.ToTypedMessage(&router.Config{
Rule: []*router.RoutingRule{
{
Tag: "blocked",
TargetTag: &router.RoutingRule_Tag{
Tag: "blocked",
},
PortRange: net.SinglePortRange(dest2.Port),
},
},
@@ -714,10 +716,14 @@ func TestDomainSniffing(t *testing.T) {
serial.ToTypedMessage(&router.Config{
Rule: []*router.RoutingRule{
{
Tag: "direct",
TargetTag: &router.RoutingRule_Tag{
Tag: "direct",
},
InboundTag: []string{"snif"},
}, {
Tag: "redir",
TargetTag: &router.RoutingRule_Tag{
Tag: "redir",
},
InboundTag: []string{"http"},
},
},

View File

@@ -57,11 +57,15 @@ func TestReverseProxy(t *testing.T) {
Domain: []*router.Domain{
{Type: router.Domain_Full, Value: "test.v2ray.com"},
},
Tag: "portal",
TargetTag: &router.RoutingRule_Tag{
Tag: "portal",
},
},
{
InboundTag: []string{"external"},
Tag: "portal",
TargetTag: &router.RoutingRule_Tag{
Tag: "portal",
},
},
},
}),
@@ -122,11 +126,15 @@ func TestReverseProxy(t *testing.T) {
Domain: []*router.Domain{
{Type: router.Domain_Full, Value: "test.v2ray.com"},
},
Tag: "reverse",
TargetTag: &router.RoutingRule_Tag{
Tag: "reverse",
},
},
{
InboundTag: []string{"bridge"},
Tag: "freedom",
TargetTag: &router.RoutingRule_Tag{
Tag: "freedom",
},
},
},
}),
@@ -256,11 +264,15 @@ func TestReverseProxyLongRunning(t *testing.T) {
Domain: []*router.Domain{
{Type: router.Domain_Full, Value: "test.v2ray.com"},
},
Tag: "portal",
TargetTag: &router.RoutingRule_Tag{
Tag: "portal",
},
},
{
InboundTag: []string{"external"},
Tag: "portal",
TargetTag: &router.RoutingRule_Tag{
Tag: "portal",
},
},
},
}),
@@ -335,11 +347,15 @@ func TestReverseProxyLongRunning(t *testing.T) {
Domain: []*router.Domain{
{Type: router.Domain_Full, Value: "test.v2ray.com"},
},
Tag: "reverse",
TargetTag: &router.RoutingRule_Tag{
Tag: "reverse",
},
},
{
InboundTag: []string{"bridge"},
Tag: "freedom",
TargetTag: &router.RoutingRule_Tag{
Tag: "freedom",
},
},
},
}),

View File

@@ -231,7 +231,9 @@ func TestSocksBridageUDPWithRouting(t *testing.T) {
serial.ToTypedMessage(&router.Config{
Rule: []*router.RoutingRule{
{
Tag: "out",
TargetTag: &router.RoutingRule_Tag{
Tag: "out",
},
InboundTag: []string{"socks"},
},
},

View File

@@ -1,7 +1,9 @@
package http_test
import (
"bytes"
"context"
"crypto/rand"
"testing"
"time"
@@ -54,6 +56,20 @@ func TestRequestHeader(t *testing.T) {
assert(cache.String(), Equals, "GET / HTTP/1.1\r\nTest: Value\r\n\r\n")
}
func TestLongRequestHeader(t *testing.T) {
payload := make([]byte, buf.Size+2)
common.Must2(rand.Read(payload[:buf.Size-2]))
copy(payload[buf.Size-2:], []byte(ENDING))
payload = append(payload, []byte("abcd")...)
reader := HeaderReader{}
b, err := reader.Read(bytes.NewReader(payload))
common.Must(err)
if b.String() != "abcd" {
t.Error("expect content abcd, but actually ", b.String())
}
}
func TestConnection(t *testing.T) {
assert := With(t)