diff --git a/app/controller/controller.go b/app/controller/controller.go new file mode 100644 index 000000000..c1a589818 --- /dev/null +++ b/app/controller/controller.go @@ -0,0 +1,31 @@ +package controller + +import ( + "github.com/v2ray/v2ray-core/app" + "github.com/v2ray/v2ray-core/app/internal" +) + +// A SpaceController is supposed to be used by a shell to create Spaces. It should not be used +// directly by proxies. +type SpaceController struct { + packetDispatcher internal.PacketDispatcherWithContext + dnsCache internal.DnsCacheWithContext +} + +func New() *SpaceController { + return new(SpaceController) +} + +func (this *SpaceController) Bind(object interface{}) { + if packetDispatcher, ok := object.(internal.PacketDispatcherWithContext); ok { + this.packetDispatcher = packetDispatcher + } + + if dnsCache, ok := object.(internal.DnsCacheWithContext); ok { + this.dnsCache = dnsCache + } +} + +func (this *SpaceController) ForContext(tag string) app.Space { + return internal.NewSpace(tag, this.packetDispatcher, this.dnsCache) +} diff --git a/app/dns.go b/app/dns.go index e0903e2a7..2ce48e142 100644 --- a/app/dns.go +++ b/app/dns.go @@ -4,25 +4,8 @@ import ( "net" ) +// A DnsCache is an internal cache of DNS resolutions. type DnsCache interface { Get(domain string) net.IP Add(domain string, ip net.IP) } - -type DnsCacheWithContext interface { - Get(context Context, domain string) net.IP - Add(contaxt Context, domain string, ip net.IP) -} - -type contextedDnsCache struct { - context Context - dnsCache DnsCacheWithContext -} - -func (this *contextedDnsCache) Get(domain string) net.IP { - return this.dnsCache.Get(this.context, domain) -} - -func (this *contextedDnsCache) Add(domain string, ip net.IP) { - this.dnsCache.Add(this.context, domain, ip) -} diff --git a/app/internal/context.go b/app/internal/context.go new file mode 100644 index 000000000..4379b1775 --- /dev/null +++ b/app/internal/context.go @@ -0,0 +1,9 @@ +package internal + +type contextImpl struct { + callerTag string +} + +func (this *contextImpl) CallerTag() string { + return this.callerTag +} diff --git a/app/internal/dns.go b/app/internal/dns.go new file mode 100644 index 000000000..e2e8a32b5 --- /dev/null +++ b/app/internal/dns.go @@ -0,0 +1,25 @@ +package internal + +import ( + "net" + + "github.com/v2ray/v2ray-core/app" +) + +type DnsCacheWithContext interface { + Get(context app.Context, domain string) net.IP + Add(contaxt app.Context, domain string, ip net.IP) +} + +type contextedDnsCache struct { + context app.Context + dnsCache DnsCacheWithContext +} + +func (this *contextedDnsCache) Get(domain string) net.IP { + return this.dnsCache.Get(this.context, domain) +} + +func (this *contextedDnsCache) Add(domain string, ip net.IP) { + this.dnsCache.Add(this.context, domain, ip) +} diff --git a/app/internal/packet_dispatcher.go b/app/internal/packet_dispatcher.go new file mode 100644 index 000000000..91a0bd893 --- /dev/null +++ b/app/internal/packet_dispatcher.go @@ -0,0 +1,20 @@ +package internal + +import ( + "github.com/v2ray/v2ray-core/app" + v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/transport/ray" +) + +type PacketDispatcherWithContext interface { + DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay +} + +type contextedPacketDispatcher struct { + context app.Context + packetDispatcher PacketDispatcherWithContext +} + +func (this *contextedPacketDispatcher) DispatchToOutbound(packet v2net.Packet) ray.InboundRay { + return this.packetDispatcher.DispatchToOutbound(this.context, packet) +} diff --git a/app/internal/space.go b/app/internal/space.go new file mode 100644 index 000000000..1e96ab3e1 --- /dev/null +++ b/app/internal/space.go @@ -0,0 +1,45 @@ +package internal + +import ( + "github.com/v2ray/v2ray-core/app" +) + +type Space struct { + packetDispatcher PacketDispatcherWithContext + dnsCache DnsCacheWithContext + tag string +} + +func NewSpace(tag string, packetDispatcher PacketDispatcherWithContext, dnsCache DnsCacheWithContext) *Space { + return &Space{ + tag: tag, + packetDispatcher: packetDispatcher, + dnsCache: dnsCache, + } +} + +func (this *Space) HasPacketDispatcher() bool { + return this.packetDispatcher != nil +} + +func (this *Space) PacketDispatcher() app.PacketDispatcher { + return &contextedPacketDispatcher{ + packetDispatcher: this.packetDispatcher, + context: &contextImpl{ + callerTag: this.tag, + }, + } +} + +func (this *Space) HasDnsCache() bool { + return this.dnsCache != nil +} + +func (this *Space) DnsCache() app.DnsCache { + return &contextedDnsCache{ + dnsCache: this.dnsCache, + context: &contextImpl{ + callerTag: this.tag, + }, + } +} diff --git a/app/packet_dispatcher.go b/app/packet_dispatcher.go index 04548bc5b..62ed936c8 100644 --- a/app/packet_dispatcher.go +++ b/app/packet_dispatcher.go @@ -9,16 +9,3 @@ import ( type PacketDispatcher interface { DispatchToOutbound(packet v2net.Packet) ray.InboundRay } - -type PacketDispatcherWithContext interface { - DispatchToOutbound(context Context, packet v2net.Packet) ray.InboundRay -} - -type contextedPacketDispatcher struct { - context Context - packetDispatcher PacketDispatcherWithContext -} - -func (this *contextedPacketDispatcher) DispatchToOutbound(packet v2net.Packet) ray.InboundRay { - return this.packetDispatcher.DispatchToOutbound(this.context, packet) -} diff --git a/app/space.go b/app/space.go index 73b97d452..9d9e5f026 100644 --- a/app/space.go +++ b/app/space.go @@ -1,74 +1,16 @@ package app +// Context of a function call from proxy to app. type Context interface { CallerTag() string } -type contextImpl struct { - callerTag string -} +// 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 { + HasPacketDispatcher() bool + PacketDispatcher() PacketDispatcher -func (this *contextImpl) CallerTag() string { - return this.callerTag -} - -type SpaceController struct { - packetDispatcher PacketDispatcherWithContext - dnsCache DnsCacheWithContext -} - -func NewSpaceController() *SpaceController { - return new(SpaceController) -} - -func (this *SpaceController) Bind(object interface{}) { - if packetDispatcher, ok := object.(PacketDispatcherWithContext); ok { - this.packetDispatcher = packetDispatcher - } - - if dnsCache, ok := object.(DnsCacheWithContext); ok { - this.dnsCache = dnsCache - } -} - -func (this *SpaceController) ForContext(tag string) *Space { - return newSpace(this, &contextImpl{callerTag: tag}) -} - -type Space struct { - packetDispatcher PacketDispatcher - dnsCache DnsCache -} - -func newSpace(controller *SpaceController, context Context) *Space { - space := new(Space) - if controller.packetDispatcher != nil { - space.packetDispatcher = &contextedPacketDispatcher{ - context: context, - packetDispatcher: controller.packetDispatcher, - } - } - if controller.dnsCache != nil { - space.dnsCache = &contextedDnsCache{ - context: context, - dnsCache: controller.dnsCache, - } - } - return space -} - -func (this *Space) HasPacketDispatcher() bool { - return this.packetDispatcher != nil -} - -func (this *Space) PacketDispatcher() PacketDispatcher { - return this.packetDispatcher -} - -func (this *Space) HasDnsCache() bool { - return this.dnsCache != nil -} - -func (this *Space) DnsCache() DnsCache { - return this.dnsCache + HasDnsCache() bool + DnsCache() DnsCache } diff --git a/proxy/blackhole/blackhole.go b/proxy/blackhole/blackhole.go index d5f07f87e..2dedbc0ba 100644 --- a/proxy/blackhole/blackhole.go +++ b/proxy/blackhole/blackhole.go @@ -32,7 +32,7 @@ func (this *BlackHole) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) e type BlackHoleFactory struct { } -func (this BlackHoleFactory) Create(space *app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) { +func (this BlackHoleFactory) Create(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) { return NewBlackHole(), nil } diff --git a/proxy/common/connhandler/inbound_connection.go b/proxy/common/connhandler/inbound_connection.go index dc0037d6a..245e13d94 100644 --- a/proxy/common/connhandler/inbound_connection.go +++ b/proxy/common/connhandler/inbound_connection.go @@ -8,7 +8,7 @@ import ( // A InboundConnectionHandlerFactory creates InboundConnectionHandler on demand. type InboundConnectionHandlerFactory interface { // Create creates a new InboundConnectionHandler with given configuration. - Create(space *app.Space, config interface{}) (InboundConnectionHandler, error) + Create(space app.Space, config interface{}) (InboundConnectionHandler, error) } // A InboundConnectionHandler handles inbound network connections to V2Ray. diff --git a/proxy/common/connhandler/outbound_connection.go b/proxy/common/connhandler/outbound_connection.go index 596a93a85..ac7aa5cb8 100644 --- a/proxy/common/connhandler/outbound_connection.go +++ b/proxy/common/connhandler/outbound_connection.go @@ -9,7 +9,7 @@ import ( // An OutboundConnectionHandlerFactory creates OutboundConnectionHandler on demand. type OutboundConnectionHandlerFactory interface { // Create creates a new OutboundConnectionHandler with given config. - Create(space *app.Space, config interface{}) (OutboundConnectionHandler, error) + Create(space app.Space, config interface{}) (OutboundConnectionHandler, error) } // An OutboundConnectionHandler handles outbound network connection for V2Ray. diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index a127ca478..f1562997c 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -16,10 +16,10 @@ type DokodemoDoor struct { config Config accepting bool address v2net.Address - space *app.Space + space app.Space } -func NewDokodemoDoor(space *app.Space, config Config) *DokodemoDoor { +func NewDokodemoDoor(space app.Space, config Config) *DokodemoDoor { return &DokodemoDoor{ config: config, space: space, diff --git a/proxy/dokodemo/dokodemo_factory.go b/proxy/dokodemo/dokodemo_factory.go index b6efe6fb8..6e21345ce 100644 --- a/proxy/dokodemo/dokodemo_factory.go +++ b/proxy/dokodemo/dokodemo_factory.go @@ -8,7 +8,7 @@ import ( type DokodemoDoorFactory struct { } -func (this DokodemoDoorFactory) Create(space *app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) { +func (this DokodemoDoorFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) { config := rawConfig.(Config) return NewDokodemoDoor(space, config), nil } diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index fd7fa94e1..9a235eca7 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -11,7 +11,7 @@ import ( ) type FreedomConnection struct { - space *app.Space + space app.Space } func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { diff --git a/proxy/freedom/freedomfactory.go b/proxy/freedom/freedomfactory.go index 1ec4ba015..92aebb45e 100644 --- a/proxy/freedom/freedomfactory.go +++ b/proxy/freedom/freedomfactory.go @@ -8,7 +8,7 @@ import ( type FreedomFactory struct { } -func (this FreedomFactory) Create(space *app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) { +func (this FreedomFactory) Create(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) { return &FreedomConnection{space: space}, nil } diff --git a/proxy/socks/socks.go b/proxy/socks/socks.go index f2de09a54..ed8fcde22 100644 --- a/proxy/socks/socks.go +++ b/proxy/socks/socks.go @@ -24,11 +24,11 @@ var ( // SocksServer is a SOCKS 5 proxy server type SocksServer struct { accepting bool - space *app.Space + space app.Space config Config } -func NewSocksServer(space *app.Space, config Config) *SocksServer { +func NewSocksServer(space app.Space, config Config) *SocksServer { return &SocksServer{ space: space, config: config, diff --git a/proxy/socks/socksfactory.go b/proxy/socks/socksfactory.go index 3e60ccc02..6f898f67c 100644 --- a/proxy/socks/socksfactory.go +++ b/proxy/socks/socksfactory.go @@ -8,7 +8,7 @@ import ( type SocksServerFactory struct { } -func (this SocksServerFactory) Create(space *app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) { +func (this SocksServerFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) { return NewSocksServer(space, rawConfig.(Config)), nil } diff --git a/proxy/testing/mocks/inboundhandler.go b/proxy/testing/mocks/inboundhandler.go index 6e8277f81..0e985ab0f 100644 --- a/proxy/testing/mocks/inboundhandler.go +++ b/proxy/testing/mocks/inboundhandler.go @@ -11,7 +11,7 @@ import ( type InboundConnectionHandler struct { Port v2net.Port - space *app.Space + space app.Space ConnInput io.Reader ConnOutput io.Writer } @@ -49,7 +49,7 @@ func (this *InboundConnectionHandler) Communicate(packet v2net.Packet) error { return nil } -func (this *InboundConnectionHandler) Create(space *app.Space, config interface{}) (connhandler.InboundConnectionHandler, error) { +func (this *InboundConnectionHandler) Create(space app.Space, config interface{}) (connhandler.InboundConnectionHandler, error) { this.space = space return this, nil } diff --git a/proxy/testing/mocks/outboundhandler.go b/proxy/testing/mocks/outboundhandler.go index fb865a556..22c79f8c1 100644 --- a/proxy/testing/mocks/outboundhandler.go +++ b/proxy/testing/mocks/outboundhandler.go @@ -45,6 +45,6 @@ func (this *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray ray.Out return nil } -func (this *OutboundConnectionHandler) Create(space *app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) { +func (this *OutboundConnectionHandler) Create(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) { return this, nil } diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 3de7274a2..0f5e77bff 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -20,12 +20,12 @@ import ( // Inbound connection handler that handles messages in VMess format. type VMessInboundHandler struct { - space *app.Space + space app.Space clients user.UserSet accepting bool } -func NewVMessInboundHandler(space *app.Space, clients user.UserSet) *VMessInboundHandler { +func NewVMessInboundHandler(space app.Space, clients user.UserSet) *VMessInboundHandler { return &VMessInboundHandler{ space: space, clients: clients, @@ -142,7 +142,7 @@ func handleOutput(request *protocol.VMessRequest, writer io.Writer, output <-cha type VMessInboundHandlerFactory struct { } -func (this *VMessInboundHandlerFactory) Create(space *app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) { +func (this *VMessInboundHandlerFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) { config := rawConfig.(Config) allowedClients := user.NewTimedUserSet() diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 0826c92f1..2760bd58e 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -19,7 +19,7 @@ import ( type VMessOutboundHandler struct { receiverManager *ReceiverManager - space *app.Space + space app.Space } func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { @@ -175,7 +175,7 @@ func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<- type VMessOutboundHandlerFactory struct { } -func (this *VMessOutboundHandlerFactory) Create(space *app.Space, rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) { +func (this *VMessOutboundHandlerFactory) Create(space app.Space, rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) { vOutConfig := rawConfig.(Config) return &VMessOutboundHandler{ space: space, diff --git a/shell/point/inbound_detour.go b/shell/point/inbound_detour.go index 0063f58a4..b81e9285e 100644 --- a/shell/point/inbound_detour.go +++ b/shell/point/inbound_detour.go @@ -15,7 +15,7 @@ type InboundConnectionHandlerWithPort struct { // Handler for inbound detour connections. type InboundDetourHandler struct { - space *app.Space + space app.Space config InboundDetourConfig ich []*InboundConnectionHandlerWithPort } diff --git a/shell/point/point.go b/shell/point/point.go index 6d07ed4c0..2cfa82777 100644 --- a/shell/point/point.go +++ b/shell/point/point.go @@ -6,6 +6,7 @@ package point import ( "github.com/v2ray/v2ray-core/app" + "github.com/v2ray/v2ray-core/app/controller" "github.com/v2ray/v2ray-core/app/router" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" @@ -22,7 +23,7 @@ type Point struct { idh []*InboundDetourHandler odh map[string]connhandler.OutboundConnectionHandler router router.Router - space *app.SpaceController + space *controller.SpaceController } // NewPoint returns a new Point server based on given configuration. @@ -50,7 +51,7 @@ func NewPoint(pConfig PointConfig) (*Point, error) { log.SetLogLevel(logConfig.LogLevel()) } - vpoint.space = app.NewSpaceController() + vpoint.space = controller.New() vpoint.space.Bind(vpoint) ichFactory := connhandler.GetInboundConnectionHandlerFactory(pConfig.InboundConfig().Protocol())