diff --git a/app/api/api.go b/app/api/api.go index 6243c94f2..21e278905 100644 --- a/app/api/api.go +++ b/app/api/api.go @@ -1,12 +1,4 @@ package api -import ( - "v2ray.com/core/app" -) - -const ( - APP_ID = app.ID(5) -) - type ApiServer struct { } diff --git a/app/dispatcher/dispatcher.go b/app/dispatcher/dispatcher.go index eb73ee1db..a73384ffc 100644 --- a/app/dispatcher/dispatcher.go +++ b/app/dispatcher/dispatcher.go @@ -2,15 +2,19 @@ package dispatcher import ( "v2ray.com/core/app" + "v2ray.com/core/common/serial" "v2ray.com/core/proxy" "v2ray.com/core/transport/ray" ) -const ( - APP_ID = app.ID(1) -) - // PacketDispatcher dispatch a packet and possibly further network payload to its destination. type PacketDispatcher interface { DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay } + +func FromSpace(space app.Space) PacketDispatcher { + if app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil))); app != nil { + return app.(PacketDispatcher) + } + return nil +} diff --git a/app/dispatcher/impl/default.go b/app/dispatcher/impl/default.go index cd7a8aac8..6c6548c52 100644 --- a/app/dispatcher/impl/default.go +++ b/app/dispatcher/impl/default.go @@ -7,11 +7,11 @@ import ( "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/proxyman" "v2ray.com/core/app/router" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" "v2ray.com/core/common/log" v2net "v2ray.com/core/common/net" - "v2ray.com/core/common/serial" "v2ray.com/core/proxy" "v2ray.com/core/transport/ray" ) @@ -23,27 +23,17 @@ type DefaultDispatcher struct { func NewDefaultDispatcher(space app.Space) *DefaultDispatcher { d := &DefaultDispatcher{} - space.InitializeApplication(func() error { - return d.Initialize(space) + space.OnInitialize(func() error { + d.ohm = proxyman.OutboundHandlerManagerFromSpace(space) + if d.ohm == nil { + return errors.New("DefaultDispatcher: OutboundHandlerManager is not found in the space.") + } + d.router = router.FromSpace(space) + return nil }) return d } -// Initialize initializes the dispatcher. -// Private: Used by app.Space only. -func (v *DefaultDispatcher) Initialize(space app.Space) error { - if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) { - return errors.New("DefaultDispatcher: OutboundHandlerManager is not found in the space.") - } - v.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager) - - if space.HasApp(router.APP_ID) { - v.router = space.GetApp(router.APP_ID).(*router.Router) - } - - return nil -} - func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay { dispatcher := v.ohm.GetDefaultHandler() destination := session.Destination @@ -95,12 +85,8 @@ func (v DefaultDispatcherFactory) Create(space app.Space, config interface{}) (a return NewDefaultDispatcher(space), nil } -func (v DefaultDispatcherFactory) AppId() app.ID { - return dispatcher.APP_ID -} - func init() { - app.RegisterApplicationFactory(serial.GetMessageType(new(dispatcher.Config)), DefaultDispatcherFactory{}) + common.Must(app.RegisterApplicationFactory((*dispatcher.Config)(nil), DefaultDispatcherFactory{})) } type waitDataInspector struct { diff --git a/app/dispatcher/testing/dispatcher.go b/app/dispatcher/testing/dispatcher.go deleted file mode 100644 index dfea35799..000000000 --- a/app/dispatcher/testing/dispatcher.go +++ /dev/null @@ -1,44 +0,0 @@ -package testing - -import ( - "v2ray.com/core/common/buf" - v2net "v2ray.com/core/common/net" - "v2ray.com/core/proxy" - "v2ray.com/core/transport/ray" -) - -type TestPacketDispatcher struct { - Destination chan v2net.Destination - Handler func(destination v2net.Destination, traffic ray.OutboundRay) -} - -func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic ray.OutboundRay)) *TestPacketDispatcher { - if handler == nil { - handler = func(destination v2net.Destination, traffic ray.OutboundRay) { - for { - payload, err := traffic.OutboundInput().Read() - if err != nil { - break - } - output := buf.New() - output.Append([]byte("Processed: ")) - output.Append(payload.Bytes()) - payload.Release() - traffic.OutboundOutput().Write(output) - } - traffic.OutboundOutput().Close() - } - } - return &TestPacketDispatcher{ - Destination: make(chan v2net.Destination), - Handler: handler, - } -} - -func (v *TestPacketDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay { - traffic := ray.NewRay() - v.Destination <- session.Destination - go v.Handler(session.Destination, traffic) - - return traffic -} diff --git a/app/dns/dns.go b/app/dns/dns.go index b84ae1d39..85f7f58b3 100644 --- a/app/dns/dns.go +++ b/app/dns/dns.go @@ -4,13 +4,18 @@ import ( "net" "v2ray.com/core/app" -) - -const ( - APP_ID = app.ID(2) + "v2ray.com/core/common/serial" ) // A DnsCache is an internal cache of DNS resolutions. type Server interface { Get(domain string) []net.IP } + +func FromSpace(space app.Space) Server { + app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil))) + if app == nil { + return nil + } + return app.(Server) +} diff --git a/app/dns/server/server.go b/app/dns/server/server.go index 7d4a39ecd..ef326cb5f 100644 --- a/app/dns/server/server.go +++ b/app/dns/server/server.go @@ -8,10 +8,10 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dns" + "v2ray.com/core/common" "v2ray.com/core/common/errors" "v2ray.com/core/common/log" v2net "v2ray.com/core/common/net" - "v2ray.com/core/common/serial" dnsmsg "github.com/miekg/dns" ) @@ -38,12 +38,11 @@ func NewCacheServer(space app.Space, config *dns.Config) *CacheServer { servers: make([]NameServer, len(config.NameServers)), hosts: config.GetInternalHosts(), } - space.InitializeApplication(func() error { - if !space.HasApp(dispatcher.APP_ID) { + space.OnInitialize(func() error { + disp := dispatcher.FromSpace(space) + if disp == nil { return errors.New("DNS: Dispatcher is not found in the space.") } - - dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher) for idx, destPB := range config.NameServers { address := destPB.Address.AsAddress() if address.Family().IsDomain() && address.Domain() == "localhost" { @@ -54,7 +53,7 @@ func NewCacheServer(space app.Space, config *dns.Config) *CacheServer { dest.Network = v2net.Network_UDP } if dest.Network == v2net.Network_UDP { - server.servers[idx] = NewUDPNameServer(dest, dispatcher) + server.servers[idx] = NewUDPNameServer(dest, disp) } } } @@ -117,10 +116,6 @@ func (v CacheServerFactory) Create(space app.Space, config interface{}) (app.App return server, nil } -func (v CacheServerFactory) AppId() app.ID { - return dns.APP_ID -} - func init() { - app.RegisterApplicationFactory(serial.GetMessageType(new(dns.Config)), CacheServerFactory{}) + common.Must(app.RegisterApplicationFactory((*dns.Config)(nil), CacheServerFactory{})) } diff --git a/app/proxy/config.pb.go b/app/proxy/config.pb.go new file mode 100644 index 000000000..dfc5c99a7 --- /dev/null +++ b/app/proxy/config.pb.go @@ -0,0 +1,42 @@ +package proxy + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Config struct { +} + +func (m *Config) Reset() { *m = Config{} } +func (m *Config) String() string { return proto.CompactTextString(m) } +func (*Config) ProtoMessage() {} +func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func init() { + proto.RegisterType((*Config)(nil), "v2ray.core.app.proxy.Config") +} + +func init() { proto.RegisterFile("v2ray.com/core/app/proxy/config.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 128 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2d, 0x33, 0x2a, 0x4a, + 0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0x2c, 0x28, 0xd0, 0x2f, + 0x28, 0xca, 0xaf, 0xa8, 0xd4, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x12, 0x81, 0x29, 0x2b, 0x4a, 0xd5, 0x4b, 0x2c, 0x28, 0xd0, 0x03, 0x2b, 0x51, 0xe2, + 0xe0, 0x62, 0x73, 0x06, 0xab, 0x72, 0x72, 0xe5, 0x92, 0x48, 0xce, 0xcf, 0xd5, 0xc3, 0xa6, 0xca, + 0x89, 0x1b, 0xa2, 0x26, 0x00, 0x64, 0x50, 0x14, 0x2b, 0x58, 0x6c, 0x15, 0x93, 0x48, 0x98, 0x51, + 0x50, 0x62, 0xa5, 0x9e, 0x33, 0x48, 0xa9, 0x63, 0x41, 0x81, 0x5e, 0x00, 0x48, 0x38, 0x89, 0x0d, + 0x6c, 0x9b, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x16, 0xbe, 0x54, 0x50, 0x96, 0x00, 0x00, 0x00, +} diff --git a/app/proxy/config.proto b/app/proxy/config.proto new file mode 100644 index 000000000..c2616aa90 --- /dev/null +++ b/app/proxy/config.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package v2ray.core.app.proxy; +option csharp_namespace = "V2Ray.Core.App.Proxy"; +option go_package = "proxy"; +option java_package = "com.v2ray.core.app.proxy"; +option java_outer_classname = "ConfigProto"; + +message Config { +} diff --git a/app/proxy/proxy.go b/app/proxy/proxy.go index b6007618a..1a610cefc 100644 --- a/app/proxy/proxy.go +++ b/app/proxy/proxy.go @@ -7,29 +7,27 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/proxyman" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" "v2ray.com/core/common/log" v2net "v2ray.com/core/common/net" + "v2ray.com/core/common/serial" "v2ray.com/core/transport/internet" "v2ray.com/core/transport/ray" ) -const ( - APP_ID = 7 -) - type OutboundProxy struct { outboundManager proxyman.OutboundHandlerManager } func NewOutboundProxy(space app.Space) *OutboundProxy { proxy := new(OutboundProxy) - space.InitializeApplication(func() error { - if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) { - return errors.New("Proxy: Outbound handler manager not found.") + space.OnInitialize(func() error { + proxy.outboundManager = proxyman.OutboundHandlerManagerFromSpace(space) + if proxy.outboundManager == nil { + return errors.New("Proxy: Outbound handler manager not found in space.") } - proxy.outboundManager = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager) return nil }) return proxy @@ -133,3 +131,21 @@ func (v *Connection) Reusable() bool { func (v *Connection) SetReusable(bool) { } + +type OutboundProxyFactory struct{} + +func (OutboundProxyFactory) Create(space app.Space, config interface{}) (app.Application, error) { + return NewOutboundProxy(space), nil +} + +func OutboundProxyFromSpace(space app.Space) *OutboundProxy { + app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil))) + if app == nil { + return nil + } + return app.(*OutboundProxy) +} + +func init() { + common.Must(app.RegisterApplicationFactory((*Config)(nil), OutboundProxyFactory{})) +} diff --git a/app/proxy/proxy_test.go b/app/proxy/proxy_test.go index 0500f44a1..ba771db38 100644 --- a/app/proxy/proxy_test.go +++ b/app/proxy/proxy_test.go @@ -6,7 +6,7 @@ import ( "v2ray.com/core/app" . "v2ray.com/core/app/proxy" "v2ray.com/core/app/proxyman" - "v2ray.com/core/app/proxyman/outbound" + _ "v2ray.com/core/app/proxyman/outbound" "v2ray.com/core/common" v2net "v2ray.com/core/common/net" "v2ray.com/core/proxy" @@ -21,17 +21,17 @@ func TestProxyDial(t *testing.T) { assert := assert.On(t) space := app.NewSpace() - outboundManager := outbound.New() + assert.Error(space.AddApp(new(proxyman.OutboundConfig))) + outboundManager := proxyman.OutboundHandlerManagerFromSpace(space) common.Must(outboundManager.SetHandler("tag", freedom.New(&freedom.Config{}, space, &proxy.OutboundHandlerMeta{ Tag: "tag", StreamSettings: &internet.StreamConfig{ Network: v2net.Network_TCP, }, }))) - space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundManager) - proxy := NewOutboundProxy(space) - space.BindApp(APP_ID, proxy) + assert.Error(space.AddApp(new(Config))).IsNil() + proxy := OutboundProxyFromSpace(space) assert.Error(space.Initialize()).IsNil() diff --git a/app/proxyman/outbound/outbound.go b/app/proxyman/outbound/outbound.go index 9b9d5a463..e957baf81 100644 --- a/app/proxyman/outbound/outbound.go +++ b/app/proxyman/outbound/outbound.go @@ -5,7 +5,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/proxyman" - "v2ray.com/core/common/serial" + "v2ray.com/core/common" "v2ray.com/core/proxy" ) @@ -60,10 +60,6 @@ func (v OutboundHandlerManagerFactory) Create(space app.Space, config interface{ return New(), nil } -func (v OutboundHandlerManagerFactory) AppId() app.ID { - return proxyman.APP_ID_OUTBOUND_MANAGER -} - func init() { - app.RegisterApplicationFactory(serial.GetMessageType(new(proxyman.OutboundConfig)), OutboundHandlerManagerFactory{}) + common.Must(app.RegisterApplicationFactory((*proxyman.OutboundConfig)(nil), OutboundHandlerManagerFactory{})) } diff --git a/app/proxyman/proxyman.go b/app/proxyman/proxyman.go index 6ad28f0f5..1bff9a674 100644 --- a/app/proxyman/proxyman.go +++ b/app/proxyman/proxyman.go @@ -3,14 +3,10 @@ package proxyman import ( "v2ray.com/core/app" + "v2ray.com/core/common/serial" "v2ray.com/core/proxy" ) -const ( - APP_ID_INBOUND_MANAGER = app.ID(4) - APP_ID_OUTBOUND_MANAGER = app.ID(6) -) - type InboundHandlerManager interface { GetHandler(tag string) (proxy.InboundHandler, int) } @@ -21,3 +17,19 @@ type OutboundHandlerManager interface { SetDefaultHandler(handler proxy.OutboundHandler) error SetHandler(tag string, handler proxy.OutboundHandler) error } + +func InboundHandlerManagerFromSpace(space app.Space) InboundHandlerManager { + app := space.(app.AppGetter).GetApp(serial.GetMessageType((*InboundConfig)(nil))) + if app == nil { + return nil + } + return app.(InboundHandlerManager) +} + +func OutboundHandlerManagerFromSpace(space app.Space) OutboundHandlerManager { + app := space.(app.AppGetter).GetApp(serial.GetMessageType((*OutboundConfig)(nil))) + if app == nil { + return nil + } + return app.(OutboundHandlerManager) +} diff --git a/app/router/router.go b/app/router/router.go index cf2802bec..35c98efbd 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -3,6 +3,7 @@ package router import ( "v2ray.com/core/app" "v2ray.com/core/app/dns" + "v2ray.com/core/common" "v2ray.com/core/common/errors" "v2ray.com/core/common/log" v2net "v2ray.com/core/common/net" @@ -10,10 +11,6 @@ import ( "v2ray.com/core/proxy" ) -const ( - APP_ID = app.ID(3) -) - var ( ErrInvalidRule = errors.New("Invalid Rule") ErrNoRuleApplicable = errors.New("No rule applicable") @@ -33,7 +30,7 @@ func NewRouter(config *Config, space app.Space) *Router { rules: make([]Rule, len(config.Rule)), } - space.InitializeApplication(func() error { + space.OnInitialize(func() error { for idx, rule := range config.Rule { r.rules[idx].Tag = rule.Tag cond, err := rule.BuildCondition() @@ -43,10 +40,10 @@ func NewRouter(config *Config, space app.Space) *Router { r.rules[idx].Condition = cond } - if !space.HasApp(dns.APP_ID) { + r.dnsServer = dns.FromSpace(space) + if r.dnsServer == nil { return errors.New("Router: DNS is not found in the space.") } - r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server) return nil }) return r @@ -116,10 +113,14 @@ func (RouterFactory) Create(space app.Space, config interface{}) (app.Applicatio return router, nil } -func (RouterFactory) AppId() app.ID { - return APP_ID +func FromSpace(space app.Space) *Router { + app := space.(app.AppGetter).GetApp(serial.GetMessageType((*Config)(nil))) + if app == nil { + return nil + } + return app.(*Router) } func init() { - app.RegisterApplicationFactory(serial.GetMessageType(new(Config)), RouterFactory{}) + common.Must(app.RegisterApplicationFactory((*Config)(nil), RouterFactory{})) } diff --git a/app/router/router_test.go b/app/router/router_test.go index da2f75d97..a298987e7 100644 --- a/app/router/router_test.go +++ b/app/router/router_test.go @@ -5,11 +5,11 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" - dispatchers "v2ray.com/core/app/dispatcher/impl" + _ "v2ray.com/core/app/dispatcher/impl" "v2ray.com/core/app/dns" - dnsserver "v2ray.com/core/app/dns/server" + _ "v2ray.com/core/app/dns/server" "v2ray.com/core/app/proxyman" - "v2ray.com/core/app/proxyman/outbound" + _ "v2ray.com/core/app/proxyman/outbound" . "v2ray.com/core/app/router" v2net "v2ray.com/core/common/net" "v2ray.com/core/proxy" @@ -31,13 +31,14 @@ func TestSimpleRouter(t *testing.T) { } space := app.NewSpace() - space.BindApp(dns.APP_ID, dnsserver.NewCacheServer(space, &dns.Config{})) - space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) - space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outbound.New()) - r := NewRouter(config, space) - space.BindApp(APP_ID, r) + assert.Error(space.AddApp(new(dns.Config))).IsNil() + assert.Error(space.AddApp(new(dispatcher.Config))).IsNil() + assert.Error(space.AddApp(new(proxyman.OutboundConfig))).IsNil() + assert.Error(space.AddApp(config)).IsNil() assert.Error(space.Initialize()).IsNil() + r := FromSpace(space) + tag, err := r.TakeDetour(&proxy.SessionInfo{Destination: v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80)}) assert.Error(err).IsNil() assert.String(tag).Equals("test") diff --git a/app/space.go b/app/space.go index 01a48d12f..35428cbbd 100644 --- a/app/space.go +++ b/app/space.go @@ -1,23 +1,37 @@ package app -import "v2ray.com/core/common/errors" - -type ID int +import ( + "github.com/golang/protobuf/proto" + "v2ray.com/core/common/errors" + "v2ray.com/core/common/log" + "v2ray.com/core/common/serial" +) type Application interface { } -type ApplicationInitializer func() error +type InitializationCallback func() error + type ApplicationFactory interface { Create(space Space, config interface{}) (Application, error) - AppId() ID +} + +type AppGetter interface { + GetApp(name string) Application } var ( applicationFactoryCache = make(map[string]ApplicationFactory) ) -func RegisterApplicationFactory(name string, factory ApplicationFactory) error { +func RegisterApplicationFactory(defaultConfig proto.Message, factory ApplicationFactory) error { + if defaultConfig == nil { + return errors.New("Space: config is nil.") + } + name := serial.GetMessageType(defaultConfig) + if len(name) == 0 { + return errors.New("Space: cannot get config type.") + } applicationFactoryCache[name] = factory return nil } @@ -25,67 +39,67 @@ func RegisterApplicationFactory(name string, factory ApplicationFactory) error { // A Space contains all apps that may be available in a V2Ray runtime. // Caller must check the availability of an app by calling HasXXX before getting its instance. type Space interface { + AddApp(config proto.Message) error + AddAppLegacy(name string, app Application) Initialize() error - InitializeApplication(ApplicationInitializer) - - HasApp(ID) bool - GetApp(ID) Application - BindApp(ID, Application) - BindFromConfig(name string, config interface{}) error + OnInitialize(InitializationCallback) } type spaceImpl struct { - cache map[ID]Application - appInit []ApplicationInitializer + initialized bool + cache map[string]Application + appInit []InitializationCallback } func NewSpace() Space { return &spaceImpl{ - cache: make(map[ID]Application), - appInit: make([]ApplicationInitializer, 0, 32), + cache: make(map[string]Application), + appInit: make([]InitializationCallback, 0, 32), } } -func (v *spaceImpl) InitializeApplication(f ApplicationInitializer) { - v.appInit = append(v.appInit, f) +func (v *spaceImpl) OnInitialize(f InitializationCallback) { + if v.initialized { + if err := f(); err != nil { + log.Error("Space: error after space initialization: ", err) + } + } else { + v.appInit = append(v.appInit, f) + } } func (v *spaceImpl) Initialize() error { for _, f := range v.appInit { - err := f() - if err != nil { + if err := f(); err != nil { return err } } + v.initialized = true return nil } -func (v *spaceImpl) HasApp(id ID) bool { - _, found := v.cache[id] - return found -} - -func (v *spaceImpl) GetApp(id ID) Application { - obj, found := v.cache[id] +func (v *spaceImpl) GetApp(configType string) Application { + obj, found := v.cache[configType] if !found { return nil } return obj } -func (v *spaceImpl) BindApp(id ID, application Application) { - v.cache[id] = application -} - -func (v *spaceImpl) BindFromConfig(name string, config interface{}) error { - factory, found := applicationFactoryCache[name] +func (v *spaceImpl) AddApp(config proto.Message) error { + configName := serial.GetMessageType(config) + factory, found := applicationFactoryCache[configName] if !found { - return errors.New("Space: app not registered: ", name) + return errors.New("Space: app not registered: ", configName) } app, err := factory.Create(v, config) if err != nil { return err } - v.BindApp(factory.AppId(), app) + v.cache[configName] = app return nil } + +func (v *spaceImpl) AddAppLegacy(name string, application Application) { + v.cache[name] = application +} diff --git a/app/web/web.go b/app/web/web.go index 19ec8cd53..f89a3e715 100644 --- a/app/web/web.go +++ b/app/web/web.go @@ -1,11 +1,5 @@ package web -import "v2ray.com/core/app" - -const ( - APP_ID = app.ID(8) -) - type WebServer interface { Handle() } diff --git a/common/serial/typed_message.go b/common/serial/typed_message.go index 535487caa..ed5cfdacd 100644 --- a/common/serial/typed_message.go +++ b/common/serial/typed_message.go @@ -30,13 +30,14 @@ func GetInstance(messageType string) (interface{}, error) { return reflect.New(mType.Elem()).Interface(), nil } -func (v *TypedMessage) GetInstance() (interface{}, error) { +func (v *TypedMessage) GetInstance() (proto.Message, error) { instance, err := GetInstance(v.Type) if err != nil { return nil, err } - if err := proto.Unmarshal(v.Value, instance.(proto.Message)); err != nil { + protoMessage := instance.(proto.Message) + if err := proto.Unmarshal(v.Value, protoMessage); err != nil { return nil, err } - return instance, nil + return protoMessage, nil } diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 075f325a7..dd1dd82d7 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -38,11 +38,11 @@ func NewDokodemoDoor(config *Config, space app.Space, meta *proxy.InboundHandler port: v2net.Port(config.Port), meta: meta, } - space.InitializeApplication(func() error { - if !space.HasApp(dispatcher.APP_ID) { + space.OnInitialize(func() error { + d.packetDispatcher = dispatcher.FromSpace(space) + if d.packetDispatcher == nil { return errors.New("Dokodemo: Dispatcher is not found in the space.") } - d.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher) return nil }) return d diff --git a/proxy/dokodemo/dokodemo_test.go b/proxy/dokodemo/dokodemo_test.go index cad2adca8..1453ec0c6 100644 --- a/proxy/dokodemo/dokodemo_test.go +++ b/proxy/dokodemo/dokodemo_test.go @@ -6,9 +6,9 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" - dispatchers "v2ray.com/core/app/dispatcher/impl" + _ "v2ray.com/core/app/dispatcher/impl" "v2ray.com/core/app/proxyman" - "v2ray.com/core/app/proxyman/outbound" + _ "v2ray.com/core/app/proxyman/outbound" "v2ray.com/core/common/dice" v2net "v2ray.com/core/common/net" "v2ray.com/core/proxy" @@ -38,8 +38,10 @@ func TestDokodemoTCP(t *testing.T) { defer tcpServer.Close() space := app.NewSpace() - space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) - ohm := outbound.New() + space.AddApp(new(dispatcher.Config)) + space.AddApp(new(proxyman.OutboundConfig)) + + ohm := proxyman.OutboundHandlerManagerFromSpace(space) ohm.SetDefaultHandler( freedom.New( &freedom.Config{}, @@ -50,7 +52,6 @@ func TestDokodemoTCP(t *testing.T) { Network: v2net.Network_TCP, }, })) - space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm) data2Send := "Data to be sent to remote." @@ -109,8 +110,10 @@ func TestDokodemoUDP(t *testing.T) { defer udpServer.Close() space := app.NewSpace() - space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) - ohm := outbound.New() + space.AddApp(new(dispatcher.Config)) + space.AddApp(new(proxyman.OutboundConfig)) + + ohm := proxyman.OutboundHandlerManagerFromSpace(space) ohm.SetDefaultHandler( freedom.New( &freedom.Config{}, @@ -120,7 +123,6 @@ func TestDokodemoUDP(t *testing.T) { StreamSettings: &internet.StreamConfig{ Network: v2net.Network_TCP, }})) - space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, ohm) data2Send := "Data to be sent to remote." diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index b4afceef5..4bb441355 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -32,12 +32,12 @@ func New(config *Config, space app.Space, meta *proxy.OutboundHandlerMeta) *Hand timeout: config.Timeout, meta: meta, } - space.InitializeApplication(func() error { + space.OnInitialize(func() error { if config.DomainStrategy == Config_USE_IP { - if !space.HasApp(dns.APP_ID) { + f.dns = dns.FromSpace(space) + if f.dns == nil { return errors.New("Freedom: DNS server is not found in the space.") } - f.dns = space.GetApp(dns.APP_ID).(dns.Server) } return nil }) diff --git a/proxy/freedom/freedom_test.go b/proxy/freedom/freedom_test.go index 287936145..6daf58115 100644 --- a/proxy/freedom/freedom_test.go +++ b/proxy/freedom/freedom_test.go @@ -6,11 +6,11 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" - dispatchers "v2ray.com/core/app/dispatcher/impl" + _ "v2ray.com/core/app/dispatcher/impl" "v2ray.com/core/app/dns" - dnsserver "v2ray.com/core/app/dns/server" + _ "v2ray.com/core/app/dns/server" "v2ray.com/core/app/proxyman" - "v2ray.com/core/app/proxyman/outbound" + _ "v2ray.com/core/app/proxyman/outbound" "v2ray.com/core/app/router" "v2ray.com/core/common/buf" v2net "v2ray.com/core/common/net" @@ -70,16 +70,14 @@ func TestIPResolution(t *testing.T) { assert := assert.On(t) space := app.NewSpace() - space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outbound.New()) - space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) - r := router.NewRouter(&router.Config{}, space) - space.BindApp(router.APP_ID, r) - dnsServer := dnsserver.NewCacheServer(space, &dns.Config{ + assert.Error(space.AddApp(new(proxyman.OutboundConfig))).IsNil() + assert.Error(space.AddApp(new(dispatcher.Config))).IsNil() + assert.Error(space.AddApp(new(router.Config))).IsNil() + assert.Error(space.AddApp(&dns.Config{ Hosts: map[string]*v2net.IPOrDomain{ "v2ray.com": v2net.NewIPOrDomain(v2net.LocalHostIP), }, - }) - space.BindApp(dns.APP_ID, dnsServer) + })).IsNil() freedom := New( &Config{DomainStrategy: Config_USE_IP}, diff --git a/proxy/http/server.go b/proxy/http/server.go index 935650194..713dbe2a5 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -33,12 +33,19 @@ type Server struct { } // NewServer creates a new HTTP inbound handler. -func NewServer(config *ServerConfig, packetDispatcher dispatcher.PacketDispatcher, meta *proxy.InboundHandlerMeta) *Server { - return &Server{ - packetDispatcher: packetDispatcher, - config: config, - meta: meta, +func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) *Server { + s := &Server{ + config: config, + meta: meta, } + space.OnInitialize(func() error { + s.packetDispatcher = dispatcher.FromSpace(space) + if s.packetDispatcher == nil { + return errors.New("HTTP|Server: Dispatcher not found in space.") + } + return nil + }) + return s } // Port implements InboundHandler.Port(). @@ -291,13 +298,7 @@ func (v *ServerFactory) StreamCapability() v2net.NetworkList { // Create implements InboundHandlerFactory.Create(). func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { - if !space.HasApp(dispatcher.APP_ID) { - return nil, common.ErrBadConfiguration - } - return NewServer( - rawConfig.(*ServerConfig), - space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher), - meta), nil + return NewServer(rawConfig.(*ServerConfig), space, meta), nil } func init() { diff --git a/proxy/http/server_test.go b/proxy/http/server_test.go index 93bdc7088..0836800d2 100644 --- a/proxy/http/server_test.go +++ b/proxy/http/server_test.go @@ -6,13 +6,8 @@ import ( "strings" "testing" - testdispatcher "v2ray.com/core/app/dispatcher/testing" - "v2ray.com/core/common/dice" - v2net "v2ray.com/core/common/net" - "v2ray.com/core/proxy" . "v2ray.com/core/proxy/http" "v2ray.com/core/testing/assert" - "v2ray.com/core/transport/internet" _ "v2ray.com/core/transport/internet/tcp" ) @@ -50,30 +45,3 @@ Accept-Language: de,en;q=0.7,en-us;q=0.3 assert.String(req.Header.Get("Proxy-Connection")).Equals("") assert.String(req.Header.Get("Proxy-Authenticate")).Equals("") } - -func TestNormalGetRequest(t *testing.T) { - assert := assert.On(t) - - testPacketDispatcher := testdispatcher.NewTestPacketDispatcher(nil) - - port := v2net.Port(dice.Roll(20000) + 10000) - httpProxy := NewServer( - &ServerConfig{}, - testPacketDispatcher, - &proxy.InboundHandlerMeta{ - Address: v2net.LocalHostIP, - Port: port, - StreamSettings: &internet.StreamConfig{ - Network: v2net.Network_TCP, - }}) - defer httpProxy.Close() - - err := httpProxy.Start() - assert.Error(err).IsNil() - assert.Port(port).Equals(httpProxy.Port()) - - httpClient := &http.Client{} - resp, err := httpClient.Get("http://127.0.0.1:" + port.String() + "/") - assert.Error(err).IsNil() - assert.Int(resp.StatusCode).Equals(400) -} diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index a5db27326..7b3159f4e 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -3,7 +3,6 @@ package shadowsocks import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" - "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/bufio" "v2ray.com/core/common/errors" @@ -46,11 +45,11 @@ func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandler account: account, } - space.InitializeApplication(func() error { - if !space.HasApp(dispatcher.APP_ID) { + space.OnInitialize(func() error { + s.packetDispatcher = dispatcher.FromSpace(space) + if s.packetDispatcher == nil { return errors.New("Shadowsocks|Server: Dispatcher is not found in space.") } - s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher) return nil }) @@ -228,8 +227,5 @@ func (v *ServerFactory) StreamCapability() v2net.NetworkList { } func (v *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { - if !space.HasApp(dispatcher.APP_ID) { - return nil, common.ErrBadConfiguration - } return NewServer(rawConfig.(*ServerConfig), space, meta) } diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 009a4bfe5..91dacb1cd 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -41,11 +41,11 @@ func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandler config: config, meta: meta, } - space.InitializeApplication(func() error { - if !space.HasApp(dispatcher.APP_ID) { + space.OnInitialize(func() error { + s.packetDispatcher = dispatcher.FromSpace(space) + if s.packetDispatcher == nil { return errors.New("Socks|Server: Dispatcher is not found in the space.") } - s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher) return nil }) return s diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index ed117836a..a30a6f882 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -261,9 +261,6 @@ func (v *Factory) StreamCapability() v2net.NetworkList { } func (v *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { - if !space.HasApp(dispatcher.APP_ID) { - return nil, common.ErrBadConfiguration - } config := rawConfig.(*Config) allowedClients := vmess.NewTimedUserValidator(protocol.DefaultIDHash) @@ -272,16 +269,23 @@ func (v *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.Inb } handler := &VMessInboundHandler{ - packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher), - clients: allowedClients, - detours: config.Detour, - usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()), - meta: meta, + clients: allowedClients, + detours: config.Detour, + usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()), + meta: meta, } - if space.HasApp(proxyman.APP_ID_INBOUND_MANAGER) { - handler.inboundHandlerManager = space.GetApp(proxyman.APP_ID_INBOUND_MANAGER).(proxyman.InboundHandlerManager) - } + space.OnInitialize(func() error { + handler.packetDispatcher = dispatcher.FromSpace(space) + if handler.packetDispatcher == nil { + return errors.New("VMess|Inbound: Dispatcher is not found in space.") + } + handler.inboundHandlerManager = proxyman.InboundHandlerManagerFromSpace(space) + if handler.inboundHandlerManager == nil { + return errors.New("VMess|Inbound: InboundHandlerManager is not found is space.") + } + return nil + }) return handler, nil } diff --git a/v2ray.go b/v2ray.go index b083a102c..bd9e5ed0e 100644 --- a/v2ray.go +++ b/v2ray.go @@ -39,43 +39,52 @@ func NewPoint(pConfig *Config) (*Point, error) { space := app.NewSpace() vpoint.space = space - vpoint.space.BindApp(proxyman.APP_ID_INBOUND_MANAGER, vpoint) + vpoint.space.AddAppLegacy(serial.GetMessageType((*proxyman.InboundConfig)(nil)), vpoint) - outboundManagerConfig := new(proxyman.OutboundConfig) - if err := space.BindFromConfig(serial.GetMessageType(outboundManagerConfig), outboundManagerConfig); err != nil { - return nil, err + outboundHandlerManager := proxyman.OutboundHandlerManagerFromSpace(space) + if outboundHandlerManager == nil { + if err := space.AddApp(new(proxyman.OutboundConfig)); err != nil { + return nil, err + } + outboundHandlerManager = proxyman.OutboundHandlerManagerFromSpace(space) } - outboundHandlerManager := space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager) - - proxyDialer := proxydialer.NewOutboundProxy(space) + proxyDialer := proxydialer.OutboundProxyFromSpace(space) + if proxyDialer == nil { + space.AddApp(new(proxydialer.Config)) + proxyDialer = proxydialer.OutboundProxyFromSpace(space) + } proxyDialer.RegisterDialer() - space.BindApp(proxydialer.APP_ID, proxyDialer) for _, app := range pConfig.App { settings, err := app.GetInstance() if err != nil { return nil, err } - if err := space.BindFromConfig(app.Type, settings); err != nil { + if err := space.AddApp(settings); err != nil { return nil, err } } - if !space.HasApp(dns.APP_ID) { + dnsServer := dns.FromSpace(space) + if dnsServer == nil { dnsConfig := &dns.Config{ NameServers: []*v2net.Endpoint{{ Address: v2net.NewIPOrDomain(v2net.LocalHostDomain), }}, } - if err := space.BindFromConfig(serial.GetMessageType(dnsConfig), dnsConfig); err != nil { + if err := space.AddApp(dnsConfig); err != nil { return nil, err } } - dispatcherConfig := new(dispatcher.Config) - if err := vpoint.space.BindFromConfig(serial.GetMessageType(dispatcherConfig), dispatcherConfig); err != nil { - return nil, err + disp := dispatcher.FromSpace(space) + if disp == nil { + dispatcherConfig := new(dispatcher.Config) + if err := vpoint.space.AddApp(dispatcherConfig); err != nil { + return nil, err + } + disp = dispatcher.FromSpace(space) } vpoint.inboundHandlers = make([]InboundDetourHandler, 0, 8)