diff --git a/app/point/config/config.go b/app/point/config/config.go index b94b14f0e..0fe3d2f51 100644 --- a/app/point/config/config.go +++ b/app/point/config/config.go @@ -1,6 +1,7 @@ package config import ( + routerconfig "github.com/v2ray/v2ray-core/app/router/config" v2net "github.com/v2ray/v2ray-core/common/net" ) @@ -30,7 +31,9 @@ type OutboundDetourConfig interface { type PointConfig interface { Port() uint16 LogConfig() LogConfig + RouterConfig() routerconfig.RouterConfig InboundConfig() ConnectionConfig OutboundConfig() ConnectionConfig InboundDetours() []InboundDetourConfig + OutboundDetours() []OutboundDetourConfig } diff --git a/app/point/config/json/json.go b/app/point/config/json/json.go index b0fbf02c6..fa3d2a765 100644 --- a/app/point/config/json/json.go +++ b/app/point/config/json/json.go @@ -6,18 +6,21 @@ import ( "os" "github.com/v2ray/v2ray-core/app/point/config" + routerconfig "github.com/v2ray/v2ray-core/app/router/config" + routerconfigjson "github.com/v2ray/v2ray-core/app/router/config/json" "github.com/v2ray/v2ray-core/common/log" proxyconfig "github.com/v2ray/v2ray-core/proxy/common/config" ) // Config is the config for Point server. type Config struct { - PortValue uint16 `json:"port"` // Port of this Point server. - LogConfigValue *LogConfig `json:"log"` - InboundConfigValue *ConnectionConfig `json:"inbound"` - OutboundConfigValue *ConnectionConfig `json:"outbound"` - InboundDetoursValue []*InboundDetourConfig `json:"inboundDetour"` - OutboundDetoursValue []*OutboundDetourConfig `json:"outboundDetour"` + PortValue uint16 `json:"port"` // Port of this Point server. + LogConfigValue *LogConfig `json:"log"` + RouterConfigValue *routerconfigjson.RouterConfig `json:"router"` + InboundConfigValue *ConnectionConfig `json:"inbound"` + OutboundConfigValue *ConnectionConfig `json:"outbound"` + InboundDetoursValue []*InboundDetourConfig `json:"inboundDetour"` + OutboundDetoursValue []*OutboundDetourConfig `json:"outboundDetour"` } func (config *Config) Port() uint16 { @@ -31,6 +34,13 @@ func (config *Config) LogConfig() config.LogConfig { return config.LogConfigValue } +func (this *Config) RouterConfig() routerconfig.RouterConfig { + if this.RouterConfigValue == nil { + return nil + } + return this.RouterConfigValue +} + func (config *Config) InboundConfig() config.ConnectionConfig { if config.InboundConfigValue == nil { return nil diff --git a/app/point/config/testing/mocks/config.go b/app/point/config/testing/mocks/config.go index e0cbd0836..33e2d5841 100644 --- a/app/point/config/testing/mocks/config.go +++ b/app/point/config/testing/mocks/config.go @@ -2,6 +2,7 @@ package mocks import ( "github.com/v2ray/v2ray-core/app/point/config" + routerconfig "github.com/v2ray/v2ray-core/app/router/config" v2net "github.com/v2ray/v2ray-core/common/net" ) @@ -44,16 +45,27 @@ func (this *InboundDetourConfig) PortRange() v2net.PortRange { return this.PortRangeValue } +type OutboundDetourConfig struct { + ConnectionConfig + TagValue config.DetourTag +} + +func (this *OutboundDetourConfig) Tag() config.DetourTag { + return this.TagValue +} + func (config *LogConfig) AccessLog() string { return config.AccessLogValue } type Config struct { - PortValue uint16 - LogConfigValue *LogConfig - InboundConfigValue *ConnectionConfig - OutboundConfigValue *ConnectionConfig - InboundDetoursValue []*InboundDetourConfig + PortValue uint16 + LogConfigValue *LogConfig + RouterConfigValue routerconfig.RouterConfig + InboundConfigValue *ConnectionConfig + OutboundConfigValue *ConnectionConfig + InboundDetoursValue []*InboundDetourConfig + OutboundDetoursValue []*OutboundDetourConfig } func (config *Config) Port() uint16 { @@ -64,6 +76,10 @@ func (config *Config) LogConfig() config.LogConfig { return config.LogConfigValue } +func (this *Config) RouterConfig() routerconfig.RouterConfig { + return this.RouterConfigValue +} + func (config *Config) InboundConfig() config.ConnectionConfig { return config.InboundConfigValue } @@ -79,3 +95,11 @@ func (this *Config) InboundDetours() []config.InboundDetourConfig { } return detours } + +func (this *Config) OutboundDetours() []config.OutboundDetourConfig { + detours := make([]config.OutboundDetourConfig, len(this.OutboundDetoursValue)) + for idx, detour := range this.OutboundDetoursValue { + detours[idx] = detour + } + return detours +} diff --git a/app/point/point.go b/app/point/point.go index 358f069e7..6a1272ba1 100644 --- a/app/point/point.go +++ b/app/point/point.go @@ -2,6 +2,7 @@ package point import ( "github.com/v2ray/v2ray-core/app/point/config" + "github.com/v2ray/v2ray-core/app/router" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/common/retry" @@ -11,10 +12,12 @@ import ( // Point is an single server in V2Ray system. type Point struct { - port uint16 - ich connhandler.InboundConnectionHandler - och connhandler.OutboundConnectionHandler - idh []*InboundDetourHandler + port uint16 + ich connhandler.InboundConnectionHandler + och connhandler.OutboundConnectionHandler + idh []*InboundDetourHandler + odh map[config.DetourTag]connhandler.OutboundConnectionHandler + router router.Router } // NewPoint returns a new Point server based on given configuration. @@ -65,6 +68,34 @@ func NewPoint(pConfig config.PointConfig) (*Point, error) { } } + outboundDetours := pConfig.OutboundDetours() + if len(outboundDetours) > 0 { + vpoint.odh = make(map[config.DetourTag]connhandler.OutboundConnectionHandler) + for _, detourConfig := range outboundDetours { + detourFactory := connhandler.GetOutboundConnectionHandlerFactory(detourConfig.Protocol()) + if detourFactory == nil { + log.Error("Unknown detour outbound connection handler factory %s", detourConfig.Protocol()) + return nil, config.BadConfiguration + } + detourHandler, err := detourFactory.Create(detourConfig.Settings()) + if err != nil { + log.Error("Failed to create detour outbound connection handler: %v", err) + return nil, err + } + vpoint.odh[detourConfig.Tag()] = detourHandler + } + } + + routerConfig := pConfig.RouterConfig() + if routerConfig != nil { + r, err := router.CreateRouter(routerConfig.Strategy(), routerConfig.Settings()) + if err != nil { + log.Error("Failed to create router: %v", err) + return nil, config.BadConfiguration + } + vpoint.router = r + } + return vpoint, nil } @@ -100,6 +131,19 @@ func (vp *Point) Start() error { func (p *Point) DispatchToOutbound(packet v2net.Packet) ray.InboundRay { direct := ray.NewRay() + dest := packet.Destination() + + if p.router != nil { + tag, err := p.router.TakeDetour(dest) + if err == nil { + handler, found := p.odh[tag] + if found { + go handler.Dispatch(packet, direct) + return direct + } + } + } + go p.och.Dispatch(packet, direct) return direct } diff --git a/app/router/router.go b/app/router/router.go index 62c18c1ce..306021a62 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -12,7 +12,7 @@ var ( ) type Router interface { - TakeDetour(v2net.Destination) (*config.DetourTag, error) + TakeDetour(v2net.Destination) (config.DetourTag, error) } type RouterFactory interface { diff --git a/app/router/rules/config/json/rules.go b/app/router/rules/config/json/rules.go index 967b27c99..e0e704b65 100644 --- a/app/router/rules/config/json/rules.go +++ b/app/router/rules/config/json/rules.go @@ -10,9 +10,8 @@ type Rule struct { OutboundTag string `json:"outboundTag"` } -func (this *Rule) Tag() *config.DetourTag { - detourTag := config.DetourTag(this.OutboundTag) - return &detourTag +func (this *Rule) Tag() config.DetourTag { + return config.DetourTag(this.OutboundTag) } func (this *Rule) Apply(dest v2net.Destination) bool { diff --git a/app/router/rules/config/rules.go b/app/router/rules/config/rules.go index 355650bd5..435f4fdf8 100644 --- a/app/router/rules/config/rules.go +++ b/app/router/rules/config/rules.go @@ -6,6 +6,6 @@ import ( ) type Rule interface { - Tag() *config.DetourTag + Tag() config.DetourTag Apply(dest v2net.Destination) bool } diff --git a/app/router/rules/router.go b/app/router/rules/router.go index 33fc147eb..5d372b601 100644 --- a/app/router/rules/router.go +++ b/app/router/rules/router.go @@ -11,21 +11,23 @@ import ( ) var ( - InvalidRule = errors.New("Invalid Rule") - EmptyTag = pointconfig.DetourTag("") + InvalidRule = errors.New("Invalid Rule") + NoRuleApplicable = errors.New("No rule applicable") + + EmptyTag = pointconfig.DetourTag("") ) type Router struct { rules []config.Rule } -func (this *Router) TakeDetour(dest v2net.Destination) (*pointconfig.DetourTag, error) { +func (this *Router) TakeDetour(dest v2net.Destination) (pointconfig.DetourTag, error) { for _, rule := range this.rules { if rule.Apply(dest) { return rule.Tag(), nil } } - return &EmptyTag, nil + return EmptyTag, NoRuleApplicable } type RouterFactory struct {