From 292d7cc353dd02affe641eb5547cf0e95f53712f Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Wed, 10 Jan 2018 12:22:37 +0100 Subject: [PATCH] massive refactoring for interoperability --- app/app.go | 2 - app/dispatcher/{impl => }/default.go | 53 +++--- app/dispatcher/dispatcher.go | 20 +-- app/dispatcher/errors.generated.go | 5 + app/dispatcher/impl/errors.generated.go | 7 - app/dispatcher/{impl => }/sniffer.go | 2 +- app/dispatcher/{impl => }/sniffer_test.go | 5 +- app/dns/nameserver.go | 4 +- app/dns/server.go | 58 +++---- app/dns/server_test.go | 60 +++---- app/policy/config.go | 16 ++ app/{ => policy}/errors.generated.go | 4 +- app/policy/manager.go | 61 +++++++ app/policy/manager/manager.go | 68 -------- app/policy/policy.go | 19 +-- app/proxyman/config.go | 17 -- app/proxyman/config.pb.go | 187 ++++++-------------- app/proxyman/config.proto | 23 --- app/proxyman/errors.generated.go | 4 +- app/proxyman/inbound/always.go | 8 +- app/proxyman/inbound/dynamic.go | 6 +- app/proxyman/inbound/inbound.go | 85 +++++----- app/proxyman/inbound/worker.go | 6 +- app/proxyman/mux/mux.go | 27 ++- app/proxyman/outbound/handler.go | 38 +++-- app/proxyman/outbound/handler_test.go | 15 ++ app/proxyman/outbound/outbound.go | 42 ++--- app/proxyman/proxyman.go | 44 ----- app/router/router.go | 61 +++---- app/router/router_test.go | 39 +++-- app/space.go | 132 --------------- common/interfaces.go | 10 ++ common/protocol/user.pb.go | 2 +- common/router/dispatcher.go | 12 ++ common/router/router.go | 53 ++++++ config.pb.go | 152 ++++++++++++++--- config.proto | 27 ++- context.go | 17 ++ dns.go | 57 +++++++ main/distro/all/all.go | 4 +- network.go | 165 ++++++++++++++++++ policy.go | 117 +++++++++++++ proxy/dokodemo/dokodemo.go | 61 +++---- proxy/freedom/freedom.go | 58 +++---- proxy/http/server.go | 49 +++--- proxy/proxy.go | 4 +- proxy/shadowsocks/client.go | 29 ++-- proxy/shadowsocks/server.go | 44 ++--- proxy/socks/server.go | 50 +++--- proxy/vmess/inbound/inbound.go | 55 +++--- proxy/vmess/outbound/outbound.go | 34 ++-- router.go | 118 +++++++++++++ testing/scenarios/common.go | 11 ++ testing/scenarios/dns_test.go | 4 +- testing/scenarios/dokodemo_test.go | 16 +- testing/scenarios/feature_test.go | 44 ++--- testing/scenarios/http_test.go | 16 +- testing/scenarios/shadowsocks_test.go | 52 +++--- testing/scenarios/socks_test.go | 20 +-- testing/scenarios/tls_test.go | 24 +-- testing/scenarios/transport_test.go | 8 +- testing/scenarios/vmess_test.go | 72 ++++---- transport/internet/config.pb.go | 5 +- transport/internet/udp/dispatcher.go | 6 +- v2ray.go | 197 ++++++++++++---------- v2ray_test.go | 4 +- 66 files changed, 1515 insertions(+), 1200 deletions(-) rename app/dispatcher/{impl => }/default.go (70%) create mode 100644 app/dispatcher/errors.generated.go delete mode 100644 app/dispatcher/impl/errors.generated.go rename app/dispatcher/{impl => }/sniffer.go (99%) rename app/dispatcher/{impl => }/sniffer_test.go (99%) rename app/{ => policy}/errors.generated.go (64%) create mode 100644 app/policy/manager.go delete mode 100644 app/policy/manager/manager.go create mode 100644 app/proxyman/outbound/handler_test.go delete mode 100644 app/space.go create mode 100644 common/interfaces.go create mode 100644 common/router/dispatcher.go create mode 100644 common/router/router.go create mode 100644 context.go create mode 100644 dns.go create mode 100644 network.go create mode 100644 policy.go create mode 100644 router.go diff --git a/app/app.go b/app/app.go index c688df1e7..4879f7a48 100644 --- a/app/app.go +++ b/app/app.go @@ -1,3 +1 @@ package app - -//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg app -path App diff --git a/app/dispatcher/impl/default.go b/app/dispatcher/default.go similarity index 70% rename from app/dispatcher/impl/default.go rename to app/dispatcher/default.go index 22cc0f59e..5f103a1f1 100644 --- a/app/dispatcher/impl/default.go +++ b/app/dispatcher/default.go @@ -1,4 +1,4 @@ -package impl +package dispatcher //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg impl -path App,Dispatcher,Default @@ -6,10 +6,8 @@ import ( "context" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/app/proxyman" - "v2ray.com/core/app/router" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -21,31 +19,27 @@ var ( errSniffingTimeout = newError("timeout on sniffing") ) -var ( - _ app.Application = (*DefaultDispatcher)(nil) -) - // DefaultDispatcher is a default implementation of Dispatcher. type DefaultDispatcher struct { - ohm proxyman.OutboundHandlerManager - router *router.Router + ohm core.OutboundHandlerManager + router core.Router } // NewDefaultDispatcher create a new DefaultDispatcher. -func NewDefaultDispatcher(ctx context.Context, config *dispatcher.Config) (*DefaultDispatcher, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") +func NewDefaultDispatcher(ctx context.Context, config *Config) (*DefaultDispatcher, error) { + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context.") + } + + d := &DefaultDispatcher{ + ohm: v.OutboundHandlerManager(), + router: v.Router(), + } + + if err := v.RegisterFeature((*core.Dispatcher)(nil), d); err != nil { + return nil, newError("unable to register Dispatcher") } - d := &DefaultDispatcher{} - space.On(app.SpaceInitializing, func(interface{}) error { - d.ohm = proxyman.OutboundHandlerManagerFromSpace(space) - if d.ohm == nil { - return newError("OutboundHandlerManager is not found in the space") - } - d.router = router.FromSpace(space) - return nil - }) return d, nil } @@ -57,12 +51,7 @@ func (*DefaultDispatcher) Start() error { // Close implements app.Application. func (*DefaultDispatcher) Close() {} -// Interface implements app.Application. -func (*DefaultDispatcher) Interface() interface{} { - return (*dispatcher.Interface)(nil) -} - -// Dispatch implements Dispatcher.Interface. +// Dispatch implements core.Dispatcher. func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (ray.InboundRay, error) { if !destination.IsValid() { panic("Dispatcher: Invalid destination.") @@ -120,7 +109,7 @@ func snifer(ctx context.Context, sniferList []proxyman.KnownProtocols, outbound func (d *DefaultDispatcher) routedDispatch(ctx context.Context, outbound ray.OutboundRay, destination net.Destination) { dispatcher := d.ohm.GetDefaultHandler() if d.router != nil { - if tag, err := d.router.TakeDetour(ctx); err == nil { + if tag, err := d.router.PickRoute(ctx); err == nil { if handler := d.ohm.GetHandler(tag); handler != nil { newError("taking detour [", tag, "] for [", destination, "]").WriteToLog() dispatcher = handler @@ -135,7 +124,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, outbound ray.Out } func init() { - common.Must(common.RegisterConfig((*dispatcher.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { - return NewDefaultDispatcher(ctx, config.(*dispatcher.Config)) + common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return NewDefaultDispatcher(ctx, config.(*Config)) })) } diff --git a/app/dispatcher/dispatcher.go b/app/dispatcher/dispatcher.go index 67b6486f1..83888b94f 100644 --- a/app/dispatcher/dispatcher.go +++ b/app/dispatcher/dispatcher.go @@ -1,21 +1,3 @@ package dispatcher -import ( - "context" - - "v2ray.com/core/app" - "v2ray.com/core/common/net" - "v2ray.com/core/transport/ray" -) - -// Interface dispatch a packet and possibly further network payload to its destination. -type Interface interface { - Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error) -} - -func FromSpace(space app.Space) Interface { - if app := space.GetApplication((*Interface)(nil)); app != nil { - return app.(Interface) - } - return nil -} +//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg dispatcher -path App,Dispatcher diff --git a/app/dispatcher/errors.generated.go b/app/dispatcher/errors.generated.go new file mode 100644 index 000000000..204f6d572 --- /dev/null +++ b/app/dispatcher/errors.generated.go @@ -0,0 +1,5 @@ +package dispatcher + +import "v2ray.com/core/common/errors" + +func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("App", "Dispatcher") } diff --git a/app/dispatcher/impl/errors.generated.go b/app/dispatcher/impl/errors.generated.go deleted file mode 100644 index 885ba26d0..000000000 --- a/app/dispatcher/impl/errors.generated.go +++ /dev/null @@ -1,7 +0,0 @@ -package impl - -import "v2ray.com/core/common/errors" - -func newError(values ...interface{}) *errors.Error { - return errors.New(values...).Path("App", "Dispatcher", "Default") -} diff --git a/app/dispatcher/impl/sniffer.go b/app/dispatcher/sniffer.go similarity index 99% rename from app/dispatcher/impl/sniffer.go rename to app/dispatcher/sniffer.go index ba4add252..a02d81054 100644 --- a/app/dispatcher/impl/sniffer.go +++ b/app/dispatcher/sniffer.go @@ -1,4 +1,4 @@ -package impl +package dispatcher import ( "bytes" diff --git a/app/dispatcher/impl/sniffer_test.go b/app/dispatcher/sniffer_test.go similarity index 99% rename from app/dispatcher/impl/sniffer_test.go rename to app/dispatcher/sniffer_test.go index 9ae7eac8b..1ac11f1b9 100644 --- a/app/dispatcher/impl/sniffer_test.go +++ b/app/dispatcher/sniffer_test.go @@ -1,11 +1,10 @@ -package impl_test +package dispatcher_test import ( "testing" + . "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/proxyman" - - . "v2ray.com/core/app/dispatcher/impl" . "v2ray.com/ext/assert" ) diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index 785739ea1..aef28064f 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -6,7 +6,7 @@ import ( "time" "github.com/miekg/dns" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/common/buf" "v2ray.com/core/common/dice" "v2ray.com/core/common/net" @@ -48,7 +48,7 @@ type UDPNameServer struct { nextCleanup time.Time } -func NewUDPNameServer(address net.Destination, dispatcher dispatcher.Interface) *UDPNameServer { +func NewUDPNameServer(address net.Destination, dispatcher core.Dispatcher) *UDPNameServer { s := &UDPNameServer{ address: address, requests: make(map[uint16]*PendingRequest), diff --git a/app/dns/server.go b/app/dns/server.go index d8494e455..c26c7985c 100644 --- a/app/dns/server.go +++ b/app/dns/server.go @@ -1,6 +1,6 @@ package dns -//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg server -path App,DNS,Server +//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg dns -path App,DNS import ( "context" @@ -8,8 +8,7 @@ import ( "time" dnsmsg "github.com/miekg/dns" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/net" ) @@ -41,39 +40,38 @@ type Server struct { } func New(ctx context.Context, config *Config) (*Server, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") - } server := &Server{ records: make(map[string]*DomainRecord), servers: make([]NameServer, len(config.NameServers)), hosts: config.GetInternalHosts(), } - space.On(app.SpaceInitializing, func(interface{}) error { - disp := dispatcher.FromSpace(space) - if disp == nil { - return newError("dispatcher is not found in the space") - } - for idx, destPB := range config.NameServers { - address := destPB.Address.AsAddress() - if address.Family().IsDomain() && address.Domain() == "localhost" { - server.servers[idx] = &LocalNameServer{} - } else { - dest := destPB.AsDestination() - if dest.Network == net.Network_Unknown { - dest.Network = net.Network_UDP - } - if dest.Network == net.Network_UDP { - server.servers[idx] = NewUDPNameServer(dest, disp) - } + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context.") + } + + if err := v.RegisterFeature((*core.DNSClient)(nil), server); err != nil { + return nil, newError("unable to register DNSClient.").Base(err) + } + + for idx, destPB := range config.NameServers { + address := destPB.Address.AsAddress() + if address.Family().IsDomain() && address.Domain() == "localhost" { + server.servers[idx] = &LocalNameServer{} + } else { + dest := destPB.AsDestination() + if dest.Network == net.Network_Unknown { + dest.Network = net.Network_UDP + } + if dest.Network == net.Network_UDP { + server.servers[idx] = NewUDPNameServer(dest, v.Dispatcher()) } } - if len(config.NameServers) == 0 { - server.servers = append(server.servers, &LocalNameServer{}) - } - return nil - }) + } + if len(config.NameServers) == 0 { + server.servers = append(server.servers, &LocalNameServer{}) + } + return server, nil } @@ -82,12 +80,10 @@ func (*Server) Interface() interface{} { } func (s *Server) Start() error { - net.RegisterIPResolver(s) return nil } func (*Server) Close() { - net.RegisterIPResolver(net.SystemIPResolver()) } func (s *Server) GetCached(domain string) []net.IP { diff --git a/app/dns/server_test.go b/app/dns/server_test.go index d773f8271..5b0a21805 100644 --- a/app/dns/server_test.go +++ b/app/dns/server_test.go @@ -1,18 +1,14 @@ package dns_test import ( - "context" "testing" - "v2ray.com/core/app" + "v2ray.com/core" "v2ray.com/core/app/dispatcher" - _ "v2ray.com/core/app/dispatcher/impl" . "v2ray.com/core/app/dns" - "v2ray.com/core/app/policy" - _ "v2ray.com/core/app/policy/manager" "v2ray.com/core/app/proxyman" + "v2ray.com/core/app/policy" _ "v2ray.com/core/app/proxyman/outbound" - "v2ray.com/core/common" "v2ray.com/core/common/net" "v2ray.com/core/common/serial" "v2ray.com/core/proxy/freedom" @@ -54,50 +50,50 @@ func TestUDPServer(t *testing.T) { go dnsServer.ListenAndServe() - config := &Config{ - NameServers: []*net.Endpoint{ - { - Network: net.Network_UDP, - Address: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, + config := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&Config{ + NameServers: []*net.Endpoint{ + { + Network: net.Network_UDP, + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, + }, + }, + Port: uint32(port), }, }, - Port: uint32(port), + }), + serial.ToTypedMessage(&dispatcher.Config{}), + serial.ToTypedMessage(&proxyman.OutboundConfig{}), + serial.ToTypedMessage(&policy.Config{}), + }, + Outbound: []*core.OutboundHandlerConfig{ + &core.OutboundHandlerConfig{ + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, } - ctx := context.Background() - space := app.NewSpace() + v, err := core.New(config) + assert(err, IsNil) - ctx = app.ContextWithSpace(ctx, space) - common.Must(app.AddApplicationToSpace(ctx, config)) - common.Must(app.AddApplicationToSpace(ctx, &dispatcher.Config{})) - common.Must(app.AddApplicationToSpace(ctx, &proxyman.OutboundConfig{})) - common.Must(app.AddApplicationToSpace(ctx, &policy.Config{})) + client := v.DNSClient() - om := proxyman.OutboundHandlerManagerFromSpace(space) - om.AddHandler(ctx, &proxyman.OutboundHandlerConfig{ - ProxySettings: serial.ToTypedMessage(&freedom.Config{}), - }) - - common.Must(space.Initialize()) - common.Must(space.Start()) - - ips, err := net.LookupIP("google.com") + ips, err := client.LookupIP("google.com") assert(err, IsNil) assert(len(ips), Equals, 1) assert([]byte(ips[0]), Equals, []byte{8, 8, 8, 8}) - ips, err = net.LookupIP("facebook.com") + ips, err = client.LookupIP("facebook.com") assert(err, IsNil) assert(len(ips), Equals, 1) assert([]byte(ips[0]), Equals, []byte{9, 9, 9, 9}) dnsServer.Shutdown() - ips, err = net.LookupIP("google.com") + ips, err = client.LookupIP("google.com") assert(err, IsNil) assert(len(ips), Equals, 1) assert([]byte(ips[0]), Equals, []byte{8, 8, 8, 8}) diff --git a/app/policy/config.go b/app/policy/config.go index 350d0751b..4d2f9452d 100644 --- a/app/policy/config.go +++ b/app/policy/config.go @@ -2,10 +2,15 @@ package policy import ( "time" + + "v2ray.com/core" ) // Duration converts Second to time.Duration. func (s *Second) Duration() time.Duration { + if s == nil { + return 0 + } return time.Second * time.Duration(s.Value) } @@ -26,3 +31,14 @@ func (p *Policy) OverrideWith(another *Policy) { } } } + +func (p *Policy) ToCorePolicy() core.Policy { + var cp core.Policy + if p.Timeout != nil { + cp.Timeouts.ConnectionIdle = p.Timeout.ConnectionIdle.Duration() + cp.Timeouts.Handshake = p.Timeout.Handshake.Duration() + cp.Timeouts.DownlinkOnly = p.Timeout.DownlinkOnly.Duration() + cp.Timeouts.UplinkOnly = p.Timeout.UplinkOnly.Duration() + } + return cp +} diff --git a/app/errors.generated.go b/app/policy/errors.generated.go similarity index 64% rename from app/errors.generated.go rename to app/policy/errors.generated.go index 3931523b9..3798ce91f 100644 --- a/app/errors.generated.go +++ b/app/policy/errors.generated.go @@ -1,5 +1,5 @@ -package app +package policy import "v2ray.com/core/common/errors" -func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("App") } +func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("App", "Policy") } diff --git a/app/policy/manager.go b/app/policy/manager.go new file mode 100644 index 000000000..d21eec4f2 --- /dev/null +++ b/app/policy/manager.go @@ -0,0 +1,61 @@ +package policy + +import ( + "context" + + "v2ray.com/core" + "v2ray.com/core/common" +) + +// Instance is an instance of Policy manager. +type Instance struct { + levels map[uint32]core.Policy +} + +// New creates new Policy manager instance. +func New(ctx context.Context, config *Config) (*Instance, error) { + m := &Instance{ + levels: make(map[uint32]core.Policy), + } + if len(config.Level) > 0 { + for lv, p := range config.Level { + dp := core.DefaultPolicy() + dp.OverrideWith(p.ToCorePolicy()) + m.levels[lv] = dp + } + } + + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context.") + } + + if err := v.RegisterFeature((*core.PolicyManager)(nil), m); err != nil { + return nil, newError("unable to register PolicyManager in core").Base(err).AtError() + } + + return m, nil +} + +// ForLevel implements core.PolicyManager. +func (m *Instance) ForLevel(level uint32) core.Policy { + if p, ok := m.levels[level]; ok { + return p + } + return core.DefaultPolicy() +} + +// Start implements app.Application.Start(). +func (m *Instance) Start() error { + return nil +} + +// Close implements app.Application.Close(). +func (m *Instance) Close() { +} + +func init() { + common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return New(ctx, config.(*Config)) + })) +} diff --git a/app/policy/manager/manager.go b/app/policy/manager/manager.go deleted file mode 100644 index e84c462b0..000000000 --- a/app/policy/manager/manager.go +++ /dev/null @@ -1,68 +0,0 @@ -package manager - -import ( - "context" - - "v2ray.com/core/app/policy" - "v2ray.com/core/common" -) - -// Instance is an instance of Policy manager. -type Instance struct { - levels map[uint32]*policy.Policy -} - -// New creates new Policy manager instance. -func New(ctx context.Context, config *policy.Config) (*Instance, error) { - levels := config.Level - if levels == nil { - levels = make(map[uint32]*policy.Policy) - } - for _, p := range levels { - g := global() - g.OverrideWith(p) - *p = g - } - return &Instance{ - levels: levels, - }, nil -} - -func global() policy.Policy { - return policy.Policy{ - Timeout: &policy.Policy_Timeout{ - Handshake: &policy.Second{Value: 4}, - ConnectionIdle: &policy.Second{Value: 300}, - UplinkOnly: &policy.Second{Value: 5}, - DownlinkOnly: &policy.Second{Value: 30}, - }, - } -} - -// GetPolicy implements policy.Manager. -func (m *Instance) GetPolicy(level uint32) policy.Policy { - if p, ok := m.levels[level]; ok { - return *p - } - return global() -} - -// Start implements app.Application.Start(). -func (m *Instance) Start() error { - return nil -} - -// Close implements app.Application.Close(). -func (m *Instance) Close() { -} - -// Interface implement app.Application.Interface(). -func (m *Instance) Interface() interface{} { - return (*policy.Manager)(nil) -} - -func init() { - common.Must(common.RegisterConfig((*policy.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { - return New(ctx, config.(*policy.Config)) - })) -} diff --git a/app/policy/policy.go b/app/policy/policy.go index f67e736e9..32554afee 100644 --- a/app/policy/policy.go +++ b/app/policy/policy.go @@ -1,20 +1,3 @@ package policy -import ( - "v2ray.com/core/app" -) - -// Manager is an utility to manage policy per user level. -type Manager interface { - // GetPolicy returns the Policy for the given user level. - GetPolicy(level uint32) Policy -} - -// FromSpace returns the policy.Manager in a space. -func FromSpace(space app.Space) Manager { - app := space.GetApplication((*Manager)(nil)) - if app == nil { - return nil - } - return app.(Manager) -} +//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg policy -path App,Policy diff --git a/app/proxyman/config.go b/app/proxyman/config.go index 9eae4e3fa..6f20ba489 100644 --- a/app/proxyman/config.go +++ b/app/proxyman/config.go @@ -1,11 +1,5 @@ package proxyman -import ( - "context" - - "v2ray.com/core/proxy" -) - func (s *AllocationStrategy) GetConcurrencyValue() uint32 { if s == nil || s.Concurrency == nil { return 3 @@ -19,14 +13,3 @@ func (s *AllocationStrategy) GetRefreshValue() uint32 { } return s.Refresh.Value } - -func (c *OutboundHandlerConfig) GetProxyHandler(ctx context.Context) (proxy.Outbound, error) { - if c == nil { - return nil, newError("OutboundHandlerConfig is nil") - } - config, err := c.ProxySettings.GetInstance() - if err != nil { - return nil, err - } - return proxy.CreateOutboundHandler(ctx, config) -} diff --git a/app/proxyman/config.pb.go b/app/proxyman/config.pb.go index 51df28603..3a64376e0 100644 --- a/app/proxyman/config.pb.go +++ b/app/proxyman/config.pb.go @@ -3,7 +3,6 @@ package proxyman import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" -import v2ray_core_common_serial "v2ray.com/core/common/serial" import v2ray_core_common_net "v2ray.com/core/common/net" import v2ray_core_common_net1 "v2ray.com/core/common/net" import v2ray_core_transport_internet "v2ray.com/core/transport/internet" @@ -211,45 +210,13 @@ func (m *ReceiverConfig) GetDomainOverride() []KnownProtocols { return nil } -type InboundHandlerConfig struct { - Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"` - ReceiverSettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=receiver_settings,json=receiverSettings" json:"receiver_settings,omitempty"` - ProxySettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"` -} - -func (m *InboundHandlerConfig) Reset() { *m = InboundHandlerConfig{} } -func (m *InboundHandlerConfig) String() string { return proto.CompactTextString(m) } -func (*InboundHandlerConfig) ProtoMessage() {} -func (*InboundHandlerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *InboundHandlerConfig) GetTag() string { - if m != nil { - return m.Tag - } - return "" -} - -func (m *InboundHandlerConfig) GetReceiverSettings() *v2ray_core_common_serial.TypedMessage { - if m != nil { - return m.ReceiverSettings - } - return nil -} - -func (m *InboundHandlerConfig) GetProxySettings() *v2ray_core_common_serial.TypedMessage { - if m != nil { - return m.ProxySettings - } - return nil -} - type OutboundConfig struct { } func (m *OutboundConfig) Reset() { *m = OutboundConfig{} } func (m *OutboundConfig) String() string { return proto.CompactTextString(m) } func (*OutboundConfig) ProtoMessage() {} -func (*OutboundConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*OutboundConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } type SenderConfig struct { // Send traffic through the given IP. Only IP is allowed. @@ -262,7 +229,7 @@ type SenderConfig struct { func (m *SenderConfig) Reset() { *m = SenderConfig{} } func (m *SenderConfig) String() string { return proto.CompactTextString(m) } func (*SenderConfig) ProtoMessage() {} -func (*SenderConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*SenderConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *SenderConfig) GetVia() *v2ray_core_common_net.IPOrDomain { if m != nil { @@ -292,54 +259,6 @@ func (m *SenderConfig) GetMultiplexSettings() *MultiplexingConfig { return nil } -type OutboundHandlerConfig struct { - Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"` - SenderSettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=sender_settings,json=senderSettings" json:"sender_settings,omitempty"` - ProxySettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"` - Expire int64 `protobuf:"varint,4,opt,name=expire" json:"expire,omitempty"` - Comment string `protobuf:"bytes,5,opt,name=comment" json:"comment,omitempty"` -} - -func (m *OutboundHandlerConfig) Reset() { *m = OutboundHandlerConfig{} } -func (m *OutboundHandlerConfig) String() string { return proto.CompactTextString(m) } -func (*OutboundHandlerConfig) ProtoMessage() {} -func (*OutboundHandlerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } - -func (m *OutboundHandlerConfig) GetTag() string { - if m != nil { - return m.Tag - } - return "" -} - -func (m *OutboundHandlerConfig) GetSenderSettings() *v2ray_core_common_serial.TypedMessage { - if m != nil { - return m.SenderSettings - } - return nil -} - -func (m *OutboundHandlerConfig) GetProxySettings() *v2ray_core_common_serial.TypedMessage { - if m != nil { - return m.ProxySettings - } - return nil -} - -func (m *OutboundHandlerConfig) GetExpire() int64 { - if m != nil { - return m.Expire - } - return 0 -} - -func (m *OutboundHandlerConfig) GetComment() string { - if m != nil { - return m.Comment - } - return "" -} - type MultiplexingConfig struct { // Whether or not Mux is enabled. Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` @@ -350,7 +269,7 @@ type MultiplexingConfig struct { func (m *MultiplexingConfig) Reset() { *m = MultiplexingConfig{} } func (m *MultiplexingConfig) String() string { return proto.CompactTextString(m) } func (*MultiplexingConfig) ProtoMessage() {} -func (*MultiplexingConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*MultiplexingConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *MultiplexingConfig) GetEnabled() bool { if m != nil { @@ -372,10 +291,8 @@ func init() { proto.RegisterType((*AllocationStrategy_AllocationStrategyConcurrency)(nil), "v2ray.core.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency") proto.RegisterType((*AllocationStrategy_AllocationStrategyRefresh)(nil), "v2ray.core.app.proxyman.AllocationStrategy.AllocationStrategyRefresh") proto.RegisterType((*ReceiverConfig)(nil), "v2ray.core.app.proxyman.ReceiverConfig") - proto.RegisterType((*InboundHandlerConfig)(nil), "v2ray.core.app.proxyman.InboundHandlerConfig") proto.RegisterType((*OutboundConfig)(nil), "v2ray.core.app.proxyman.OutboundConfig") proto.RegisterType((*SenderConfig)(nil), "v2ray.core.app.proxyman.SenderConfig") - proto.RegisterType((*OutboundHandlerConfig)(nil), "v2ray.core.app.proxyman.OutboundHandlerConfig") proto.RegisterType((*MultiplexingConfig)(nil), "v2ray.core.app.proxyman.MultiplexingConfig") proto.RegisterEnum("v2ray.core.app.proxyman.KnownProtocols", KnownProtocols_name, KnownProtocols_value) proto.RegisterEnum("v2ray.core.app.proxyman.AllocationStrategy_Type", AllocationStrategy_Type_name, AllocationStrategy_Type_value) @@ -384,57 +301,49 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/app/proxyman/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 822 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xd1, 0x8e, 0xdb, 0x44, - 0x14, 0xad, 0xe3, 0x34, 0xc9, 0xde, 0xed, 0x7a, 0xdd, 0xa1, 0xd0, 0x10, 0x40, 0x0a, 0x01, 0xd1, - 0xa8, 0x20, 0xa7, 0xa4, 0xe2, 0x81, 0x27, 0x58, 0x76, 0x2b, 0x75, 0x81, 0x55, 0xcc, 0x24, 0xe2, - 0xa1, 0x42, 0xb2, 0x66, 0xed, 0xa9, 0x19, 0x61, 0xcf, 0x58, 0x33, 0x93, 0x74, 0xfd, 0x4b, 0x7c, - 0x05, 0x8f, 0x3c, 0xf0, 0x05, 0xfc, 0x0a, 0x2f, 0xc8, 0x9e, 0x71, 0x76, 0xb7, 0x49, 0x5a, 0x96, - 0xaa, 0x6f, 0x33, 0xc9, 0x39, 0xc7, 0x73, 0xcf, 0x3d, 0x77, 0x06, 0xc6, 0xab, 0xa9, 0x24, 0x65, - 0x10, 0x8b, 0x7c, 0x12, 0x0b, 0x49, 0x27, 0xa4, 0x28, 0x26, 0x85, 0x14, 0x17, 0x65, 0x4e, 0xf8, - 0x24, 0x16, 0xfc, 0x39, 0x4b, 0x83, 0x42, 0x0a, 0x2d, 0xd0, 0xfd, 0x06, 0x29, 0x69, 0x40, 0x8a, - 0x22, 0x68, 0x50, 0x83, 0x47, 0x2f, 0x49, 0xc4, 0x22, 0xcf, 0x05, 0x9f, 0x28, 0x2a, 0x19, 0xc9, - 0x26, 0xba, 0x2c, 0x68, 0x12, 0xe5, 0x54, 0x29, 0x92, 0x52, 0x23, 0x35, 0x78, 0xb0, 0x9d, 0xc1, - 0xa9, 0x9e, 0x90, 0x24, 0x91, 0x54, 0x29, 0x0b, 0xfc, 0x74, 0x37, 0xb0, 0x10, 0x52, 0x5b, 0x54, - 0xf0, 0x12, 0x4a, 0x4b, 0xc2, 0x55, 0xf5, 0xff, 0x84, 0x71, 0x4d, 0x65, 0x85, 0xbe, 0x5a, 0xc9, - 0xe8, 0x10, 0x0e, 0x4e, 0xf9, 0xb9, 0x58, 0xf2, 0xe4, 0xb8, 0xfe, 0x79, 0xf4, 0x87, 0x0b, 0xe8, - 0x28, 0xcb, 0x44, 0x4c, 0x34, 0x13, 0x7c, 0xae, 0x25, 0xd1, 0x34, 0x2d, 0xd1, 0x09, 0xb4, 0xab, - 0xd3, 0xf7, 0x9d, 0xa1, 0x33, 0xf6, 0xa6, 0x8f, 0x82, 0x1d, 0x06, 0x04, 0x9b, 0xd4, 0x60, 0x51, - 0x16, 0x14, 0xd7, 0x6c, 0xf4, 0x1b, 0xec, 0xc7, 0x82, 0xc7, 0x4b, 0x29, 0x29, 0x8f, 0xcb, 0x7e, - 0x6b, 0xe8, 0x8c, 0xf7, 0xa7, 0xa7, 0x37, 0x11, 0xdb, 0xfc, 0xe9, 0xf8, 0x52, 0x10, 0x5f, 0x55, - 0x47, 0x11, 0x74, 0x25, 0x7d, 0x2e, 0xa9, 0xfa, 0xb5, 0xef, 0xd6, 0x1f, 0x7a, 0xf2, 0x66, 0x1f, - 0xc2, 0x46, 0x0c, 0x37, 0xaa, 0x83, 0xaf, 0xe0, 0xa3, 0x57, 0x1e, 0x07, 0xdd, 0x83, 0xdb, 0x2b, - 0x92, 0x2d, 0x8d, 0x6b, 0x07, 0xd8, 0x6c, 0x06, 0x5f, 0xc2, 0xfb, 0x3b, 0xc5, 0xb7, 0x53, 0x46, - 0x5f, 0x40, 0xbb, 0x72, 0x11, 0x01, 0x74, 0x8e, 0xb2, 0x17, 0xa4, 0x54, 0xfe, 0xad, 0x6a, 0x8d, - 0x09, 0x4f, 0x44, 0xee, 0x3b, 0xe8, 0x0e, 0xf4, 0x9e, 0x5c, 0x54, 0xed, 0x25, 0x99, 0xdf, 0x1a, - 0xfd, 0xed, 0x82, 0x87, 0x69, 0x4c, 0xd9, 0x8a, 0x4a, 0xd3, 0x55, 0xf4, 0x0d, 0x40, 0x15, 0x82, - 0x48, 0x12, 0x9e, 0x1a, 0xed, 0xfd, 0xe9, 0xf0, 0xaa, 0x1d, 0x26, 0x4d, 0x01, 0xa7, 0x3a, 0x08, - 0x85, 0xd4, 0xb8, 0xc2, 0xe1, 0xbd, 0xa2, 0x59, 0xa2, 0xaf, 0xa1, 0x93, 0x31, 0xa5, 0x29, 0xb7, - 0x4d, 0xfb, 0x78, 0x07, 0xf9, 0x34, 0x9c, 0xc9, 0x13, 0x91, 0x13, 0xc6, 0xb1, 0x25, 0xa0, 0x5f, - 0xe0, 0x1d, 0xb2, 0xae, 0x37, 0x52, 0xb6, 0x60, 0xdb, 0x93, 0xcf, 0x6f, 0xd0, 0x13, 0x8c, 0xc8, - 0x66, 0x30, 0x17, 0x70, 0xa8, 0xb4, 0xa4, 0x24, 0x8f, 0x14, 0xd5, 0x9a, 0xf1, 0x54, 0xf5, 0xdb, - 0x9b, 0xca, 0xeb, 0x31, 0x08, 0x9a, 0x31, 0x08, 0xe6, 0x35, 0xcb, 0xf8, 0x83, 0x3d, 0xa3, 0x31, - 0xb7, 0x12, 0xe8, 0x5b, 0xf8, 0x50, 0x1a, 0x07, 0x23, 0x21, 0x59, 0xca, 0x38, 0xc9, 0xa2, 0x84, - 0x2a, 0xcd, 0x78, 0xfd, 0xf5, 0xfe, 0xed, 0xa1, 0x33, 0xee, 0xe1, 0x81, 0xc5, 0xcc, 0x2c, 0xe4, - 0xe4, 0x12, 0x81, 0x42, 0x38, 0x4c, 0x6a, 0x1f, 0x22, 0xb1, 0xa2, 0x52, 0xb2, 0x84, 0xf6, 0xbb, - 0x43, 0x77, 0xec, 0x4d, 0x1f, 0xec, 0xac, 0xf8, 0x07, 0x2e, 0x5e, 0xf0, 0xb0, 0x1a, 0xcb, 0x58, - 0x64, 0x0a, 0x7b, 0x86, 0x3f, 0xb3, 0xf4, 0xef, 0xdb, 0xbd, 0x8e, 0xdf, 0x1d, 0xfd, 0xe5, 0xc0, - 0x3d, 0x3b, 0xb1, 0x4f, 0x09, 0x4f, 0xb2, 0x75, 0x8b, 0x7d, 0x70, 0x35, 0x49, 0xeb, 0xde, 0xee, - 0xe1, 0x6a, 0x89, 0xe6, 0x70, 0xd7, 0x1e, 0x50, 0x5e, 0x9a, 0x63, 0xda, 0xf7, 0xd9, 0x96, 0xf6, - 0x99, 0x4b, 0xaa, 0x1e, 0xd7, 0xe4, 0xcc, 0xdc, 0x51, 0xd8, 0x6f, 0x04, 0xd6, 0xce, 0x9c, 0x81, - 0x57, 0x1f, 0xf8, 0x52, 0xd1, 0xbd, 0x91, 0xe2, 0x41, 0xcd, 0x6e, 0xe4, 0x46, 0x3e, 0x78, 0xb3, - 0xa5, 0xbe, 0x7a, 0x01, 0xfd, 0xd9, 0x82, 0x3b, 0x73, 0xca, 0x93, 0x75, 0x61, 0x8f, 0xc1, 0x5d, - 0x31, 0x62, 0x43, 0xfb, 0x1f, 0x72, 0x57, 0xa1, 0xb7, 0xc5, 0xa2, 0xf5, 0xe6, 0xb1, 0xf8, 0x69, - 0x47, 0xf1, 0x0f, 0x5f, 0x23, 0x1a, 0x56, 0x24, 0xab, 0x79, 0xdd, 0x00, 0xf4, 0x0c, 0x50, 0xbe, - 0xcc, 0x34, 0x2b, 0x32, 0x7a, 0xf1, 0xca, 0x08, 0x5f, 0x8b, 0xca, 0x59, 0x43, 0x61, 0x3c, 0xb5, - 0xba, 0x77, 0xd7, 0x32, 0x6b, 0x73, 0xff, 0x71, 0xe0, 0xdd, 0xc6, 0xdd, 0xd7, 0x85, 0x65, 0x06, - 0x87, 0xaa, 0x76, 0xfd, 0xff, 0x46, 0xc5, 0x33, 0xf4, 0xb7, 0x14, 0x14, 0xf4, 0x1e, 0x74, 0xe8, - 0x45, 0xc1, 0x24, 0xad, 0xbd, 0x71, 0xb1, 0xdd, 0xa1, 0x3e, 0x74, 0x2b, 0x11, 0xca, 0x75, 0x3d, - 0x94, 0x7b, 0xb8, 0xd9, 0x8e, 0x42, 0x40, 0x9b, 0x36, 0x55, 0x78, 0xca, 0xc9, 0x79, 0x46, 0x93, - 0xba, 0xfa, 0x1e, 0x6e, 0xb6, 0x68, 0xb8, 0xf9, 0x38, 0x1d, 0x5c, 0x7b, 0x51, 0x1e, 0x7e, 0x02, - 0xde, 0xf5, 0x19, 0x45, 0x3d, 0x68, 0x3f, 0x5d, 0x2c, 0x42, 0xff, 0x16, 0xea, 0x82, 0xbb, 0xf8, - 0x71, 0xee, 0x3b, 0xdf, 0x1d, 0xc3, 0x07, 0xb1, 0xc8, 0x77, 0x75, 0x2e, 0x74, 0x9e, 0xf5, 0x9a, - 0xf5, 0xef, 0xad, 0xfb, 0x3f, 0x4f, 0x31, 0x29, 0x83, 0xe3, 0x0a, 0x75, 0x54, 0x14, 0x26, 0x27, - 0x39, 0xe1, 0xe7, 0x9d, 0xfa, 0x75, 0x7e, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x25, 0xdf, - 0x6a, 0xb2, 0x93, 0x08, 0x00, 0x00, + // 691 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x5d, 0x6f, 0xd3, 0x3a, + 0x1c, 0xc6, 0x97, 0xb6, 0x6b, 0x7b, 0xfe, 0x5b, 0xb3, 0x1c, 0x9f, 0x23, 0x2d, 0xa7, 0x07, 0xa4, + 0x52, 0x90, 0x56, 0x0d, 0x94, 0x40, 0x27, 0x2e, 0xb8, 0x82, 0xd1, 0x4d, 0x62, 0xbc, 0xa8, 0xc1, + 0xad, 0xb8, 0x98, 0x90, 0x22, 0x2f, 0xf1, 0x8a, 0x45, 0x62, 0x47, 0x8e, 0xdb, 0x2d, 0x5f, 0x89, + 0x4f, 0xc1, 0x25, 0x9f, 0x81, 0x4f, 0x83, 0xf2, 0xd6, 0x75, 0xeb, 0x3a, 0x98, 0x76, 0xe7, 0xa6, + 0xcf, 0xf3, 0xb3, 0xfd, 0x3c, 0xb6, 0xa1, 0x37, 0xeb, 0x4b, 0x92, 0x58, 0x9e, 0x08, 0x6d, 0x4f, + 0x48, 0x6a, 0x93, 0x28, 0xb2, 0x23, 0x29, 0xce, 0x93, 0x90, 0x70, 0xdb, 0x13, 0xfc, 0x94, 0x4d, + 0xac, 0x48, 0x0a, 0x25, 0xd0, 0x76, 0xa9, 0x94, 0xd4, 0x22, 0x51, 0x64, 0x95, 0xaa, 0xf6, 0xce, + 0x15, 0x84, 0x27, 0xc2, 0x50, 0x70, 0x9b, 0x53, 0x65, 0x13, 0xdf, 0x97, 0x34, 0x8e, 0x73, 0x42, + 0xfb, 0xd1, 0x6a, 0x61, 0x24, 0xa4, 0x2a, 0x54, 0xd6, 0x15, 0x95, 0x92, 0x84, 0xc7, 0xe9, 0xff, + 0x36, 0xe3, 0x8a, 0xca, 0x54, 0xbd, 0xb8, 0xae, 0xee, 0x16, 0xb4, 0x8e, 0xf8, 0x89, 0x98, 0x72, + 0x7f, 0x90, 0x7d, 0xee, 0x7e, 0xaf, 0x02, 0xda, 0x0f, 0x02, 0xe1, 0x11, 0xc5, 0x04, 0x1f, 0x29, + 0x49, 0x14, 0x9d, 0x24, 0xe8, 0x00, 0x6a, 0x2a, 0x89, 0xa8, 0xa9, 0x75, 0xb4, 0x9e, 0xde, 0x7f, + 0x6a, 0xad, 0xd8, 0x8e, 0xb5, 0x6c, 0xb5, 0xc6, 0x49, 0x44, 0x71, 0xe6, 0x46, 0x5f, 0x61, 0xc3, + 0x13, 0xdc, 0x9b, 0x4a, 0x49, 0xb9, 0x97, 0x98, 0x95, 0x8e, 0xd6, 0xdb, 0xe8, 0x1f, 0xdd, 0x06, + 0xb6, 0xfc, 0x69, 0x70, 0x01, 0xc4, 0x8b, 0x74, 0xe4, 0x42, 0x43, 0xd2, 0x53, 0x49, 0xe3, 0x2f, + 0x66, 0x35, 0x9b, 0xe8, 0xf0, 0x6e, 0x13, 0xe1, 0x1c, 0x86, 0x4b, 0x6a, 0xfb, 0x39, 0xdc, 0xbf, + 0x71, 0x39, 0xe8, 0x5f, 0x58, 0x9f, 0x91, 0x60, 0x9a, 0xa7, 0xd6, 0xc2, 0xf9, 0x8f, 0xf6, 0x33, + 0xf8, 0x6f, 0x25, 0xfc, 0x7a, 0x4b, 0xf7, 0x09, 0xd4, 0xd2, 0x14, 0x11, 0x40, 0x7d, 0x3f, 0x38, + 0x23, 0x49, 0x6c, 0xac, 0xa5, 0x63, 0x4c, 0xb8, 0x2f, 0x42, 0x43, 0x43, 0x9b, 0xd0, 0x3c, 0x3c, + 0x4f, 0xeb, 0x25, 0x81, 0x51, 0xe9, 0xfe, 0xac, 0x82, 0x8e, 0xa9, 0x47, 0xd9, 0x8c, 0xca, 0xbc, + 0x55, 0xf4, 0x12, 0x20, 0x3d, 0x04, 0xae, 0x24, 0x7c, 0x92, 0xb3, 0x37, 0xfa, 0x9d, 0xc5, 0x38, + 0xf2, 0xd3, 0x64, 0x71, 0xaa, 0x2c, 0x47, 0x48, 0x85, 0x53, 0x1d, 0xfe, 0x2b, 0x2a, 0x87, 0xe8, + 0x05, 0xd4, 0x03, 0x16, 0x2b, 0xca, 0x8b, 0xd2, 0x1e, 0xac, 0x30, 0x1f, 0x39, 0x43, 0x79, 0x20, + 0x42, 0xc2, 0x38, 0x2e, 0x0c, 0xe8, 0x33, 0xfc, 0x43, 0xe6, 0xfb, 0x75, 0xe3, 0x62, 0xc3, 0x45, + 0x27, 0x8f, 0x6f, 0xd1, 0x09, 0x46, 0x64, 0xf9, 0x60, 0x8e, 0x61, 0x2b, 0x56, 0x92, 0x92, 0xd0, + 0x8d, 0xa9, 0x52, 0x8c, 0x4f, 0x62, 0xb3, 0xb6, 0x4c, 0x9e, 0x5f, 0x03, 0xab, 0xbc, 0x06, 0xd6, + 0x28, 0x73, 0xe5, 0xf9, 0x60, 0x3d, 0x67, 0x8c, 0x0a, 0x04, 0x7a, 0x05, 0xf7, 0x64, 0x9e, 0xa0, + 0x2b, 0x24, 0x9b, 0x30, 0x4e, 0x02, 0xd7, 0xa7, 0xb1, 0x62, 0x3c, 0x9b, 0xdd, 0x5c, 0xef, 0x68, + 0xbd, 0x26, 0x6e, 0x17, 0x9a, 0x61, 0x21, 0x39, 0xb8, 0x50, 0x20, 0x07, 0xb6, 0xfc, 0x2c, 0x07, + 0x57, 0xcc, 0xa8, 0x94, 0xcc, 0xa7, 0x66, 0xa3, 0x53, 0xed, 0xe9, 0xfd, 0x9d, 0x95, 0x3b, 0x7e, + 0xc7, 0xc5, 0x19, 0x77, 0xd2, 0x6b, 0xe9, 0x89, 0x20, 0xc6, 0x7a, 0xee, 0x1f, 0x16, 0xf6, 0xb7, + 0xb5, 0x66, 0xdd, 0x68, 0x74, 0x0d, 0xd0, 0x87, 0x53, 0xb5, 0x78, 0x63, 0x7f, 0x54, 0x60, 0x73, + 0x44, 0xb9, 0x3f, 0x2f, 0x7b, 0x0f, 0xaa, 0x33, 0x46, 0x8a, 0x96, 0xff, 0xa0, 0xa8, 0x54, 0x7d, + 0x5d, 0x8e, 0x95, 0xbb, 0xe7, 0xf8, 0x11, 0xf4, 0x6c, 0x7b, 0x17, 0xd0, 0xbc, 0xf6, 0xdd, 0xdf, + 0x40, 0x9d, 0xd4, 0x54, 0x30, 0x5b, 0x19, 0x61, 0x8e, 0x3c, 0x06, 0x14, 0x4e, 0x03, 0xc5, 0xa2, + 0x80, 0x9e, 0xdf, 0xd8, 0xf9, 0xa5, 0x6c, 0x3f, 0x94, 0x16, 0xc6, 0x27, 0x05, 0xf7, 0xef, 0x39, + 0xa6, 0x64, 0x77, 0x1d, 0x40, 0xcb, 0x42, 0x64, 0x42, 0x83, 0x72, 0x72, 0x12, 0x50, 0x3f, 0xcb, + 0xb4, 0x89, 0xcb, 0x9f, 0xa8, 0xb3, 0xfc, 0x9e, 0xb5, 0x2e, 0x3d, 0x42, 0xbb, 0x0f, 0x41, 0xbf, + 0x5c, 0x2b, 0x6a, 0x42, 0xed, 0xcd, 0x78, 0xec, 0x18, 0x6b, 0xa8, 0x01, 0xd5, 0xf1, 0xfb, 0x91, + 0xa1, 0xbd, 0x1e, 0xc0, 0xff, 0x9e, 0x08, 0x57, 0xad, 0xdd, 0xd1, 0x8e, 0x9b, 0xe5, 0xf8, 0x5b, + 0x65, 0xfb, 0x53, 0x1f, 0x93, 0xc4, 0x1a, 0xa4, 0xaa, 0xfd, 0x28, 0xca, 0x93, 0x0a, 0x09, 0x3f, + 0xa9, 0x67, 0x0f, 0xfa, 0xde, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x77, 0x7f, 0xdc, 0x8e, 0x94, + 0x06, 0x00, 0x00, } diff --git a/app/proxyman/config.proto b/app/proxyman/config.proto index 6219db4fb..15f2171e0 100644 --- a/app/proxyman/config.proto +++ b/app/proxyman/config.proto @@ -6,7 +6,6 @@ option go_package = "proxyman"; option java_package = "com.v2ray.core.app.proxyman"; option java_multiple_files = true; -import "v2ray.com/core/common/serial/typed_message.proto"; import "v2ray.com/core/common/net/address.proto"; import "v2ray.com/core/common/net/port.proto"; import "v2ray.com/core/transport/internet/config.proto"; @@ -61,15 +60,6 @@ message ReceiverConfig { repeated KnownProtocols domain_override = 7; } -message InboundHandlerConfig { - // Tag of the inbound handler. - string tag = 1; - // Settings for how this inbound proxy is handled. Must be ReceiverConfig above. - v2ray.core.common.serial.TypedMessage receiver_settings = 2; - // Settings for inbound proxy. Must be one of the inbound proxies. - v2ray.core.common.serial.TypedMessage proxy_settings = 3; -} - message OutboundConfig { } @@ -82,19 +72,6 @@ message SenderConfig { MultiplexingConfig multiplex_settings = 4; } -message OutboundHandlerConfig { - // Tag of this outbound handler. - string tag = 1; - // Settings for how to dial connection for this outbound handler. Must be SenderConfig above. - v2ray.core.common.serial.TypedMessage sender_settings = 2; - // Settings for this outbound proxy. Must be one of the outbound proxies. - v2ray.core.common.serial.TypedMessage proxy_settings = 3; - // If not zero, this outbound will be expired in seconds. Not used for now. - int64 expire = 4; - // Comment of this outbound handler. Not used for now. - string comment = 5; -} - message MultiplexingConfig { // Whether or not Mux is enabled. bool enabled = 1; diff --git a/app/proxyman/errors.generated.go b/app/proxyman/errors.generated.go index b69ca4bc4..61b329269 100644 --- a/app/proxyman/errors.generated.go +++ b/app/proxyman/errors.generated.go @@ -2,6 +2,4 @@ package proxyman import "v2ray.com/core/common/errors" -func newError(values ...interface{}) *errors.Error { - return errors.New(values...).Path("App", "Proxyman") -} +func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("App", "Proxyman") } diff --git a/app/proxyman/inbound/always.go b/app/proxyman/inbound/always.go index 4d20739f4..7a49ce592 100644 --- a/app/proxyman/inbound/always.go +++ b/app/proxyman/inbound/always.go @@ -14,6 +14,7 @@ type AlwaysOnInboundHandler struct { proxy proxy.Inbound workers []worker mux *mux.Server + tag string } func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) { @@ -25,6 +26,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig * h := &AlwaysOnInboundHandler{ proxy: p, mux: mux.NewServer(ctx), + tag: tag, } nl := p.Network() @@ -80,10 +82,14 @@ func (h *AlwaysOnInboundHandler) Close() { } } -func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (proxy.Inbound, net.Port, int) { +func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) { if len(h.workers) == 0 { return nil, 0, 0 } w := h.workers[dice.Roll(len(h.workers))] return w.Proxy(), w.Port(), 9999 } + +func (h *AlwaysOnInboundHandler) Tag() string { + return h.tag +} diff --git a/app/proxyman/inbound/dynamic.go b/app/proxyman/inbound/dynamic.go index ca1aa9d0c..281f8eb63 100644 --- a/app/proxyman/inbound/dynamic.go +++ b/app/proxyman/inbound/dynamic.go @@ -163,7 +163,7 @@ func (h *DynamicInboundHandler) Close() { h.cancel() } -func (h *DynamicInboundHandler) GetRandomInboundProxy() (proxy.Inbound, net.Port, int) { +func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) { h.workerMutex.RLock() defer h.workerMutex.RUnlock() @@ -174,3 +174,7 @@ func (h *DynamicInboundHandler) GetRandomInboundProxy() (proxy.Inbound, net.Port expire := h.receiverConfig.AllocationStrategy.GetRefreshValue() - uint32(time.Since(h.lastRefresh)/time.Minute) return w.Proxy(), w.Port(), int(expire) } + +func (h *DynamicInboundHandler) Tag() string { + return h.tag +} diff --git a/app/proxyman/inbound/inbound.go b/app/proxyman/inbound/inbound.go index bedf07b2f..f52a4cdae 100644 --- a/app/proxyman/inbound/inbound.go +++ b/app/proxyman/inbound/inbound.go @@ -5,64 +5,41 @@ package inbound import ( "context" + "v2ray.com/core" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" ) // Manager is to manage all inbound handlers. type Manager struct { - handlers []proxyman.InboundHandler - taggedHandlers map[string]proxyman.InboundHandler + handlers []core.InboundHandler + taggedHandlers map[string]core.InboundHandler } func New(ctx context.Context, config *proxyman.InboundConfig) (*Manager, error) { - return &Manager{ - taggedHandlers: make(map[string]proxyman.InboundHandler), - }, nil + m := &Manager{ + taggedHandlers: make(map[string]core.InboundHandler), + } + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context") + } + if err := v.RegisterFeature((*core.InboundHandlerManager)(nil), m); err != nil { + return nil, newError("unable to register InboundHandlerManager").Base(err) + } + return m, nil } -func (m *Manager) AddHandler(ctx context.Context, config *proxyman.InboundHandlerConfig) error { - rawReceiverSettings, err := config.ReceiverSettings.GetInstance() - if err != nil { - return err - } - receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig) - if !ok { - return newError("not a ReceiverConfig").AtError() - } - proxySettings, err := config.ProxySettings.GetInstance() - if err != nil { - return err - } - var handler proxyman.InboundHandler - tag := config.Tag - allocStrategy := receiverSettings.AllocationStrategy - if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { - h, err := NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings) - if err != nil { - return err - } - handler = h - } else if allocStrategy.Type == proxyman.AllocationStrategy_Random { - h, err := NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings) - if err != nil { - return err - } - handler = h - } - - if handler == nil { - return newError("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError() - } - +func (m *Manager) AddHandler(ctx context.Context, handler core.InboundHandler) error { m.handlers = append(m.handlers, handler) + tag := handler.Tag() if len(tag) > 0 { m.taggedHandlers[tag] = handler } return nil } -func (m *Manager) GetHandler(ctx context.Context, tag string) (proxyman.InboundHandler, error) { +func (m *Manager) GetHandler(ctx context.Context, tag string) (core.InboundHandler, error) { handler, found := m.taggedHandlers[tag] if !found { return nil, newError("handler not found: ", tag) @@ -85,12 +62,36 @@ func (m *Manager) Close() { } } -func (m *Manager) Interface() interface{} { - return (*proxyman.InboundHandlerManager)(nil) +func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (core.InboundHandler, error) { + rawReceiverSettings, err := config.ReceiverSettings.GetInstance() + if err != nil { + return nil, err + } + receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig) + if !ok { + return nil, newError("not a ReceiverConfig").AtError() + } + proxySettings, err := config.ProxySettings.GetInstance() + if err != nil { + return nil, err + } + tag := config.Tag + allocStrategy := receiverSettings.AllocationStrategy + if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { + return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings) + } + + if allocStrategy.Type == proxyman.AllocationStrategy_Random { + return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings) + } + return nil, newError("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError() } func init() { common.Must(common.RegisterConfig((*proxyman.InboundConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { return New(ctx, config.(*proxyman.InboundConfig)) })) + common.Must(common.RegisterConfig((*core.InboundHandlerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return NewHandler(ctx, config.(*core.InboundHandlerConfig)) + })) } diff --git a/app/proxyman/inbound/worker.go b/app/proxyman/inbound/worker.go index 6fce64c8b..24cfc2653 100644 --- a/app/proxyman/inbound/worker.go +++ b/app/proxyman/inbound/worker.go @@ -7,7 +7,7 @@ import ( "sync/atomic" "time" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/app/proxyman" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -31,7 +31,7 @@ type tcpWorker struct { stream *internet.StreamConfig recvOrigDest bool tag string - dispatcher dispatcher.Interface + dispatcher core.Dispatcher sniffers []proxyman.KnownProtocols ctx context.Context @@ -185,7 +185,7 @@ type udpWorker struct { port net.Port recvOrigDest bool tag string - dispatcher dispatcher.Interface + dispatcher core.Dispatcher ctx context.Context cancel context.CancelFunc diff --git a/app/proxyman/mux/mux.go b/app/proxyman/mux/mux.go index ca34c34c9..52b2b8851 100644 --- a/app/proxyman/mux/mux.go +++ b/app/proxyman/mux/mux.go @@ -8,8 +8,7 @@ import ( "sync" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/app/proxyman" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" @@ -262,21 +261,14 @@ func (m *Client) fetchOutput() { } type Server struct { - dispatcher dispatcher.Interface + dispatcher core.Dispatcher } // NewServer creates a new mux.Server. func NewServer(ctx context.Context) *Server { - s := &Server{} - space := app.SpaceFromContext(ctx) - space.On(app.SpaceInitializing, func(interface{}) error { - d := dispatcher.FromSpace(space) - if d == nil { - return newError("no dispatcher in space") - } - s.dispatcher = d - return nil - }) + s := &Server{ + dispatcher: core.FromContext(ctx).Dispatcher(), + } return s } @@ -295,8 +287,15 @@ func (s *Server) Dispatch(ctx context.Context, dest net.Destination) (ray.Inboun return ray, nil } +func (s *Server) Start() error { + return nil +} + +func (s *Server) Close() { +} + type ServerWorker struct { - dispatcher dispatcher.Interface + dispatcher core.Dispatcher outboundRay ray.OutboundRay sessionManager *SessionManager } diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 33e06d5e5..176b94a44 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -5,7 +5,7 @@ import ( "io" "time" - "v2ray.com/core/app" + "v2ray.com/core" "v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman/mux" "v2ray.com/core/common/buf" @@ -17,29 +17,22 @@ import ( ) type Handler struct { - config *proxyman.OutboundHandlerConfig + config *core.OutboundHandlerConfig senderSettings *proxyman.SenderConfig proxy proxy.Outbound - outboundManager proxyman.OutboundHandlerManager + outboundManager core.OutboundHandlerManager mux *mux.ClientManager } -func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*Handler, error) { +func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (*Handler, error) { + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context") + } h := &Handler{ - config: config, + config: config, + outboundManager: v.OutboundHandlerManager(), } - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") - } - space.On(app.SpaceInitializing, func(interface{}) error { - ohm := proxyman.OutboundHandlerManagerFromSpace(space) - if ohm == nil { - return newError("no OutboundManager in space") - } - h.outboundManager = ohm - return nil - }) if config.SenderSettings != nil { senderSettings, err := config.SenderSettings.GetInstance() @@ -54,7 +47,12 @@ func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*H } } - proxyHandler, err := config.GetProxyHandler(ctx) + proxyConfig, err := config.ProxySettings.GetInstance() + if err != nil { + return nil, err + } + + proxyHandler, err := proxy.CreateOutboundHandler(ctx, proxyConfig) if err != nil { return nil, err } @@ -71,6 +69,10 @@ func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*H return h, nil } +func (h *Handler) Tag() string { + return h.config.Tag +} + // Dispatch implements proxy.Outbound.Dispatch. func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) { if h.mux != nil { diff --git a/app/proxyman/outbound/handler_test.go b/app/proxyman/outbound/handler_test.go new file mode 100644 index 000000000..109b087f0 --- /dev/null +++ b/app/proxyman/outbound/handler_test.go @@ -0,0 +1,15 @@ +package outbound_test + +import ( + "testing" + + "v2ray.com/core" + . "v2ray.com/core/app/proxyman/outbound" + . "v2ray.com/ext/assert" +) + +func TestInterfaces(t *testing.T) { + assert := With(t) + + assert((*Handler)(nil), Implements, (*core.OutboundHandler)(nil)) +} diff --git a/app/proxyman/outbound/outbound.go b/app/proxyman/outbound/outbound.go index 5835cb0e3..6fb68866d 100644 --- a/app/proxyman/outbound/outbound.go +++ b/app/proxyman/outbound/outbound.go @@ -6,6 +6,7 @@ import ( "context" "sync" + "v2ray.com/core" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" ) @@ -13,20 +14,23 @@ import ( // Manager is to manage all outbound handlers. type Manager struct { sync.RWMutex - defaultHandler *Handler - taggedHandler map[string]*Handler + defaultHandler core.OutboundHandler + taggedHandler map[string]core.OutboundHandler } // New creates a new Manager. func New(ctx context.Context, config *proxyman.OutboundConfig) (*Manager, error) { - return &Manager{ - taggedHandler: make(map[string]*Handler), - }, nil -} - -// Interface implements Application.Interface. -func (*Manager) Interface() interface{} { - return (*proxyman.OutboundHandlerManager)(nil) + m := &Manager{ + taggedHandler: make(map[string]core.OutboundHandler), + } + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context") + } + if err := v.RegisterFeature((*core.OutboundHandlerManager)(nil), m); err != nil { + return nil, newError("unable to register OutboundHandlerManager").Base(err) + } + return m, nil } // Start implements Application.Start @@ -35,7 +39,7 @@ func (*Manager) Start() error { return nil } // Close implements Application.Close func (*Manager) Close() {} -func (m *Manager) GetDefaultHandler() proxyman.OutboundHandler { +func (m *Manager) GetDefaultHandler() core.OutboundHandler { m.RLock() defer m.RUnlock() if m.defaultHandler == nil { @@ -44,7 +48,7 @@ func (m *Manager) GetDefaultHandler() proxyman.OutboundHandler { return m.defaultHandler } -func (m *Manager) GetHandler(tag string) proxyman.OutboundHandler { +func (m *Manager) GetHandler(tag string) core.OutboundHandler { m.RLock() defer m.RUnlock() if handler, found := m.taggedHandler[tag]; found { @@ -53,20 +57,17 @@ func (m *Manager) GetHandler(tag string) proxyman.OutboundHandler { return nil } -func (m *Manager) AddHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) error { +func (m *Manager) AddHandler(ctx context.Context, handler core.OutboundHandler) error { m.Lock() defer m.Unlock() - handler, err := NewHandler(ctx, config) - if err != nil { - return err - } if m.defaultHandler == nil { m.defaultHandler = handler } - if len(config.Tag) > 0 { - m.taggedHandler[config.Tag] = handler + tag := handler.Tag() + if len(tag) > 0 { + m.taggedHandler[tag] = handler } return nil @@ -76,4 +77,7 @@ func init() { common.Must(common.RegisterConfig((*proxyman.OutboundConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { return New(ctx, config.(*proxyman.OutboundConfig)) })) + common.Must(common.RegisterConfig((*core.OutboundHandlerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return NewHandler(ctx, config.(*core.OutboundHandlerConfig)) + })) } diff --git a/app/proxyman/proxyman.go b/app/proxyman/proxyman.go index f782a77b5..1ae393aa3 100644 --- a/app/proxyman/proxyman.go +++ b/app/proxyman/proxyman.go @@ -5,52 +5,8 @@ package proxyman import ( "context" - - "v2ray.com/core/app" - "v2ray.com/core/common/net" - "v2ray.com/core/proxy" - "v2ray.com/core/transport/ray" ) -type InboundHandlerManager interface { - GetHandler(ctx context.Context, tag string) (InboundHandler, error) - AddHandler(ctx context.Context, config *InboundHandlerConfig) error -} - -type InboundHandler interface { - Start() error - Close() - - // For migration - GetRandomInboundProxy() (proxy.Inbound, net.Port, int) -} - -type OutboundHandlerManager interface { - GetHandler(tag string) OutboundHandler - GetDefaultHandler() OutboundHandler - AddHandler(ctx context.Context, config *OutboundHandlerConfig) error -} - -type OutboundHandler interface { - Dispatch(ctx context.Context, outboundRay ray.OutboundRay) -} - -func InboundHandlerManagerFromSpace(space app.Space) InboundHandlerManager { - app := space.GetApplication((*InboundHandlerManager)(nil)) - if app == nil { - return nil - } - return app.(InboundHandlerManager) -} - -func OutboundHandlerManagerFromSpace(space app.Space) OutboundHandlerManager { - app := space.GetApplication((*OutboundHandlerManager)(nil)) - if app == nil { - return nil - } - return app.(OutboundHandlerManager) -} - type key int const ( diff --git a/app/router/router.go b/app/router/router.go index 17184a2d0..7d003dc4c 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -5,46 +5,47 @@ package router import ( "context" - "v2ray.com/core/app" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/net" "v2ray.com/core/proxy" ) -var ( - ErrNoRuleApplicable = newError("No rule applicable") -) - type Router struct { domainStrategy Config_DomainStrategy rules []Rule + dns core.DNSClient } func NewRouter(ctx context.Context, config *Config) (*Router, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context") } + r := &Router{ domainStrategy: config.DomainStrategy, rules: make([]Rule, len(config.Rule)), + dns: v.DNSClient(), } - space.On(app.SpaceInitializing, func(interface{}) 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 + for idx, rule := range config.Rule { + r.rules[idx].Tag = rule.Tag + cond, err := rule.BuildCondition() + if err != nil { + return nil, err } - return nil - }) + r.rules[idx].Condition = cond + } + + if err := v.RegisterFeature((*core.Router)(nil), r); err != nil { + return nil, newError("unable to register Router").Base(err) + } return r, nil } type ipResolver struct { + dns core.DNSClient ip []net.Address domain string resolved bool @@ -57,7 +58,7 @@ func (r *ipResolver) Resolve() []net.Address { newError("looking for IP for domain: ", r.domain).WriteToLog() r.resolved = true - ips, err := net.LookupIP(r.domain) + ips, err := r.dns.LookupIP(r.domain) if err != nil { newError("failed to get IP address").Base(err).WriteToLog() } @@ -71,8 +72,10 @@ func (r *ipResolver) Resolve() []net.Address { return r.ip } -func (r *Router) TakeDetour(ctx context.Context) (string, error) { - resolver := &ipResolver{} +func (r *Router) PickRoute(ctx context.Context) (string, error) { + resolver := &ipResolver{ + dns: r.dns, + } if r.domainStrategy == Config_IpOnDemand { if dest, ok := proxy.TargetFromContext(ctx); ok && dest.Address.Family().IsDomain() { resolver.domain = dest.Address.Domain() @@ -88,7 +91,7 @@ func (r *Router) TakeDetour(ctx context.Context) (string, error) { dest, ok := proxy.TargetFromContext(ctx) if !ok { - return "", ErrNoRuleApplicable + return "", core.ErrNoClue } if r.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() { @@ -104,11 +107,7 @@ func (r *Router) TakeDetour(ctx context.Context) (string, error) { } } - return "", ErrNoRuleApplicable -} - -func (*Router) Interface() interface{} { - return (*Router)(nil) + return "", core.ErrNoClue } func (*Router) Start() error { @@ -117,14 +116,6 @@ func (*Router) Start() error { func (*Router) Close() {} -func FromSpace(space app.Space) *Router { - app := space.GetApplication((*Router)(nil)) - if app == nil { - return nil - } - return app.(*Router) -} - func init() { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { return NewRouter(ctx, config.(*Config)) diff --git a/app/router/router_test.go b/app/router/router_test.go index 855272cb7..856d5adb5 100644 --- a/app/router/router_test.go +++ b/app/router/router_test.go @@ -4,13 +4,14 @@ import ( "context" "testing" - "v2ray.com/core/app" + "v2ray.com/core" "v2ray.com/core/app/dispatcher" - _ "v2ray.com/core/app/dispatcher/impl" "v2ray.com/core/app/proxyman" _ "v2ray.com/core/app/proxyman/outbound" . "v2ray.com/core/app/router" + "v2ray.com/core/common" "v2ray.com/core/common/net" + "v2ray.com/core/common/serial" "v2ray.com/core/proxy" . "v2ray.com/ext/assert" ) @@ -18,28 +19,30 @@ import ( func TestSimpleRouter(t *testing.T) { assert := With(t) - config := &Config{ - Rule: []*RoutingRule{ - { - Tag: "test", - NetworkList: &net.NetworkList{ - Network: []net.Network{net.Network_TCP}, + config := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&Config{ + Rule: []*RoutingRule{ + { + Tag: "test", + NetworkList: &net.NetworkList{ + Network: []net.Network{net.Network_TCP}, + }, + }, }, - }, + }), + serial.ToTypedMessage(&dispatcher.Config{}), + serial.ToTypedMessage(&proxyman.OutboundConfig{}), }, } - space := app.NewSpace() - ctx := app.ContextWithSpace(context.Background(), space) - assert(app.AddApplicationToSpace(ctx, new(dispatcher.Config)), IsNil) - assert(app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig)), IsNil) - assert(app.AddApplicationToSpace(ctx, config), IsNil) - assert(space.Initialize(), IsNil) + v, err := core.New(config) + common.Must(err) - r := FromSpace(space) + r := v.Router() - ctx = proxy.ContextWithTarget(ctx, net.TCPDestination(net.DomainAddress("v2ray.com"), 80)) - tag, err := r.TakeDetour(ctx) + ctx := proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)) + tag, err := r.PickRoute(ctx) assert(err, IsNil) assert(tag, Equals, "test") } diff --git a/app/space.go b/app/space.go deleted file mode 100644 index 4a7bc22c4..000000000 --- a/app/space.go +++ /dev/null @@ -1,132 +0,0 @@ -package app - -import ( - "context" - "reflect" - - "v2ray.com/core/common" - "v2ray.com/core/common/event" -) - -// Application is a component that runs in Space. -type Application interface { - Interface() interface{} - Start() error - Close() -} - -// CreateAppFromConfig creates an Application based on its config. Application must have been registered. -func CreateAppFromConfig(ctx context.Context, config interface{}) (Application, error) { - application, err := common.CreateObject(ctx, config) - if err != nil { - return nil, err - } - switch a := application.(type) { - case Application: - return a, nil - default: - return nil, newError("not an application") - } -} - -// A Space contains all apps that may be available in a V2Ray runtime. -type Space interface { - event.Registry - GetApplication(appInterface interface{}) Application - AddApplication(application Application) error - Initialize() error - Start() error - Close() -} - -const ( - // SpaceInitializing is an event to be fired when Space is being initialized. - SpaceInitializing event.Event = iota -) - -type spaceImpl struct { - event.Listener - cache map[reflect.Type]Application - initialized bool -} - -// NewSpace creates a new Space. -func NewSpace() Space { - return &spaceImpl{ - cache: make(map[reflect.Type]Application), - } -} - -func (s *spaceImpl) On(e event.Event, h event.Handler) { - if e == SpaceInitializing && s.initialized { - _ = h(nil) // Ignore error - return - } - s.Listener.On(e, h) -} - -func (s *spaceImpl) Initialize() error { - if s.initialized { - return nil - } - s.initialized = true - return s.Fire(SpaceInitializing, nil) -} - -func (s *spaceImpl) GetApplication(appInterface interface{}) Application { - if s == nil { - return nil - } - appType := reflect.TypeOf(appInterface) - return s.cache[appType] -} - -func (s *spaceImpl) AddApplication(app Application) error { - if s == nil { - return newError("nil space").AtError() - } - appType := reflect.TypeOf(app.Interface()) - s.cache[appType] = app - return nil -} - -func (s *spaceImpl) Start() error { - for _, app := range s.cache { - if err := app.Start(); err != nil { - return err - } - } - return nil -} - -func (s *spaceImpl) Close() { - for _, app := range s.cache { - app.Close() - } -} - -type contextKey int - -const ( - spaceKey = contextKey(0) -) - -func AddApplicationToSpace(ctx context.Context, appConfig interface{}) error { - space := SpaceFromContext(ctx) - if space == nil { - return newError("no space in context").AtError() - } - application, err := CreateAppFromConfig(ctx, appConfig) - if err != nil { - return err - } - return space.AddApplication(application) -} - -func SpaceFromContext(ctx context.Context) Space { - return ctx.Value(spaceKey).(Space) -} - -func ContextWithSpace(ctx context.Context, space Space) context.Context { - return context.WithValue(ctx, spaceKey, space) -} diff --git a/common/interfaces.go b/common/interfaces.go new file mode 100644 index 000000000..6ce590c23 --- /dev/null +++ b/common/interfaces.go @@ -0,0 +1,10 @@ +package common + +// Runnable is the interface for objects that can start to work and stop on demand. +type Runnable interface { + // Start starts the runnable object. Upon the method returning nil, the object begins to function properly. + Start() error + + // Close stops the object being working. + Close() +} diff --git a/common/protocol/user.pb.go b/common/protocol/user.pb.go index 46c68a5fa..882c1542f 100644 --- a/common/protocol/user.pb.go +++ b/common/protocol/user.pb.go @@ -14,7 +14,7 @@ var _ = math.Inf type User struct { Level uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"` Email string `protobuf:"bytes,2,opt,name=email" json:"email,omitempty"` - // Protocol specific account information. + // Protocol specific account information. Must be the account proto in one of the proxies. Account *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=account" json:"account,omitempty"` } diff --git a/common/router/dispatcher.go b/common/router/dispatcher.go new file mode 100644 index 000000000..4934d3027 --- /dev/null +++ b/common/router/dispatcher.go @@ -0,0 +1,12 @@ +package router + +import ( + "context" + + "v2ray.com/core/common/net" + "v2ray.com/core/transport/ray" +) + +type Dispatcher interface { + Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error) +} diff --git a/common/router/router.go b/common/router/router.go new file mode 100644 index 000000000..a2dc15bbe --- /dev/null +++ b/common/router/router.go @@ -0,0 +1,53 @@ +package router + +import ( + "context" + "sync" +) + +type Router interface { + Pick(ctx context.Context) (string, bool) +} + +type defaultRouter byte + +func (defaultRouter) Pick(ctx context.Context) (string, bool) { + return "", false +} + +type syncRouter struct { + sync.RWMutex + Router +} + +func (r *syncRouter) Pick(ctx context.Context) (string, bool) { + r.RLock() + defer r.RUnlock() + + return r.Router.Pick(ctx) +} + +func (r *syncRouter) Set(router Router) { + r.Lock() + defer r.Unlock() + + r.Router = router +} + +var ( + routerInstance = &syncRouter{ + Router: defaultRouter(0), + } +) + +func RegisterRouter(router Router) { + if router == nil { + panic("Router is nil.") + } + + routerInstance.Set(router) +} + +func Pick(ctx context.Context) (string, bool) { + return routerInstance.Router.Pick(ctx) +} diff --git a/config.pb.go b/config.pb.go index 7c3426a54..1429f6e22 100644 --- a/config.pb.go +++ b/config.pb.go @@ -3,7 +3,6 @@ package core import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" -import v2ray_core_app_proxyman "v2ray.com/core/app/proxyman" import v2ray_core_common_serial "v2ray.com/core/common/serial" import v2ray_core_transport "v2ray.com/core/transport" @@ -40,12 +39,12 @@ func (x ConfigFormat) String() string { } func (ConfigFormat) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -// Master config of V2Ray. V2Ray Core takes this config as input and functions accordingly. +// Master config of V2Ray. V2Ray takes this config as input and functions accordingly. type Config struct { // Inbound handler configurations. Must have at least one item. - Inbound []*v2ray_core_app_proxyman.InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbound" json:"inbound,omitempty"` + Inbound []*InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbound" json:"inbound,omitempty"` // Outbound handler configurations. Must have at least one item. The first item is used as default for routing. - Outbound []*v2ray_core_app_proxyman.OutboundHandlerConfig `protobuf:"bytes,2,rep,name=outbound" json:"outbound,omitempty"` + Outbound []*OutboundHandlerConfig `protobuf:"bytes,2,rep,name=outbound" json:"outbound,omitempty"` // App configuration. Must be one in the app directory. App []*v2ray_core_common_serial.TypedMessage `protobuf:"bytes,4,rep,name=app" json:"app,omitempty"` // Transport settings. @@ -60,14 +59,14 @@ func (m *Config) String() string { return proto.CompactTextString(m) func (*Config) ProtoMessage() {} func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (m *Config) GetInbound() []*v2ray_core_app_proxyman.InboundHandlerConfig { +func (m *Config) GetInbound() []*InboundHandlerConfig { if m != nil { return m.Inbound } return nil } -func (m *Config) GetOutbound() []*v2ray_core_app_proxyman.OutboundHandlerConfig { +func (m *Config) GetOutbound() []*OutboundHandlerConfig { if m != nil { return m.Outbound } @@ -95,34 +94,131 @@ func (m *Config) GetExtension() []*v2ray_core_common_serial.TypedMessage { return nil } +type InboundHandlerConfig struct { + // Tag of the inbound handler. + Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"` + // Settings for how this inbound proxy is handled. Must be ReceiverConfig above. + ReceiverSettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=receiver_settings,json=receiverSettings" json:"receiver_settings,omitempty"` + // Settings for inbound proxy. Must be one of the inbound proxies. + ProxySettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"` +} + +func (m *InboundHandlerConfig) Reset() { *m = InboundHandlerConfig{} } +func (m *InboundHandlerConfig) String() string { return proto.CompactTextString(m) } +func (*InboundHandlerConfig) ProtoMessage() {} +func (*InboundHandlerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *InboundHandlerConfig) GetTag() string { + if m != nil { + return m.Tag + } + return "" +} + +func (m *InboundHandlerConfig) GetReceiverSettings() *v2ray_core_common_serial.TypedMessage { + if m != nil { + return m.ReceiverSettings + } + return nil +} + +func (m *InboundHandlerConfig) GetProxySettings() *v2ray_core_common_serial.TypedMessage { + if m != nil { + return m.ProxySettings + } + return nil +} + +type OutboundHandlerConfig struct { + // Tag of this outbound handler. + Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"` + // Settings for how to dial connection for this outbound handler. Must be SenderConfig above. + SenderSettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=sender_settings,json=senderSettings" json:"sender_settings,omitempty"` + // Settings for this outbound proxy. Must be one of the outbound proxies. + ProxySettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"` + // If not zero, this outbound will be expired in seconds. Not used for now. + Expire int64 `protobuf:"varint,4,opt,name=expire" json:"expire,omitempty"` + // Comment of this outbound handler. Not used for now. + Comment string `protobuf:"bytes,5,opt,name=comment" json:"comment,omitempty"` +} + +func (m *OutboundHandlerConfig) Reset() { *m = OutboundHandlerConfig{} } +func (m *OutboundHandlerConfig) String() string { return proto.CompactTextString(m) } +func (*OutboundHandlerConfig) ProtoMessage() {} +func (*OutboundHandlerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *OutboundHandlerConfig) GetTag() string { + if m != nil { + return m.Tag + } + return "" +} + +func (m *OutboundHandlerConfig) GetSenderSettings() *v2ray_core_common_serial.TypedMessage { + if m != nil { + return m.SenderSettings + } + return nil +} + +func (m *OutboundHandlerConfig) GetProxySettings() *v2ray_core_common_serial.TypedMessage { + if m != nil { + return m.ProxySettings + } + return nil +} + +func (m *OutboundHandlerConfig) GetExpire() int64 { + if m != nil { + return m.Expire + } + return 0 +} + +func (m *OutboundHandlerConfig) GetComment() string { + if m != nil { + return m.Comment + } + return "" +} + func init() { proto.RegisterType((*Config)(nil), "v2ray.core.Config") + proto.RegisterType((*InboundHandlerConfig)(nil), "v2ray.core.InboundHandlerConfig") + proto.RegisterType((*OutboundHandlerConfig)(nil), "v2ray.core.OutboundHandlerConfig") proto.RegisterEnum("v2ray.core.ConfigFormat", ConfigFormat_name, ConfigFormat_value) } func init() { proto.RegisterFile("v2ray.com/core/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 336 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xcd, 0x4a, 0xf3, 0x40, - 0x18, 0x85, 0xbf, 0xb4, 0xf9, 0x6a, 0xfa, 0xb6, 0x48, 0x99, 0x55, 0xa8, 0x2e, 0x8a, 0xd0, 0x52, - 0x04, 0x27, 0x12, 0x37, 0xe2, 0xd2, 0x8a, 0x3f, 0x05, 0x6d, 0xa9, 0xe2, 0xc2, 0x8d, 0x4c, 0xd3, - 0x69, 0x09, 0x74, 0xe6, 0x1d, 0x26, 0x53, 0x69, 0x6e, 0xc9, 0x9b, 0xf2, 0x56, 0x24, 0x99, 0xfe, - 0xa5, 0xe2, 0xc2, 0x55, 0x20, 0x73, 0x9e, 0xe7, 0x4c, 0x4e, 0xe0, 0xe8, 0x23, 0xd4, 0x2c, 0xa5, - 0x11, 0x8a, 0x20, 0x42, 0xcd, 0x83, 0x08, 0xe5, 0x34, 0x9e, 0x51, 0xa5, 0xd1, 0x20, 0x81, 0xf5, - 0xa1, 0xe6, 0xcd, 0xee, 0x5e, 0x90, 0x29, 0x15, 0x28, 0x8d, 0xcb, 0x54, 0x30, 0x59, 0xa0, 0x9a, - 0xe7, 0x3f, 0x94, 0x42, 0xa0, 0x0c, 0x12, 0xae, 0x63, 0x36, 0x0f, 0x4c, 0xaa, 0xf8, 0xe4, 0x5d, - 0xf0, 0x24, 0x61, 0x33, 0xbe, 0x22, 0xda, 0x7b, 0x84, 0xd1, 0x4c, 0x26, 0x0a, 0xb5, 0x29, 0x88, - 0x4f, 0xbe, 0x4a, 0x50, 0xe9, 0xe5, 0x2f, 0xc8, 0x1d, 0x1c, 0xc4, 0x72, 0x8c, 0x0b, 0x39, 0xf1, - 0x9d, 0x56, 0xb9, 0x5b, 0x0b, 0xcf, 0xe8, 0xf6, 0xae, 0x94, 0x29, 0x45, 0xd7, 0x77, 0xa3, 0x0f, - 0x36, 0x77, 0xcf, 0xe4, 0x64, 0xce, 0xb5, 0xe5, 0x47, 0x6b, 0x9a, 0xf4, 0xc1, 0xc3, 0x85, 0xb1, - 0xa6, 0x52, 0x6e, 0xa2, 0xbf, 0x9a, 0x06, 0xab, 0x60, 0x51, 0xb5, 0xe1, 0xc9, 0x25, 0x94, 0x99, - 0x52, 0xbe, 0x9b, 0x6b, 0x3a, 0xbb, 0x1a, 0x3b, 0x01, 0xb5, 0x13, 0xd0, 0x97, 0x6c, 0x82, 0x47, - 0xbb, 0xc0, 0x28, 0x43, 0xc8, 0x15, 0x54, 0x37, 0xdf, 0xec, 0xff, 0x6f, 0x39, 0xdd, 0x5a, 0x78, - 0xbc, 0xcb, 0x6f, 0x0e, 0xe9, 0xaa, 0x74, 0x1b, 0x27, 0x37, 0x50, 0xe5, 0x4b, 0xc3, 0x65, 0x12, - 0xa3, 0xf4, 0x2b, 0x7f, 0xea, 0xde, 0x82, 0x7d, 0xd7, 0x2b, 0x37, 0xdc, 0xd3, 0x0e, 0xd4, 0x6d, - 0xc1, 0x2d, 0x6a, 0xc1, 0x0c, 0xa9, 0x83, 0x37, 0xcc, 0xa6, 0x1f, 0x2f, 0xa6, 0x8d, 0x7f, 0xc4, - 0x03, 0xb7, 0xff, 0x3c, 0x78, 0x6a, 0x38, 0xd7, 0x6d, 0x38, 0x8c, 0x50, 0xec, 0xb4, 0x0c, 0x9d, - 0x37, 0x37, 0x7b, 0x7e, 0x96, 0xe0, 0x35, 0x1c, 0xb1, 0x94, 0xf6, 0x50, 0xf3, 0x71, 0x25, 0xff, - 0x6f, 0x17, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x62, 0x93, 0x6d, 0x78, 0x65, 0x02, 0x00, 0x00, + // 436 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x93, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x71, 0x13, 0xba, 0xf6, 0x6d, 0x94, 0x60, 0x01, 0xb2, 0x06, 0x87, 0x50, 0x69, 0x53, + 0xc5, 0xc1, 0x45, 0xe5, 0x82, 0x26, 0x71, 0x61, 0x08, 0xc1, 0xa4, 0xd1, 0x29, 0x45, 0x1c, 0xb8, + 0x4c, 0x6e, 0xfa, 0x56, 0x45, 0x5a, 0xec, 0xc8, 0x76, 0xa7, 0xe6, 0x2b, 0xf1, 0x3d, 0xb8, 0xf1, + 0x8d, 0xb8, 0xa0, 0xc4, 0x49, 0x93, 0x41, 0x0f, 0x14, 0x69, 0xa7, 0xc4, 0x79, 0xfe, 0xfd, 0xdf, + 0xfb, 0x25, 0x31, 0x3c, 0xbb, 0x99, 0x68, 0x91, 0xf3, 0x58, 0xa5, 0xe3, 0x58, 0x69, 0x1c, 0xc7, + 0x4a, 0x5e, 0x25, 0x4b, 0x9e, 0x69, 0x65, 0x15, 0x85, 0xba, 0xa8, 0xf1, 0xf0, 0xd5, 0x5f, 0x1b, + 0xd3, 0x54, 0xc9, 0xb1, 0x41, 0x9d, 0x88, 0xeb, 0xb1, 0xcd, 0x33, 0x5c, 0x5c, 0xa6, 0x68, 0x8c, + 0x58, 0xa2, 0xa3, 0x0f, 0x8f, 0xfe, 0x20, 0xac, 0x16, 0xd2, 0x64, 0x4a, 0xdb, 0x5b, 0x4d, 0x86, + 0x3f, 0x3a, 0xd0, 0x3d, 0x2d, 0x1f, 0xd0, 0x13, 0xd8, 0x4b, 0xe4, 0x5c, 0xad, 0xe4, 0x82, 0x91, + 0xd0, 0x1b, 0xed, 0x4f, 0x42, 0xde, 0x4c, 0xc0, 0x3f, 0xb9, 0xd2, 0x47, 0x21, 0x17, 0xd7, 0xa8, + 0x1d, 0x12, 0xd5, 0x00, 0x7d, 0x0b, 0x3d, 0xb5, 0xb2, 0x0e, 0xee, 0x94, 0xf0, 0x8b, 0x36, 0x3c, + 0xad, 0x6a, 0xb7, 0xe9, 0x0d, 0x42, 0xdf, 0x80, 0x27, 0xb2, 0x8c, 0xf9, 0x25, 0x79, 0xdc, 0x26, + 0x9d, 0x28, 0x77, 0xa2, 0xfc, 0x4b, 0x21, 0x7a, 0xee, 0x3c, 0xa3, 0x02, 0xa1, 0x27, 0xd0, 0xdf, + 0x98, 0xb1, 0xfb, 0x21, 0x19, 0xed, 0x4f, 0x9e, 0xb7, 0xf9, 0x4d, 0x91, 0x57, 0x4d, 0x9b, 0xed, + 0xf4, 0x3d, 0xf4, 0x71, 0x6d, 0x51, 0x9a, 0x44, 0x49, 0xd6, 0xdd, 0xa9, 0x77, 0x03, 0x9e, 0xf9, + 0x3d, 0x2f, 0xf0, 0x87, 0x3f, 0x09, 0x3c, 0xde, 0xf6, 0x8a, 0x68, 0x00, 0x9e, 0x15, 0x4b, 0x46, + 0x42, 0x32, 0xea, 0x47, 0xc5, 0x2d, 0x9d, 0xc1, 0x23, 0x8d, 0x31, 0x26, 0x37, 0xa8, 0x2f, 0x0d, + 0x5a, 0x9b, 0xc8, 0xa5, 0x61, 0x9d, 0x72, 0xf4, 0x7f, 0x6d, 0x1f, 0xd4, 0x01, 0xb3, 0x8a, 0xa7, + 0xe7, 0x30, 0xc8, 0xb4, 0x5a, 0xe7, 0x4d, 0xa2, 0xb7, 0x53, 0xe2, 0x83, 0x92, 0xae, 0xe3, 0x86, + 0xbf, 0x08, 0x3c, 0xd9, 0xfa, 0xd1, 0xb6, 0xf8, 0x4c, 0xe1, 0xa1, 0x41, 0xb9, 0xf8, 0x7f, 0x9b, + 0x81, 0xc3, 0xef, 0xc8, 0x85, 0x3e, 0x85, 0x2e, 0xae, 0xb3, 0x44, 0x23, 0xf3, 0x43, 0x32, 0xf2, + 0xa2, 0x6a, 0x45, 0x19, 0xec, 0x15, 0x21, 0x28, 0xdd, 0x8f, 0xd3, 0x8f, 0xea, 0xe5, 0xcb, 0x63, + 0x38, 0x70, 0xb6, 0x1f, 0x94, 0x4e, 0x85, 0xa5, 0x07, 0xd0, 0xbb, 0x28, 0x4e, 0xcb, 0x7c, 0x75, + 0x15, 0xdc, 0xa3, 0x3d, 0xf0, 0xcf, 0x66, 0xd3, 0xcf, 0x01, 0x79, 0x77, 0x04, 0x83, 0x58, 0xa5, + 0xad, 0xa9, 0x2e, 0xc8, 0x37, 0xbf, 0xb8, 0x7e, 0xef, 0xc0, 0xd7, 0x49, 0x24, 0x72, 0x7e, 0xaa, + 0x34, 0xce, 0xbb, 0xe5, 0x51, 0x7b, 0xfd, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x59, 0x1b, + 0xee, 0x03, 0x00, 0x00, } diff --git a/config.proto b/config.proto index b5e337fc0..6101c0fa4 100644 --- a/config.proto +++ b/config.proto @@ -6,7 +6,6 @@ option go_package = "core"; option java_package = "com.v2ray.core"; option java_multiple_files = true; -import "v2ray.com/core/app/proxyman/config.proto"; import "v2ray.com/core/common/serial/typed_message.proto"; import "v2ray.com/core/transport/config.proto"; @@ -19,10 +18,10 @@ enum ConfigFormat { // Master config of V2Ray. V2Ray takes this config as input and functions accordingly. message Config { // Inbound handler configurations. Must have at least one item. - repeated v2ray.core.app.proxyman.InboundHandlerConfig inbound = 1; + repeated InboundHandlerConfig inbound = 1; // Outbound handler configurations. Must have at least one item. The first item is used as default for routing. - repeated v2ray.core.app.proxyman.OutboundHandlerConfig outbound = 2; + repeated OutboundHandlerConfig outbound = 2; reserved 3; @@ -36,3 +35,25 @@ message Config { // V2Ray will ignore such config during initialization. repeated v2ray.core.common.serial.TypedMessage extension = 6; } + +message InboundHandlerConfig { + // Tag of the inbound handler. + string tag = 1; + // Settings for how this inbound proxy is handled. Must be ReceiverConfig above. + v2ray.core.common.serial.TypedMessage receiver_settings = 2; + // Settings for inbound proxy. Must be one of the inbound proxies. + v2ray.core.common.serial.TypedMessage proxy_settings = 3; +} + +message OutboundHandlerConfig { + // Tag of this outbound handler. + string tag = 1; + // Settings for how to dial connection for this outbound handler. Must be SenderConfig above. + v2ray.core.common.serial.TypedMessage sender_settings = 2; + // Settings for this outbound proxy. Must be one of the outbound proxies. + v2ray.core.common.serial.TypedMessage proxy_settings = 3; + // If not zero, this outbound will be expired in seconds. Not used for now. + int64 expire = 4; + // Comment of this outbound handler. Not used for now. + string comment = 5; +} diff --git a/context.go b/context.go new file mode 100644 index 000000000..c92f0bacc --- /dev/null +++ b/context.go @@ -0,0 +1,17 @@ +package core + +import ( + "context" +) + +type key int + +const v2rayKey key = 1 + +// FromContext returns a Instance from the given context, or nil if the context doesn't contain one. +func FromContext(ctx context.Context) *Instance { + if s, ok := ctx.Value(v2rayKey).(*Instance); ok { + return s + } + return nil +} diff --git a/dns.go b/dns.go new file mode 100644 index 000000000..0c8046e19 --- /dev/null +++ b/dns.go @@ -0,0 +1,57 @@ +package core + +import "net" +import "sync" + +// DNSClient is a V2Ray feature for querying DNS information. +type DNSClient interface { + Feature + LookupIP(host string) ([]net.IP, error) +} + +type syncDNSClient struct { + sync.RWMutex + DNSClient +} + +func (d *syncDNSClient) LookupIP(host string) ([]net.IP, error) { + d.RLock() + defer d.RUnlock() + + if d.DNSClient == nil { + return net.LookupIP(host) + } + + return d.DNSClient.LookupIP(host) +} + +func (d *syncDNSClient) Start() error { + d.RLock() + defer d.RUnlock() + + if d.DNSClient == nil { + return nil + } + + return d.DNSClient.Start() +} + +func (d *syncDNSClient) Close() { + d.RLock() + defer d.RUnlock() + + if d.DNSClient != nil { + d.DNSClient.Close() + } +} + +func (d *syncDNSClient) Set(client DNSClient) { + if client == nil { + return + } + + d.Lock() + defer d.Unlock() + + d.DNSClient = client +} diff --git a/main/distro/all/all.go b/main/distro/all/all.go index 85380d04e..1b55c1cad 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -2,10 +2,10 @@ package all import ( // The following are necessary as they register handlers in their init functions. - _ "v2ray.com/core/app/dispatcher/impl" + _ "v2ray.com/core/app/dispatcher" _ "v2ray.com/core/app/dns" _ "v2ray.com/core/app/log" - _ "v2ray.com/core/app/policy/manager" + _ "v2ray.com/core/app/policy" _ "v2ray.com/core/app/proxyman/inbound" _ "v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/router" diff --git a/network.go b/network.go new file mode 100644 index 000000000..7524f7e4c --- /dev/null +++ b/network.go @@ -0,0 +1,165 @@ +package core + +import ( + "context" + "sync" + + "v2ray.com/core/common" + "v2ray.com/core/common/net" + "v2ray.com/core/transport/ray" +) + +// InboundHandler is the interface for handlers that process inbound connections. +type InboundHandler interface { + common.Runnable + // The tag of this handler. + Tag() string + + // Deprecated. Do not use in new code. + GetRandomInboundProxy() (interface{}, net.Port, int) +} + +// OutboundHandler is the interface for handlers that process outbound connections. +type OutboundHandler interface { + Tag() string + Dispatch(ctx context.Context, outboundRay ray.OutboundRay) +} + +// InboundHandlerManager is a feature that managers InboundHandlers. +type InboundHandlerManager interface { + Feature + // GetHandlers returns an InboundHandler for the given tag. + GetHandler(ctx context.Context, tag string) (InboundHandler, error) + // AddHandler adds the given handler into this InboundHandlerManager. + AddHandler(ctx context.Context, handler InboundHandler) error +} + +type syncInboundHandlerManager struct { + sync.RWMutex + InboundHandlerManager +} + +func (m *syncInboundHandlerManager) GetHandler(ctx context.Context, tag string) (InboundHandler, error) { + m.RLock() + defer m.RUnlock() + + if m.InboundHandlerManager == nil { + return nil, newError("InboundHandlerManager not set.").AtError() + } + + return m.InboundHandlerManager.GetHandler(ctx, tag) +} + +func (m *syncInboundHandlerManager) AddHandler(ctx context.Context, handler InboundHandler) error { + m.RLock() + defer m.RUnlock() + + if m.InboundHandlerManager == nil { + return newError("InboundHandlerManager not set.").AtError() + } + + return m.InboundHandlerManager.AddHandler(ctx, handler) +} + +func (m *syncInboundHandlerManager) Start() error { + m.RLock() + defer m.RUnlock() + + if m.InboundHandlerManager == nil { + return newError("InboundHandlerManager not set.").AtError() + } + + return m.InboundHandlerManager.Start() +} + +func (m *syncInboundHandlerManager) Close() { + m.RLock() + defer m.RUnlock() + + if m.InboundHandlerManager != nil { + m.InboundHandlerManager.Close() + } +} + +func (m *syncInboundHandlerManager) Set(manager InboundHandlerManager) { + m.Lock() + defer m.Unlock() + + m.InboundHandlerManager = manager +} + +// OutboundHandlerManager is a feature that manages OutboundHandlers. +type OutboundHandlerManager interface { + Feature + // GetHandler returns an OutboundHandler will given tag. + GetHandler(tag string) OutboundHandler + // GetDefaultHandler returns the default OutboundHandler. It is usually the first OutboundHandler specified in the configuration. + GetDefaultHandler() OutboundHandler + // AddHandler adds a handler into this OutboundHandlerManager. + AddHandler(ctx context.Context, handler OutboundHandler) error +} + +type syncOutboundHandlerManager struct { + sync.RWMutex + OutboundHandlerManager +} + +func (m *syncOutboundHandlerManager) GetHandler(tag string) OutboundHandler { + m.RLock() + defer m.RUnlock() + + if m.OutboundHandlerManager == nil { + return nil + } + + return m.OutboundHandlerManager.GetHandler(tag) +} + +func (m *syncOutboundHandlerManager) GetDefaultHandler() OutboundHandler { + m.RLock() + defer m.RUnlock() + + if m.OutboundHandlerManager == nil { + return nil + } + + return m.OutboundHandlerManager.GetDefaultHandler() +} + +func (m *syncOutboundHandlerManager) AddHandler(ctx context.Context, handler OutboundHandler) error { + m.RLock() + defer m.RUnlock() + + if m.OutboundHandlerManager == nil { + return newError("OutboundHandlerManager not set.").AtError() + } + + return m.OutboundHandlerManager.AddHandler(ctx, handler) +} + +func (m *syncOutboundHandlerManager) Start() error { + m.RLock() + defer m.RUnlock() + + if m.OutboundHandlerManager == nil { + return newError("OutboundHandlerManager not set.").AtError() + } + + return m.OutboundHandlerManager.Start() +} + +func (m *syncOutboundHandlerManager) Close() { + m.RLock() + defer m.RUnlock() + + if m.OutboundHandlerManager != nil { + m.OutboundHandlerManager.Close() + } +} + +func (m *syncOutboundHandlerManager) Set(manager OutboundHandlerManager) { + m.Lock() + defer m.Unlock() + + m.OutboundHandlerManager = manager +} diff --git a/policy.go b/policy.go new file mode 100644 index 000000000..12cff0f10 --- /dev/null +++ b/policy.go @@ -0,0 +1,117 @@ +package core + +import ( + "sync" + "time" +) + +// TimeoutPolicy contains limits for connection timeout. +type TimeoutPolicy struct { + // Timeout for handshake phase in a connection. + Handshake time.Duration + // Timeout for connection being idle, i.e., there is no egress or ingress traffic in this connection. + ConnectionIdle time.Duration + // Timeout for an uplink only connection, i.e., the downlink of the connection has ben closed. + UplinkOnly time.Duration + // Timeout for an downlink only connection, i.e., the uplink of the connection has ben closed. + DownlinkOnly time.Duration +} + +// OverrideWith overrides the current TimeoutPolicy with another one. All timeouts with zero value will be overridden with the new value. +func (p TimeoutPolicy) OverrideWith(another TimeoutPolicy) TimeoutPolicy { + if p.Handshake == 0 { + p.Handshake = another.Handshake + } + if p.ConnectionIdle == 0 { + p.ConnectionIdle = another.ConnectionIdle + } + if p.UplinkOnly == 0 { + p.UplinkOnly = another.UplinkOnly + } + if p.DownlinkOnly == 0 { + p.DownlinkOnly = another.DownlinkOnly + } + return p +} + +// Policy is session based settings for controlling V2Ray requests. It contains various settings (or limits) that may differ for different users in the context. +type Policy struct { + Timeouts TimeoutPolicy // Timeout settings +} + +// OverrideWith overrides the current Policy with another one. All values with default value will be overridden. +func (p Policy) OverrideWith(another Policy) Policy { + p.Timeouts.OverrideWith(another.Timeouts) + return p +} + +// PolicyManager is a feature that provides Policy for the given user by its id or level. +type PolicyManager interface { + Feature + + // ForLevel returns the Policy for the given user level. + ForLevel(level uint32) Policy +} + +// DefaultPolicy returns the Policy when user is not specified. +func DefaultPolicy() Policy { + return Policy{ + Timeouts: TimeoutPolicy{ + Handshake: time.Second * 4, + ConnectionIdle: time.Second * 300, + UplinkOnly: time.Second * 5, + DownlinkOnly: time.Second * 30, + }, + } +} + +type syncPolicyManager struct { + sync.RWMutex + PolicyManager +} + +func (m *syncPolicyManager) ForLevel(level uint32) Policy { + m.RLock() + defer m.RUnlock() + + if m.PolicyManager == nil { + p := DefaultPolicy() + if level == 1 { + p.Timeouts.ConnectionIdle = time.Second * 600 + } + return p + } + + return m.PolicyManager.ForLevel(level) +} + +func (m *syncPolicyManager) Start() error { + m.RLock() + defer m.RUnlock() + + if m.PolicyManager == nil { + return nil + } + + return m.PolicyManager.Start() +} + +func (m *syncPolicyManager) Close() { + m.RLock() + defer m.RUnlock() + + if m.PolicyManager != nil { + m.PolicyManager.Close() + } +} + +func (m *syncPolicyManager) Set(manager PolicyManager) { + if manager == nil { + return + } + + m.Lock() + defer m.Unlock() + + m.PolicyManager = manager +} diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index f56901d50..80e952390 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -4,10 +4,9 @@ package dokodemo import ( "context" + "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -18,36 +17,29 @@ import ( ) type DokodemoDoor struct { - config *Config - address net.Address - port net.Port - policy policy.Policy + policyManager core.PolicyManager + config *Config + address net.Address + port net.Port + v *core.Instance } func New(ctx context.Context, config *Config) (*DokodemoDoor, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") - } if config.NetworkList == nil || config.NetworkList.Size() == 0 { return nil, newError("no network specified") } - d := &DokodemoDoor{ - config: config, - address: config.GetPredefinedAddress(), - port: net.Port(config.Port), + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context.") } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy not found in space.") - } - d.policy = pm.GetPolicy(config.UserLevel) - if config.Timeout > 0 && config.UserLevel == 0 { - d.policy.Timeout.ConnectionIdle.Value = config.Timeout - } - return nil - }) + + d := &DokodemoDoor{ + config: config, + address: config.GetPredefinedAddress(), + port: net.Port(config.Port), + policyManager: v.PolicyManager(), + } + return d, nil } @@ -55,7 +47,16 @@ func (d *DokodemoDoor) Network() net.NetworkList { return *(d.config.NetworkList) } -func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error { +func (d *DokodemoDoor) policy() core.Policy { + config := d.config + p := d.policyManager.ForLevel(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second + } + return p +} + +func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher core.Dispatcher) error { newError("processing connection from: ", conn.RemoteAddr()).AtDebug().WriteToLog() dest := net.Destination{ Network: network, @@ -72,7 +73,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in } ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, d.policy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, d.policy().Timeouts.ConnectionIdle) inboundRay, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -88,7 +89,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("failed to transport request").Base(err) } - timer.SetTimeout(d.policy.Timeout.DownlinkOnly.Duration()) + timer.SetTimeout(d.policy().Timeouts.DownlinkOnly) return nil }) @@ -115,7 +116,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("failed to transport response").Base(err) } - timer.SetTimeout(d.policy.Timeout.UplinkOnly.Duration()) + timer.SetTimeout(d.policy().Timeouts.UplinkOnly) return nil }) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index c7294a527..ef87340f4 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -4,9 +4,9 @@ package freedom import ( "context" + "time" - "v2ray.com/core/app" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/dice" @@ -20,37 +20,35 @@ import ( // Handler handles Freedom connections. type Handler struct { - domainStrategy Config_DomainStrategy - timeout uint32 - destOverride *DestinationOverride - policy policy.Policy + policyManager core.PolicyManager + dns core.DNSClient + config Config } // New creates a new Freedom handler. func New(ctx context.Context, config *Config) (*Handler, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not found in context.") } + f := &Handler{ - domainStrategy: config.DomainStrategy, - timeout: config.Timeout, - destOverride: config.DestinationOverride, + config: *config, + policyManager: v.PolicyManager(), + dns: v.DNSClient(), } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy not found in space.") - } - f.policy = pm.GetPolicy(config.UserLevel) - if config.Timeout > 0 && config.UserLevel == 0 { - f.policy.Timeout.ConnectionIdle.Value = config.Timeout - } - return nil - }) + return f, nil } +func (h *Handler) policy() core.Policy { + p := h.policyManager.ForLevel(h.config.UserLevel) + if h.config.Timeout > 0 && h.config.UserLevel == 0 { + p.Timeouts.ConnectionIdle = time.Duration(h.config.Timeout) * time.Second + } + return p +} + func (h *Handler) resolveIP(ctx context.Context, domain string) net.Address { if resolver, ok := proxy.ResolvedIPsFromContext(ctx); ok { ips := resolver.Resolve() @@ -60,7 +58,7 @@ func (h *Handler) resolveIP(ctx context.Context, domain string) net.Address { return ips[dice.Roll(len(ips))] } - ips, err := net.LookupIP(domain) + ips, err := h.dns.LookupIP(domain) if err != nil { newError("failed to get IP address for domain ", domain).Base(err).WriteToLog() } @@ -73,8 +71,8 @@ func (h *Handler) resolveIP(ctx context.Context, domain string) net.Address { // Process implements proxy.Outbound. func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dialer proxy.Dialer) error { destination, _ := proxy.TargetFromContext(ctx) - if h.destOverride != nil { - server := h.destOverride.Server + if h.config.DestinationOverride != nil { + server := h.config.DestinationOverride.Server destination = net.Destination{ Network: destination.Network, Address: server.Address.AsAddress(), @@ -86,7 +84,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial input := outboundRay.OutboundInput() output := outboundRay.OutboundOutput() - if h.domainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() { + if h.config.DomainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() { ip := h.resolveIP(ctx, destination.Address.Domain()) if ip != nil { destination = net.Destination{ @@ -113,7 +111,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial defer conn.Close() ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, h.policy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, h.policy().Timeouts.ConnectionIdle) requestDone := signal.ExecuteAsync(func() error { var writer buf.Writer @@ -125,7 +123,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to process request").Base(err) } - timer.SetTimeout(h.policy.Timeout.DownlinkOnly.Duration()) + timer.SetTimeout(h.policy().Timeouts.DownlinkOnly) return nil }) @@ -136,7 +134,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if err := buf.Copy(v2reader, output, buf.UpdateActivity(timer)); err != nil { return newError("failed to process response").Base(err) } - timer.SetTimeout(h.policy.Timeout.UplinkOnly.Duration()) + timer.SetTimeout(h.policy().Timeouts.UplinkOnly) return nil }) diff --git a/proxy/http/server.go b/proxy/http/server.go index 6841bfe7a..9179de132 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -10,9 +10,7 @@ import ( "strings" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" @@ -26,32 +24,31 @@ import ( // Server is a HTTP proxy server. type Server struct { config *ServerConfig - policy policy.Policy + v *core.Instance } // NewServer creates a new HTTP inbound handler. func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context.") - } s := &Server{ config: config, + v: core.FromContext(ctx), } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy not found in space.") - } - s.policy = pm.GetPolicy(config.UserLevel) - if config.Timeout > 0 && config.UserLevel == 0 { - s.policy.Timeout.ConnectionIdle.Value = config.Timeout - } - return nil - }) + if s.v == nil { + return nil, newError("V is not in context.") + } + return s, nil } +func (s *Server) policy() core.Policy { + config := s.config + p := s.v.PolicyManager().ForLevel(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second + } + return p +} + func (*Server) Network() net.NetworkList { return net.NetworkList{ Network: []net.Network{net.Network_TCP}, @@ -104,11 +101,11 @@ type readerOnly struct { io.Reader } -func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error { +func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher core.Dispatcher) error { reader := bufio.NewReaderSize(readerOnly{conn}, buf.Size) Start: - conn.SetReadDeadline(time.Now().Add(s.policy.Timeout.Handshake.Duration())) + conn.SetReadDeadline(time.Now().Add(s.policy().Timeouts.Handshake)) request, err := http.ReadRequest(reader) if err != nil { @@ -165,14 +162,14 @@ Start: return err } -func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher dispatcher.Interface) error { +func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher core.Dispatcher) error { _, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) if err != nil { return newError("failed to write back OK response").Base(err) } ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, s.policy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, s.policy().Timeouts.ConnectionIdle) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { return err @@ -191,7 +188,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade requestDone := signal.ExecuteAsync(func() error { defer ray.InboundInput().Close() - defer timer.SetTimeout(s.policy.Timeout.DownlinkOnly.Duration()) + defer timer.SetTimeout(s.policy().Timeouts.DownlinkOnly) v2reader := buf.NewReader(conn) return buf.Copy(v2reader, ray.InboundInput(), buf.UpdateActivity(timer)) @@ -202,7 +199,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade if err := buf.Copy(ray.InboundOutput(), v2writer, buf.UpdateActivity(timer)); err != nil { return err } - timer.SetTimeout(s.policy.Timeout.UplinkOnly.Duration()) + timer.SetTimeout(s.policy().Timeouts.UplinkOnly) return nil }) @@ -217,7 +214,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade var errWaitAnother = newError("keep alive") -func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { +func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher core.Dispatcher) error { if !s.config.AllowTransparent && len(request.URL.Host) <= 0 { // RFC 2068 (HTTP/1.1) requires URL to be absolute URL in HTTP proxy. response := &http.Response{ diff --git a/proxy/proxy.go b/proxy/proxy.go index ea359f630..50162378e 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -10,7 +10,7 @@ package proxy import ( "context" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/common/net" "v2ray.com/core/transport/internet" "v2ray.com/core/transport/ray" @@ -22,7 +22,7 @@ type Inbound interface { Network() net.NetworkList // Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound. - Process(context.Context, net.Network, internet.Connection, dispatcher.Interface) error + Process(context.Context, net.Network, internet.Connection, core.Dispatcher) error } // An Outbound process outbound connections. diff --git a/proxy/shadowsocks/client.go b/proxy/shadowsocks/client.go index 3d5d2be4d..ff19538e6 100644 --- a/proxy/shadowsocks/client.go +++ b/proxy/shadowsocks/client.go @@ -3,8 +3,7 @@ package shadowsocks import ( "context" - "v2ray.com/core/app" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -18,8 +17,8 @@ import ( // Client is a inbound handler for Shadowsocks protocol type Client struct { - serverPicker protocol.ServerPicker - policyManager policy.Manager + serverPicker protocol.ServerPicker + v *core.Instance } // NewClient create a new Shadowsocks client. @@ -33,19 +32,11 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { } client := &Client{ serverPicker: protocol.NewRoundRobinServerPicker(serverList), + v: core.FromContext(ctx), } - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("Space not found.") + if client.v == nil { + return nil, newError("V is not in context.") } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy not found in space.") - } - client.policyManager = pm - return nil - }) return client, nil } @@ -103,9 +94,9 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale request.Option |= RequestOptionOneTimeAuth } - sessionPolicy := v.policyManager.GetPolicy(user.Level) + sessionPolicy := v.v.PolicyManager().ForLevel(user.Level) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) if request.Command == protocol.RequestCommandTCP { bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn)) @@ -119,13 +110,13 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale } requestDone := signal.ExecuteAsync(func() error { - defer timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) + defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) return buf.Copy(outboundRay.OutboundInput(), bodyWriter, buf.UpdateActivity(timer)) }) responseDone := signal.ExecuteAsync(func() error { defer outboundRay.OutboundOutput().Close() - defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) + defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) responseReader, err := ReadTCPResponse(user, conn) if err != nil { diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index afb1812f1..31b345a07 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -4,9 +4,7 @@ import ( "context" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/log" @@ -19,18 +17,14 @@ import ( ) type Server struct { - config *ServerConfig - user *protocol.User - account *MemoryAccount - policyManager policy.Manager + config *ServerConfig + user *protocol.User + account *MemoryAccount + v *core.Instance } // NewServer create a new Shadowsocks server. func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") - } if config.GetUser() == nil { return nil, newError("user is not specified") } @@ -45,16 +39,12 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { config: config, user: config.GetUser(), account: account, + v: core.FromContext(ctx), } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy not found in space.") - } - s.policyManager = pm - return nil - }) + if s.v == nil { + return nil, newError("V is not in context.") + } return s, nil } @@ -69,7 +59,7 @@ func (s *Server) Network() net.NetworkList { return list } -func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error { +func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher core.Dispatcher) error { switch network { case net.Network_TCP: return s.handleConnection(ctx, conn, dispatcher) @@ -80,7 +70,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet } } -func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { +func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection, dispatcher core.Dispatcher) error { udpServer := udp.NewDispatcher(dispatcher) reader := buf.NewReader(conn) @@ -148,9 +138,9 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection return nil } -func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { - sessionPolicy := s.policyManager.GetPolicy(s.user.Level) - conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeout.Handshake.Duration())) +func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher core.Dispatcher) error { + sessionPolicy := s.v.PolicyManager().ForLevel(s.user.Level) + conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)) bufferedReader := buf.NewBufferedReader(buf.NewReader(conn)) request, bodyReader, err := ReadTCPSession(s.user, bufferedReader) if err != nil { @@ -178,7 +168,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, ctx = protocol.ContextWithUser(ctx, request.User) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { return err @@ -208,7 +198,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, return newError("failed to transport all TCP response").Base(err) } - timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) + timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) return nil }) @@ -219,7 +209,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, if err := buf.Copy(bodyReader, ray.InboundInput(), buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP request").Base(err) } - timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) + timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) return nil }) diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 6c6670466..262ef4ad5 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -5,9 +5,7 @@ import ( "io" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/log" @@ -22,32 +20,30 @@ import ( // Server is a SOCKS 5 proxy server type Server struct { config *ServerConfig - policy policy.Policy + v *core.Instance } // NewServer creates a new Server object. func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context").AtWarning() - } s := &Server{ config: config, + v: core.FromContext(ctx), + } + if s.v == nil { + return nil, newError("V is not in context.") } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy not found in space.") - } - s.policy = pm.GetPolicy(config.UserLevel) - if config.Timeout > 0 && config.UserLevel == 0 { - s.policy.Timeout.ConnectionIdle.Value = config.Timeout - } - return nil - }) return s, nil } +func (s *Server) policy() core.Policy { + config := s.config + p := s.v.PolicyManager().ForLevel(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second + } + return p +} + func (s *Server) Network() net.NetworkList { list := net.NetworkList{ Network: []net.Network{net.Network_TCP}, @@ -58,7 +54,7 @@ func (s *Server) Network() net.NetworkList { return list } -func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error { +func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher core.Dispatcher) error { switch network { case net.Network_TCP: return s.processTCP(ctx, conn, dispatcher) @@ -69,8 +65,8 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet } } -func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { - conn.SetReadDeadline(time.Now().Add(s.policy.Timeout.Handshake.Duration())) +func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispatcher core.Dispatcher) error { + conn.SetReadDeadline(time.Now().Add(s.policy().Timeouts.Handshake)) reader := buf.NewBufferedReader(buf.NewReader(conn)) inboundDest, ok := proxy.InboundEntryPointFromContext(ctx) @@ -125,9 +121,9 @@ func (*Server) handleUDP(c net.Conn) error { return err } -func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { +func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher core.Dispatcher) error { ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, v.policy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, v.policy().Timeouts.ConnectionIdle) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -144,7 +140,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ if err := buf.Copy(v2reader, input, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP request").Base(err) } - timer.SetTimeout(v.policy.Timeout.DownlinkOnly.Duration()) + timer.SetTimeout(v.policy().Timeouts.DownlinkOnly) return nil }) @@ -153,7 +149,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ if err := buf.Copy(output, v2writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP response").Base(err) } - timer.SetTimeout(v.policy.Timeout.UplinkOnly.Duration()) + timer.SetTimeout(v.policy().Timeouts.UplinkOnly) return nil }) @@ -166,7 +162,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ return nil } -func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { +func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, dispatcher core.Dispatcher) error { udpServer := udp.NewDispatcher(dispatcher) if source, ok := proxy.SourceFromContext(ctx); ok { diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 4b310f6c1..5021fd5b8 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -8,10 +8,7 @@ import ( "sync" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" - "v2ray.com/core/app/policy" - "v2ray.com/core/app/proxyman" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" @@ -74,21 +71,16 @@ func (v *userByEmail) Get(email string) (*protocol.User, bool) { // Handler is an inbound connection handler that handles messages in VMess protocol. type Handler struct { - inboundHandlerManager proxyman.InboundHandlerManager + policyManager core.PolicyManager + inboundHandlerManager core.InboundHandlerManager clients protocol.UserValidator usersByEmail *userByEmail detours *DetourConfig sessionHistory *encoding.SessionHistory - policyManager policy.Manager } // New creates a new VMess inbound handler. func New(ctx context.Context, config *Config) (*Handler, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context") - } - allowedClients := vmess.NewTimedUserValidator(ctx, protocol.DefaultIDHash) for _, user := range config.User { if err := allowedClients.Add(user); err != nil { @@ -96,24 +88,19 @@ func New(ctx context.Context, config *Config) (*Handler, error) { } } - handler := &Handler{ - clients: allowedClients, - detours: config.Detour, - usersByEmail: newUserByEmail(config.User, config.GetDefaultValue()), - sessionHistory: encoding.NewSessionHistory(ctx), + v := core.FromContext(ctx) + if v == nil { + return nil, newError("V is not in context.") } - space.On(app.SpaceInitializing, func(interface{}) error { - handler.inboundHandlerManager = proxyman.InboundHandlerManagerFromSpace(space) - if handler.inboundHandlerManager == nil { - return newError("InboundHandlerManager is not found is space.") - } - handler.policyManager = policy.FromSpace(space) - if handler.policyManager == nil { - return newError("Policy is not found in space.") - } - return nil - }) + handler := &Handler{ + policyManager: v.PolicyManager(), + inboundHandlerManager: v.InboundHandlerManager(), + clients: allowedClients, + detours: config.Detour, + usersByEmail: newUserByEmail(config.User, config.GetDefaultValue()), + sessionHistory: encoding.NewSessionHistory(ctx), + } return handler, nil } @@ -179,9 +166,9 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess } // Process implements proxy.Inbound.Process(). -func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher dispatcher.Interface) error { - sessionPolicy := h.policyManager.GetPolicy(0) - if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeout.Handshake.Duration())); err != nil { +func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher core.Dispatcher) error { + sessionPolicy := h.policyManager.ForLevel(0) + if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { return newError("unable to set read deadline").Base(err).AtWarning() } @@ -221,11 +208,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i newError("unable to set back read deadline").Base(err).WriteToLog() } - sessionPolicy = h.policyManager.GetPolicy(request.User.Level) + sessionPolicy = h.policyManager.ForLevel(request.User.Level) ctx = protocol.ContextWithUser(ctx, request.User) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) ray, err := dispatcher.Dispatch(ctx, request.Destination()) if err != nil { return newError("failed to dispatch request to ", request.Destination()).Base(err) @@ -235,14 +222,14 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i output := ray.InboundOutput() requestDone := signal.ExecuteAsync(func() error { - defer timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) + defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) return transferRequest(timer, session, request, reader, input) }) responseDone := signal.ExecuteAsync(func() error { writer := buf.NewBufferedWriter(buf.NewWriter(connection)) defer writer.Flush() - defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) + defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) response := &protocol.ResponseHeader{ Command: h.generateCommand(ctx, request), diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 5cc5f818c..d195c8cc4 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -6,8 +6,7 @@ import ( "context" "time" - "v2ray.com/core/app" - "v2ray.com/core/app/policy" + "v2ray.com/core" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -23,17 +22,12 @@ import ( // Handler is an outbound connection handler for VMess protocol. type Handler struct { - serverList *protocol.ServerList - serverPicker protocol.ServerPicker - policyManager policy.Manager + serverList *protocol.ServerList + serverPicker protocol.ServerPicker + v *core.Instance } func New(ctx context.Context, config *Config) (*Handler, error) { - space := app.SpaceFromContext(ctx) - if space == nil { - return nil, newError("no space in context.") - } - serverList := protocol.NewServerList() for _, rec := range config.Receiver { serverList.AddServer(protocol.NewServerSpecFromPB(*rec)) @@ -41,16 +35,12 @@ func New(ctx context.Context, config *Config) (*Handler, error) { handler := &Handler{ serverList: serverList, serverPicker: protocol.NewRoundRobinServerPicker(serverList), + v: core.FromContext(ctx), } - space.On(app.SpaceInitializing, func(interface{}) error { - pm := policy.FromSpace(space) - if pm == nil { - return newError("Policy is not found in space.") - } - handler.policyManager = pm - return nil - }) + if handler.v == nil { + return nil, newError("V is not in context.") + } return handler, nil } @@ -112,10 +102,10 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial output := outboundRay.OutboundOutput() session := encoding.NewClientSession(protocol.DefaultIDHash) - sessionPolicy := v.policyManager.GetPolicy(request.User.Level) + sessionPolicy := v.v.PolicyManager().ForLevel(request.User.Level) ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) requestDone := signal.ExecuteAsync(func() error { writer := buf.NewBufferedWriter(buf.NewWriter(conn)) @@ -148,13 +138,13 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial return err } } - timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) + timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) return nil }) responseDone := signal.ExecuteAsync(func() error { defer output.Close() - defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) + defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) reader := buf.NewBufferedReader(buf.NewReader(conn)) header, err := session.DecodeResponseHeader(reader) diff --git a/router.go b/router.go new file mode 100644 index 000000000..260806203 --- /dev/null +++ b/router.go @@ -0,0 +1,118 @@ +package core + +import ( + "context" + "sync" + + "v2ray.com/core/common/errors" + "v2ray.com/core/common/net" + "v2ray.com/core/transport/ray" +) + +// Dispatcher is a feature that dispatches inbound requests to outbound handlers based on rules. +// Dispatcher is required to be registered in a V2Ray instance to make V2Ray function properly. +type Dispatcher interface { + Feature + + // Dispatch returns a Ray for transporting data for the given request. + Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error) +} + +type syncDispatcher struct { + sync.RWMutex + Dispatcher +} + +func (d *syncDispatcher) Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error) { + d.RLock() + defer d.RUnlock() + + if d.Dispatcher == nil { + return nil, newError("Dispatcher not set.").AtError() + } + + return d.Dispatcher.Dispatch(ctx, dest) +} + +func (d *syncDispatcher) Start() error { + d.RLock() + defer d.RUnlock() + + if d.Dispatcher == nil { + return newError("Dispatcher not set.").AtError() + } + + return d.Dispatcher.Start() +} + +func (d *syncDispatcher) Close() { + d.RLock() + defer d.RUnlock() + + if d.Dispatcher != nil { + d.Dispatcher.Close() + } +} + +func (d *syncDispatcher) Set(disp Dispatcher) { + d.Lock() + defer d.Unlock() + + d.Dispatcher = disp +} + +var ( + // ErrNoClue is for the situation that existing information is not enough to make a decision. For example, Router may return this error when there is no suitable route. + ErrNoClue = errors.New("not enough information for making a decision") +) + +// Router is a feature to choose a outbound tag for the given request. +type Router interface { + Feature + + // PickRoute returns a tag of an OutboundHandler based on the given context. + PickRoute(ctx context.Context) (string, error) +} + +type syncRouter struct { + sync.RWMutex + Router +} + +func (r *syncRouter) PickRoute(ctx context.Context) (string, error) { + r.RLock() + defer r.RUnlock() + + if r.Router == nil { + return "", ErrNoClue + } + + return r.Router.PickRoute(ctx) +} + +func (r *syncRouter) Start() error { + r.RLock() + defer r.RUnlock() + + if r.Router == nil { + return nil + } + + return r.Router.Start() +} + +func (r *syncRouter) Close() { + r.RLock() + defer r.RUnlock() + + if r.Router != nil { + r.Router.Close() + } +} + +func (r *syncRouter) Set(router Router) { + r.Lock() + defer r.Unlock() + + r.Router = router +} diff --git a/testing/scenarios/common.go b/testing/scenarios/common.go index 6d054233f..ebfc663d3 100644 --- a/testing/scenarios/common.go +++ b/testing/scenarios/common.go @@ -13,10 +13,13 @@ import ( "github.com/golang/protobuf/proto" "v2ray.com/core" + "v2ray.com/core/app/dispatcher" + "v2ray.com/core/app/proxyman" "v2ray.com/core/common" "v2ray.com/core/common/log" "v2ray.com/core/common/net" "v2ray.com/core/common/retry" + "v2ray.com/core/common/serial" ) func pickPort() net.Port { @@ -70,6 +73,7 @@ func InitializeServerConfig(config *core.Config) (*exec.Cmd, error) { return nil, err } + config = withDefaultApps(config) configBytes, err := proto.Marshal(config) if err != nil { return nil, err @@ -128,3 +132,10 @@ func CloseAllServers(servers []*exec.Cmd) { Content: "All server closed.", }) } + +func withDefaultApps(config *core.Config) *core.Config { + config.App = append(config.App, serial.ToTypedMessage(&dispatcher.Config{})) + config.App = append(config.App, serial.ToTypedMessage(&proxyman.InboundConfig{})) + config.App = append(config.App, serial.ToTypedMessage(&proxyman.OutboundConfig{})) + return config +} diff --git a/testing/scenarios/dns_test.go b/testing/scenarios/dns_test.go index 665270776..5f168211d 100644 --- a/testing/scenarios/dns_test.go +++ b/testing/scenarios/dns_test.go @@ -51,7 +51,7 @@ func TestResolveIP(t *testing.T) { }, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -67,7 +67,7 @@ func TestResolveIP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&blackhole.Config{}), }, diff --git a/testing/scenarios/dokodemo_test.go b/testing/scenarios/dokodemo_test.go index 110584917..2a821f35b 100644 --- a/testing/scenarios/dokodemo_test.go +++ b/testing/scenarios/dokodemo_test.go @@ -40,7 +40,7 @@ func TestDokodemoTCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -57,7 +57,7 @@ func TestDokodemoTCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -73,7 +73,7 @@ func TestDokodemoTCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: &net.PortRange{From: clientPort, To: clientPort + clientPortRange}, @@ -88,7 +88,7 @@ func TestDokodemoTCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -147,7 +147,7 @@ func TestDokodemoUDP(t *testing.T) { userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -164,7 +164,7 @@ func TestDokodemoUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -174,7 +174,7 @@ func TestDokodemoUDP(t *testing.T) { clientPort := uint32(pickPort()) clientPortRange := uint32(5) clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: &net.PortRange{From: clientPort, To: clientPort + clientPortRange}, @@ -189,7 +189,7 @@ func TestDokodemoUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ diff --git a/testing/scenarios/feature_test.go b/testing/scenarios/feature_test.go index 6c1513142..22c3ff727 100644 --- a/testing/scenarios/feature_test.go +++ b/testing/scenarios/feature_test.go @@ -44,7 +44,7 @@ func TestPassiveConnection(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -59,7 +59,7 @@ func TestPassiveConnection(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -115,7 +115,7 @@ func TestProxy(t *testing.T) { serverUserID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -132,7 +132,7 @@ func TestProxy(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -142,7 +142,7 @@ func TestProxy(t *testing.T) { proxyUserID := protocol.NewID(uuid.New()) proxyPort := pickPort() proxyConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(proxyPort), @@ -159,7 +159,7 @@ func TestProxy(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -168,7 +168,7 @@ func TestProxy(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -183,7 +183,7 @@ func TestProxy(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -263,7 +263,7 @@ func TestProxyOverKCP(t *testing.T) { serverUserID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -283,7 +283,7 @@ func TestProxyOverKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -293,7 +293,7 @@ func TestProxyOverKCP(t *testing.T) { proxyUserID := protocol.NewID(uuid.New()) proxyPort := pickPort() proxyConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(proxyPort), @@ -310,7 +310,7 @@ func TestProxyOverKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ @@ -324,7 +324,7 @@ func TestProxyOverKCP(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -339,7 +339,7 @@ func TestProxyOverKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -429,7 +429,7 @@ func TestBlackhole(t *testing.T) { serverPort := pickPort() serverPort2 := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -457,7 +457,7 @@ func TestBlackhole(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { Tag: "direct", ProxySettings: serial.ToTypedMessage(&freedom.Config{}), @@ -519,7 +519,7 @@ func TestForward(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -535,7 +535,7 @@ func TestForward(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{ DestinationOverride: &freedom.DestinationOverride{ @@ -585,7 +585,7 @@ func TestUDPConnection(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -600,7 +600,7 @@ func TestUDPConnection(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -662,7 +662,7 @@ func TestDomainSniffing(t *testing.T) { sniffingPort := pickPort() httpPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { Tag: "snif", ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -689,7 +689,7 @@ func TestDomainSniffing(t *testing.T) { ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { Tag: "redir", ProxySettings: serial.ToTypedMessage(&freedom.Config{ diff --git a/testing/scenarios/http_test.go b/testing/scenarios/http_test.go index 0e4752aef..942718e33 100644 --- a/testing/scenarios/http_test.go +++ b/testing/scenarios/http_test.go @@ -37,7 +37,7 @@ func TestHttpConformance(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -46,7 +46,7 @@ func TestHttpConformance(t *testing.T) { ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -92,7 +92,7 @@ func TestHttpConnectMethod(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -101,7 +101,7 @@ func TestHttpConnectMethod(t *testing.T) { ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -171,7 +171,7 @@ func TestHttpPost(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -180,7 +180,7 @@ func TestHttpPost(t *testing.T) { ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -237,7 +237,7 @@ func TestHttpBasicAuth(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -250,7 +250,7 @@ func TestHttpBasicAuth(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, diff --git a/testing/scenarios/shadowsocks_test.go b/testing/scenarios/shadowsocks_test.go index 931b64022..7f827bb9b 100644 --- a/testing/scenarios/shadowsocks_test.go +++ b/testing/scenarios/shadowsocks_test.go @@ -49,7 +49,7 @@ func TestShadowsocksAES256TCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -63,7 +63,7 @@ func TestShadowsocksAES256TCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -78,7 +78,7 @@ func TestShadowsocksAES256TCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -93,7 +93,7 @@ func TestShadowsocksAES256TCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -167,7 +167,7 @@ func TestShadowsocksAES128UDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -182,7 +182,7 @@ func TestShadowsocksAES128UDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -197,7 +197,7 @@ func TestShadowsocksAES128UDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -212,7 +212,7 @@ func TestShadowsocksAES128UDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -286,7 +286,7 @@ func TestShadowsocksChacha20TCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -300,7 +300,7 @@ func TestShadowsocksChacha20TCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -315,7 +315,7 @@ func TestShadowsocksChacha20TCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -330,7 +330,7 @@ func TestShadowsocksChacha20TCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -403,7 +403,7 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -417,7 +417,7 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -432,7 +432,7 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -447,7 +447,7 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -520,7 +520,7 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -535,7 +535,7 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -550,7 +550,7 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -565,7 +565,7 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -638,7 +638,7 @@ func TestShadowsocksAES256GCMConformance(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -652,7 +652,7 @@ func TestShadowsocksAES256GCMConformance(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -716,7 +716,7 @@ func TestShadowsocksChacha20Poly1305UDPConformance(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -731,7 +731,7 @@ func TestShadowsocksChacha20Poly1305UDPConformance(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -799,7 +799,7 @@ func TestShadowsocksChacha20Conformance(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -813,7 +813,7 @@ func TestShadowsocksChacha20Conformance(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, diff --git a/testing/scenarios/socks_test.go b/testing/scenarios/socks_test.go index 5351ad1c6..04ebe9660 100644 --- a/testing/scenarios/socks_test.go +++ b/testing/scenarios/socks_test.go @@ -30,7 +30,7 @@ func TestSocksBridgeTCP(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -46,7 +46,7 @@ func TestSocksBridgeTCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -55,7 +55,7 @@ func TestSocksBridgeTCP(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -70,7 +70,7 @@ func TestSocksBridgeTCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -127,7 +127,7 @@ func TestSocksBridageUDP(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -143,7 +143,7 @@ func TestSocksBridageUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -152,7 +152,7 @@ func TestSocksBridageUDP(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -167,7 +167,7 @@ func TestSocksBridageUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{ Server: []*protocol.ServerEndpoint{ @@ -225,7 +225,7 @@ func TestSocksConformance(t *testing.T) { authPort := pickPort() noAuthPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(authPort), @@ -255,7 +255,7 @@ func TestSocksConformance(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, diff --git a/testing/scenarios/tls_test.go b/testing/scenarios/tls_test.go index 76987d7a3..c6d5505d4 100644 --- a/testing/scenarios/tls_test.go +++ b/testing/scenarios/tls_test.go @@ -38,7 +38,7 @@ func TestSimpleTLSConnection(t *testing.T) { userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -63,7 +63,7 @@ func TestSimpleTLSConnection(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -72,7 +72,7 @@ func TestSimpleTLSConnection(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -87,7 +87,7 @@ func TestSimpleTLSConnection(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -152,7 +152,7 @@ func TestTLSOverKCP(t *testing.T) { userID := protocol.NewID(uuid.New()) serverPort := udp.PickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -178,7 +178,7 @@ func TestTLSOverKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -187,7 +187,7 @@ func TestTLSOverKCP(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -202,7 +202,7 @@ func TestTLSOverKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -268,7 +268,7 @@ func TestTLSOverWebSocket(t *testing.T) { userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -294,7 +294,7 @@ func TestTLSOverWebSocket(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -303,7 +303,7 @@ func TestTLSOverWebSocket(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -318,7 +318,7 @@ func TestTLSOverWebSocket(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ diff --git a/testing/scenarios/transport_test.go b/testing/scenarios/transport_test.go index a657366e8..253cd2806 100644 --- a/testing/scenarios/transport_test.go +++ b/testing/scenarios/transport_test.go @@ -35,7 +35,7 @@ func TestHttpConnectionHeader(t *testing.T) { userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -62,7 +62,7 @@ func TestHttpConnectionHeader(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -71,7 +71,7 @@ func TestHttpConnectionHeader(t *testing.T) { clientPort := pickPort() clientConfig := &core.Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -86,7 +86,7 @@ func TestHttpConnectionHeader(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ diff --git a/testing/scenarios/vmess_test.go b/testing/scenarios/vmess_test.go index 9b494fb91..c392d91f2 100644 --- a/testing/scenarios/vmess_test.go +++ b/testing/scenarios/vmess_test.go @@ -44,7 +44,7 @@ func TestVMessDynamicPort(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -84,7 +84,7 @@ func TestVMessDynamicPort(t *testing.T) { Tag: "detour", }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -99,7 +99,7 @@ func TestVMessDynamicPort(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -114,7 +114,7 @@ func TestVMessDynamicPort(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -179,7 +179,7 @@ func TestVMessGCM(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -197,7 +197,7 @@ func TestVMessGCM(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -212,7 +212,7 @@ func TestVMessGCM(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -227,7 +227,7 @@ func TestVMessGCM(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -302,7 +302,7 @@ func TestVMessGCMUDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -320,7 +320,7 @@ func TestVMessGCMUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -335,7 +335,7 @@ func TestVMessGCMUDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -350,7 +350,7 @@ func TestVMessGCMUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -435,7 +435,7 @@ func TestVMessChacha20(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -453,7 +453,7 @@ func TestVMessChacha20(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -468,7 +468,7 @@ func TestVMessChacha20(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -483,7 +483,7 @@ func TestVMessChacha20(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -558,7 +558,7 @@ func TestVMessNone(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -576,7 +576,7 @@ func TestVMessNone(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -591,7 +591,7 @@ func TestVMessNone(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -606,7 +606,7 @@ func TestVMessNone(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -683,7 +683,7 @@ func TestVMessKCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -704,7 +704,7 @@ func TestVMessKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -719,7 +719,7 @@ func TestVMessKCP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -734,7 +734,7 @@ func TestVMessKCP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -816,7 +816,7 @@ func TestVMessIPv6(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -834,7 +834,7 @@ func TestVMessIPv6(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -849,7 +849,7 @@ func TestVMessIPv6(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -864,7 +864,7 @@ func TestVMessIPv6(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{ @@ -931,7 +931,7 @@ func TestVMessGCMMux(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -949,7 +949,7 @@ func TestVMessGCMMux(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -964,7 +964,7 @@ func TestVMessGCMMux(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -979,7 +979,7 @@ func TestVMessGCMMux(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ MultiplexSettings: &proxyman.MultiplexingConfig{ @@ -1073,7 +1073,7 @@ func TestVMessGCMMuxUDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(serverPort), @@ -1091,7 +1091,7 @@ func TestVMessGCMMuxUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, @@ -1107,7 +1107,7 @@ func TestVMessGCMMuxUDP(t *testing.T) { ErrorLogType: log.LogType_Console, }), }, - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(clientPort), @@ -1135,7 +1135,7 @@ func TestVMessGCMMuxUDP(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{ MultiplexSettings: &proxyman.MultiplexingConfig{ diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go index 80e4e5c21..ff89b9c73 100644 --- a/transport/internet/config.pb.go +++ b/transport/internet/config.pb.go @@ -46,7 +46,7 @@ func (TransportProtocol) EnumDescriptor() ([]byte, []int) { return fileDescripto type TransportConfig struct { // Type of network that this settings supports. Protocol TransportProtocol `protobuf:"varint,1,opt,name=protocol,enum=v2ray.core.transport.internet.TransportProtocol" json:"protocol,omitempty"` - // Specific settings. + // Specific settings. Must be of the transports. Settings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=settings" json:"settings,omitempty"` } @@ -74,7 +74,8 @@ type StreamConfig struct { Protocol TransportProtocol `protobuf:"varint,1,opt,name=protocol,enum=v2ray.core.transport.internet.TransportProtocol" json:"protocol,omitempty"` TransportSettings []*TransportConfig `protobuf:"bytes,2,rep,name=transport_settings,json=transportSettings" json:"transport_settings,omitempty"` // Type of security. Must be a message name of the settings proto. - SecurityType string `protobuf:"bytes,3,opt,name=security_type,json=securityType" json:"security_type,omitempty"` + SecurityType string `protobuf:"bytes,3,opt,name=security_type,json=securityType" json:"security_type,omitempty"` + // Settings for transport security. For now the only choice is TLS. SecuritySettings []*v2ray_core_common_serial.TypedMessage `protobuf:"bytes,4,rep,name=security_settings,json=securitySettings" json:"security_settings,omitempty"` } diff --git a/transport/internet/udp/dispatcher.go b/transport/internet/udp/dispatcher.go index 72cd30710..0db6ae54c 100644 --- a/transport/internet/udp/dispatcher.go +++ b/transport/internet/udp/dispatcher.go @@ -5,7 +5,7 @@ import ( "sync" "time" - "v2ray.com/core/app/dispatcher" + "v2ray.com/core" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/signal" @@ -23,10 +23,10 @@ type connEntry struct { type Dispatcher struct { sync.RWMutex conns map[net.Destination]*connEntry - dispatcher dispatcher.Interface + dispatcher core.Dispatcher } -func NewDispatcher(dispatcher dispatcher.Interface) *Dispatcher { +func NewDispatcher(dispatcher core.Dispatcher) *Dispatcher { return &Dispatcher{ conns: make(map[net.Destination]*connEntry), dispatcher: dispatcher, diff --git a/v2ray.go b/v2ray.go index f6fcb49ea..0bbb50e52 100644 --- a/v2ray.go +++ b/v2ray.go @@ -3,139 +3,160 @@ package core import ( "context" - "v2ray.com/core/app" - "v2ray.com/core/app/dispatcher" - "v2ray.com/core/app/policy" - "v2ray.com/core/app/proxyman" "v2ray.com/core/common" ) // Server is an instance of V2Ray. At any time, there must be at most one Server instance running. +// Deprecated. Use Instance directly. type Server interface { - // Start starts the V2Ray server, and return any error during the process. - // In the case of any errors, the state of the server is unpredicatable. - Start() error - - // Close closes the V2Ray server. All inbound and outbound connections will be closed immediately. - Close() + common.Runnable } -// New creates a new V2Ray server with given config. -func New(config *Config) (Server, error) { - return newSimpleServer(config) +// Feature is the interface for V2Ray features. All features must implement this interface. +// All existing features have an implementation in app directory. These features can be replaced by third-party ones. +type Feature interface { + common.Runnable } -// simpleServer shell of V2Ray. -type simpleServer struct { - space app.Space +// Instance combines all functionalities in V2Ray. +type Instance struct { + dnsClient syncDNSClient + policyManager syncPolicyManager + dispatcher syncDispatcher + router syncRouter + ihm syncInboundHandlerManager + ohm syncOutboundHandlerManager + + features []Feature } -// newSimpleServer returns a new Point server based on given configuration. -// The server is not started at this point. -func newSimpleServer(config *Config) (*simpleServer, error) { - var server = new(simpleServer) +// New returns a new V2Ray instance based on given configuration. +// The instance is not started at this point. +// To make sure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional. +func New(config *Config) (*Instance, error) { + var server = new(Instance) if err := config.Transport.Apply(); err != nil { return nil, err } - space := app.NewSpace() - ctx := app.ContextWithSpace(context.Background(), space) - - server.space = space + ctx := context.WithValue(context.Background(), v2rayKey, server) for _, appSettings := range config.App { settings, err := appSettings.GetInstance() if err != nil { return nil, err } - application, err := app.CreateAppFromConfig(ctx, settings) + app, err := common.CreateObject(ctx, settings) if err != nil { return nil, err } - if err := space.AddApplication(application); err != nil { - return nil, err + f, ok := app.(Feature) + if !ok { + return nil, newError("not a feature") } - } - - outboundHandlerManager := proxyman.OutboundHandlerManagerFromSpace(space) - if outboundHandlerManager == nil { - o, err := app.CreateAppFromConfig(ctx, new(proxyman.OutboundConfig)) - if err != nil { - return nil, err - } - if err := space.AddApplication(o); err != nil { - return nil, newError("failed to add default outbound handler manager").Base(err) - } - outboundHandlerManager = o.(proxyman.OutboundHandlerManager) - } - - inboundHandlerManager := proxyman.InboundHandlerManagerFromSpace(space) - if inboundHandlerManager == nil { - o, err := app.CreateAppFromConfig(ctx, new(proxyman.InboundConfig)) - if err != nil { - return nil, err - } - if err := space.AddApplication(o); err != nil { - return nil, newError("failed to add default inbound handler manager").Base(err) - } - inboundHandlerManager = o.(proxyman.InboundHandlerManager) - } - - if disp := dispatcher.FromSpace(space); disp == nil { - d, err := app.CreateAppFromConfig(ctx, new(dispatcher.Config)) - if err != nil { - return nil, err - } - common.Must(space.AddApplication(d)) - } - - if p := policy.FromSpace(space); p == nil { - p, err := app.CreateAppFromConfig(ctx, &policy.Config{ - Level: map[uint32]*policy.Policy{ - 1: { - Timeout: &policy.Policy_Timeout{ - ConnectionIdle: &policy.Second{ - Value: 600, - }, - }, - }, - }, - }) - if err != nil { - return nil, err - } - common.Must(space.AddApplication(p)) + server.features = append(server.features, f) } for _, inbound := range config.Inbound { - if err := inboundHandlerManager.AddHandler(ctx, inbound); err != nil { + rawHandler, err := common.CreateObject(ctx, inbound) + if err != nil { + return nil, err + } + handler, ok := rawHandler.(InboundHandler) + if !ok { + return nil, newError("not an InboundHandler") + } + if err := server.InboundHandlerManager().AddHandler(ctx, handler); err != nil { return nil, err } } for _, outbound := range config.Outbound { - if err := outboundHandlerManager.AddHandler(ctx, outbound); err != nil { + rawHandler, err := common.CreateObject(ctx, outbound) + if err != nil { + return nil, err + } + handler, ok := rawHandler.(OutboundHandler) + if !ok { + return nil, newError("not an OutboundHandler") + } + if err := server.OutboundHandlerManager().AddHandler(ctx, handler); err != nil { return nil, err } - } - - if err := server.space.Initialize(); err != nil { - return nil, err } return server, nil } -func (s *simpleServer) Close() { - s.space.Close() +// Close shutdown the V2Ray instance. +func (s *Instance) Close() { + for _, f := range s.features { + f.Close() + } } -func (s *simpleServer) Start() error { - if err := s.space.Start(); err != nil { - return err +// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown. +func (s *Instance) Start() error { + for _, f := range s.features { + if err := f.Start(); err != nil { + return nil + } } + newError("V2Ray started").AtWarning().WriteToLog() return nil } + +// RegisterFeature registers the given feature into V2Ray. +// If feature is one of the following types, the corressponding feature in this Instance +// will be replaced: DNSClient, PolicyManager, Router, Dispatcher, InboundHandlerManager, OutboundHandlerManager. +func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error { + switch feature.(type) { + case DNSClient, *DNSClient: + s.dnsClient.Set(instance.(DNSClient)) + case PolicyManager, *PolicyManager: + s.policyManager.Set(instance.(PolicyManager)) + case Router, *Router: + s.router.Set(instance.(Router)) + case Dispatcher, *Dispatcher: + s.dispatcher.Set(instance.(Dispatcher)) + case InboundHandlerManager, *InboundHandlerManager: + s.ihm.Set(instance.(InboundHandlerManager)) + case OutboundHandlerManager, *OutboundHandlerManager: + s.ohm.Set(instance.(OutboundHandlerManager)) + } + s.features = append(s.features, instance) + return nil +} + +// DNSClient returns the DNSClient used by this Instance. The returned DNSClient is always functional. +func (s *Instance) DNSClient() DNSClient { + return &(s.dnsClient) +} + +// PolicyManager returns the PolicyManager used by this Instance. The returned PolicyManager is always functional. +func (s *Instance) PolicyManager() PolicyManager { + return &(s.policyManager) +} + +// Router returns the Router used by this Instance. The returned Router is always functional. +func (s *Instance) Router() Router { + return &(s.router) +} + +// Dispatcher returns the Dispatcher used by this Instance. If Dispatcher was not registered before, the returned value doesn't work, although it is not nil. +func (s *Instance) Dispatcher() Dispatcher { + return &(s.dispatcher) +} + +// InboundHandlerManager returns the InboundHandlerManager used by this Instance. If InboundHandlerManager was not registered before, the returned value doesn't work. +func (s *Instance) InboundHandlerManager() InboundHandlerManager { + return &(s.ihm) +} + +// OutboundHandlerManager returns the OutboundHandlerManager used by this Instance. If OutboundHandlerManager was not registered before, the returned value doesn't work. +func (s *Instance) OutboundHandlerManager() OutboundHandlerManager { + return &(s.ohm) +} diff --git a/v2ray_test.go b/v2ray_test.go index 4374340c3..6d18c62b1 100644 --- a/v2ray_test.go +++ b/v2ray_test.go @@ -22,7 +22,7 @@ func TestV2RayClose(t *testing.T) { port := net.Port(dice.RollUint16()) config := &Config{ - Inbound: []*proxyman.InboundHandlerConfig{ + Inbound: []*core.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ PortRange: net.SinglePortRange(port), @@ -37,7 +37,7 @@ func TestV2RayClose(t *testing.T) { }), }, }, - Outbound: []*proxyman.OutboundHandlerConfig{ + Outbound: []*core.OutboundHandlerConfig{ { ProxySettings: serial.ToTypedMessage(&outbound.Config{ Receiver: []*protocol.ServerEndpoint{