فهرست منبع

interface for inbound connection handler manager

v2ray 9 سال پیش
والد
کامیت
3baa1f5bc5

+ 9 - 4
app/controller/controller.go

@@ -8,9 +8,10 @@ import (
 // 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
-	pubsub           internal.PubsubWithContext
+	packetDispatcher      internal.PacketDispatcherWithContext
+	dnsCache              internal.DnsCacheWithContext
+	pubsub                internal.PubsubWithContext
+	inboundHandlerManager internal.InboundHandlerManagerWithContext
 }
 
 func New() *SpaceController {
@@ -29,8 +30,12 @@ func (this *SpaceController) Bind(object interface{}) {
 	if pubsub, ok := object.(internal.PubsubWithContext); ok {
 		this.pubsub = pubsub
 	}
+
+	if inboundHandlerManager, ok := object.(internal.InboundHandlerManagerWithContext); ok {
+		this.inboundHandlerManager = inboundHandlerManager
+	}
 }
 
 func (this *SpaceController) ForContext(tag string) app.Space {
-	return internal.NewSpace(tag, this.packetDispatcher, this.dnsCache, this.pubsub)
+	return internal.NewSpace(tag, this.packetDispatcher, this.dnsCache, this.pubsub, this.inboundHandlerManager)
 }

+ 9 - 0
app/handlers.go

@@ -0,0 +1,9 @@
+package app
+
+import (
+	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
+)
+
+type InboundHandlerManager interface {
+	GetHandler(tag string) (connhandler.InboundConnectionHandler, int)
+}

+ 19 - 0
app/internal/handlers.go

@@ -0,0 +1,19 @@
+package internal
+
+import (
+	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
+)
+
+type InboundHandlerManagerWithContext interface {
+	GetHandler(context app.Context, tag string) (connhandler.InboundConnectionHandler, int)
+}
+
+type inboundHandlerManagerWithContext struct {
+	context app.Context
+	manager InboundHandlerManagerWithContext
+}
+
+func (this *inboundHandlerManagerWithContext) GetHandler(tag string) (connhandler.InboundConnectionHandler, int) {
+	return this.manager.GetHandler(this.context, tag)
+}

+ 24 - 9
app/internal/space.go

@@ -5,18 +5,20 @@ import (
 )
 
 type Space struct {
-	packetDispatcher PacketDispatcherWithContext
-	dnsCache         DnsCacheWithContext
-	pubsub           PubsubWithContext
-	tag              string
+	packetDispatcher      PacketDispatcherWithContext
+	dnsCache              DnsCacheWithContext
+	pubsub                PubsubWithContext
+	inboundHandlerManager InboundHandlerManagerWithContext
+	tag                   string
 }
 
-func NewSpace(tag string, packetDispatcher PacketDispatcherWithContext, dnsCache DnsCacheWithContext, pubsub PubsubWithContext) *Space {
+func NewSpace(tag string, packetDispatcher PacketDispatcherWithContext, dnsCache DnsCacheWithContext, pubsub PubsubWithContext, inboundHandlerManager InboundHandlerManagerWithContext) *Space {
 	return &Space{
-		tag:              tag,
-		packetDispatcher: packetDispatcher,
-		dnsCache:         dnsCache,
-		pubsub:           pubsub,
+		tag:                   tag,
+		packetDispatcher:      packetDispatcher,
+		dnsCache:              dnsCache,
+		pubsub:                pubsub,
+		inboundHandlerManager: inboundHandlerManager,
 	}
 }
 
@@ -58,3 +60,16 @@ func (this *Space) Pubsub() app.Pubsub {
 		},
 	}
 }
+
+func (this *Space) HasInboundHandlerManager() bool {
+	return this.inboundHandlerManager != nil
+}
+
+func (this *Space) InboundHandlerManager() app.InboundHandlerManager {
+	return &inboundHandlerManagerWithContext{
+		manager: this.inboundHandlerManager,
+		context: &contextImpl{
+			callerTag: this.tag,
+		},
+	}
+}

+ 3 - 0
app/space.go

@@ -16,4 +16,7 @@ type Space interface {
 
 	HasPubsub() bool
 	Pubsub() Pubsub
+
+	HasInboundHandlerManager() bool
+	InboundHandlerManager() InboundHandlerManager
 }

+ 6 - 8
proxy/blackhole/blackhole.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/transport/ray"
 )
@@ -29,13 +30,10 @@ func (this *BlackHole) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) e
 	return nil
 }
 
-type BlackHoleFactory struct {
-}
-
-func (this BlackHoleFactory) Create(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
-	return NewBlackHole(), nil
-}
-
 func init() {
-	connhandler.RegisterOutboundConnectionHandlerFactory("blackhole", BlackHoleFactory{})
+	if err := proxy.RegisterOutboundConnectionHandlerFactory("blackhole", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return NewBlackHole(), nil
+	}); err != nil {
+		panic(err)
+	}
 }

+ 0 - 7
proxy/common/connhandler/inbound_connection.go

@@ -1,16 +1,9 @@
 package connhandler
 
 import (
-	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 )
 
-// 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)
-}
-
 // A InboundConnectionHandler handles inbound network connections to V2Ray.
 type InboundConnectionHandler interface {
 	// Listen starts a InboundConnectionHandler by listen on a specific port. This method is called

+ 0 - 7
proxy/common/connhandler/outbound_connection.go

@@ -1,17 +1,10 @@
 package connhandler
 
 import (
-	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/transport/ray"
 )
 
-// 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)
-}
-
 // An OutboundConnectionHandler handles outbound network connection for V2Ray.
 type OutboundConnectionHandler interface {
 	// Dispatch sends one or more Packets to its destination.

+ 0 - 34
proxy/common/connhandler/proxy_cache.go

@@ -1,34 +0,0 @@
-package connhandler
-
-var (
-	inboundFactories  = make(map[string]InboundConnectionHandlerFactory)
-	outboundFactories = make(map[string]OutboundConnectionHandlerFactory)
-)
-
-func RegisterInboundConnectionHandlerFactory(name string, factory InboundConnectionHandlerFactory) error {
-	// TODO check name
-	inboundFactories[name] = factory
-	return nil
-}
-
-func RegisterOutboundConnectionHandlerFactory(name string, factory OutboundConnectionHandlerFactory) error {
-	// TODO check name
-	outboundFactories[name] = factory
-	return nil
-}
-
-func GetInboundConnectionHandlerFactory(name string) InboundConnectionHandlerFactory {
-	factory, found := inboundFactories[name]
-	if !found {
-		return nil
-	}
-	return factory
-}
-
-func GetOutboundConnectionHandlerFactory(name string) OutboundConnectionHandlerFactory {
-	factory, found := outboundFactories[name]
-	if !found {
-		return nil
-	}
-	return factory
-}

+ 7 - 9
proxy/dokodemo/dokodemo_factory.go

@@ -2,17 +2,15 @@ package dokodemo
 
 import (
 	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
-type DokodemoDoorFactory struct {
-}
-
-func (this DokodemoDoorFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
-	config := rawConfig.(Config)
-	return NewDokodemoDoor(space, config), nil
-}
-
 func init() {
-	connhandler.RegisterInboundConnectionHandlerFactory("dokodemo-door", DokodemoDoorFactory{})
+	if err := proxy.RegisterInboundConnectionHandlerFactory("dokodemo-door", func(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
+		config := rawConfig.(Config)
+		return NewDokodemoDoor(space, config), nil
+	}); err != nil {
+		panic(err)
+	}
 }

+ 8 - 2
proxy/freedom/freedom_test.go

@@ -8,12 +8,14 @@ import (
 
 	"golang.org/x/net/proxy"
 
+	"github.com/v2ray/v2ray-core/app"
 	"github.com/v2ray/v2ray-core/common/alloc"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	v2nettesting "github.com/v2ray/v2ray-core/common/net/testing"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	_ "github.com/v2ray/v2ray-core/proxy/socks"
 	"github.com/v2ray/v2ray-core/proxy/socks/json"
+	proxytesting "github.com/v2ray/v2ray-core/proxy/testing"
 	proxymocks "github.com/v2ray/v2ray-core/proxy/testing/mocks"
 	"github.com/v2ray/v2ray-core/shell/point"
 	"github.com/v2ray/v2ray-core/shell/point/testing/mocks"
@@ -47,13 +49,17 @@ func TestUDPSend(t *testing.T) {
 		ConnOutput: connOutput,
 	}
 
-	connhandler.RegisterInboundConnectionHandlerFactory("mock_ich", ich)
+	protocol, err := proxytesting.RegisterInboundConnectionHandlerCreator("mock_ich", func(space app.Space, config interface{}) (connhandler.InboundConnectionHandler, error) {
+		ich.Space = space
+		return ich, nil
+	})
+	assert.Error(err).IsNil()
 
 	pointPort := v2nettesting.PickPort()
 	config := mocks.Config{
 		PortValue: pointPort,
 		InboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_ich",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{

+ 6 - 8
proxy/freedom/freedomfactory.go

@@ -2,16 +2,14 @@ package freedom
 
 import (
 	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
-type FreedomFactory struct {
-}
-
-func (this FreedomFactory) Create(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
-	return &FreedomConnection{space: space}, nil
-}
-
 func init() {
-	connhandler.RegisterOutboundConnectionHandlerFactory("freedom", FreedomFactory{})
+	if err := proxy.RegisterOutboundConnectionHandlerFactory("freedom", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return &FreedomConnection{space: space}, nil
+	}); err != nil {
+		panic(err)
+	}
 }

+ 6 - 8
proxy/http/http_factory.go

@@ -2,16 +2,14 @@ package http
 
 import (
 	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
-type HttpProxyServerFactory struct {
-}
-
-func (this HttpProxyServerFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
-	return NewHttpProxyServer(space, rawConfig.(Config)), nil
-}
-
 func init() {
-	connhandler.RegisterInboundConnectionHandlerFactory("http", HttpProxyServerFactory{})
+	if err := proxy.RegisterInboundConnectionHandlerFactory("http", func(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
+		return NewHttpProxyServer(space, rawConfig.(Config)), nil
+	}); err != nil {
+		panic(err)
+	}
 }

+ 9 - 0
proxy/internal/creator.go

@@ -0,0 +1,9 @@
+package internal
+
+import (
+	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
+)
+
+type InboundConnectionHandlerCreator func(space app.Space, config interface{}) (connhandler.InboundConnectionHandler, error)
+type OutboundConnectionHandlerCreator func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error)

+ 51 - 0
proxy/proxy.go

@@ -0,0 +1,51 @@
+// Package proxy contains all proxies used by V2Ray.
+
+package proxy
+
+import (
+	"errors"
+
+	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
+	"github.com/v2ray/v2ray-core/proxy/internal"
+)
+
+var (
+	inboundFactories  = make(map[string]internal.InboundConnectionHandlerCreator)
+	outboundFactories = make(map[string]internal.OutboundConnectionHandlerCreator)
+
+	ErrorProxyNotFound = errors.New("Proxy not found.")
+	ErrorNameExists    = errors.New("Proxy with the same name already exists.")
+)
+
+func RegisterInboundConnectionHandlerFactory(name string, creator internal.InboundConnectionHandlerCreator) error {
+	if _, found := inboundFactories[name]; found {
+		return ErrorNameExists
+	}
+	inboundFactories[name] = creator
+	return nil
+}
+
+func RegisterOutboundConnectionHandlerFactory(name string, creator internal.OutboundConnectionHandlerCreator) error {
+	if _, found := outboundFactories[name]; found {
+		return ErrorNameExists
+	}
+	outboundFactories[name] = creator
+	return nil
+}
+
+func CreateInboundConnectionHandler(name string, space app.Space, config interface{}) (connhandler.InboundConnectionHandler, error) {
+	if creator, found := inboundFactories[name]; !found {
+		return nil, ErrorProxyNotFound
+	} else {
+		return creator(space, config)
+	}
+}
+
+func CreateOutboundConnectionHandler(name string, space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+	if creator, found := outboundFactories[name]; !found {
+		return nil, ErrorNameExists
+	} else {
+		return creator(space, config)
+	}
+}

+ 27 - 10
proxy/socks/socks_test.go

@@ -9,9 +9,11 @@ import (
 
 	"golang.org/x/net/proxy"
 
+	"github.com/v2ray/v2ray-core/app"
 	v2nettesting "github.com/v2ray/v2ray-core/common/net/testing"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/proxy/socks/json"
+	proxytesting "github.com/v2ray/v2ray-core/proxy/testing"
 	proxymocks "github.com/v2ray/v2ray-core/proxy/testing/mocks"
 	"github.com/v2ray/v2ray-core/shell/point"
 	"github.com/v2ray/v2ray-core/shell/point/testing/mocks"
@@ -30,7 +32,10 @@ func TestSocksTcpConnect(t *testing.T) {
 		ConnInput:  bytes.NewReader(connInput),
 	}
 
-	connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
+	protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return och, nil
+	})
+	assert.Error(err).IsNil()
 
 	config := mocks.Config{
 		PortValue: port,
@@ -41,7 +46,7 @@ func TestSocksTcpConnect(t *testing.T) {
 			},
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_och",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 	}
@@ -85,7 +90,10 @@ func TestSocksTcpConnectWithUserPass(t *testing.T) {
 		ConnOutput: connOutput,
 	}
 
-	connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
+	protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return och, nil
+	})
+	assert.Error(err).IsNil()
 
 	config := mocks.Config{
 		PortValue: port,
@@ -99,7 +107,7 @@ func TestSocksTcpConnectWithUserPass(t *testing.T) {
 			},
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_och",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 	}
@@ -143,7 +151,10 @@ func TestSocksTcpConnectWithWrongUserPass(t *testing.T) {
 		ConnOutput: connOutput,
 	}
 
-	connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
+	protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return och, nil
+	})
+	assert.Error(err).IsNil()
 
 	config := mocks.Config{
 		PortValue: port,
@@ -157,7 +168,7 @@ func TestSocksTcpConnectWithWrongUserPass(t *testing.T) {
 			},
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_och",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 	}
@@ -187,7 +198,10 @@ func TestSocksTcpConnectWithWrongAuthMethod(t *testing.T) {
 		ConnOutput: connOutput,
 	}
 
-	connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
+	protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return och, nil
+	})
+	assert.Error(err).IsNil()
 
 	config := mocks.Config{
 		PortValue: port,
@@ -201,7 +215,7 @@ func TestSocksTcpConnectWithWrongAuthMethod(t *testing.T) {
 			},
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_och",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 	}
@@ -231,7 +245,10 @@ func TestSocksUdpSend(t *testing.T) {
 		ConnOutput: connOutput,
 	}
 
-	connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
+	protocol, err := proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return och, nil
+	})
+	assert.Error(err).IsNil()
 
 	config := mocks.Config{
 		PortValue: port,
@@ -243,7 +260,7 @@ func TestSocksUdpSend(t *testing.T) {
 			},
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_och",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 	}

+ 6 - 8
proxy/socks/socksfactory.go

@@ -2,16 +2,14 @@ package socks
 
 import (
 	"github.com/v2ray/v2ray-core/app"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
-type SocksServerFactory struct {
-}
-
-func (this SocksServerFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
-	return NewSocksServer(space, rawConfig.(Config)), nil
-}
-
 func init() {
-	connhandler.RegisterInboundConnectionHandlerFactory("socks", SocksServerFactory{})
+	if err := proxy.RegisterInboundConnectionHandlerFactory("socks", func(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
+		return NewSocksServer(space, rawConfig.(Config)), nil
+	}); err != nil {
+		panic(err)
+	}
 }

+ 2 - 8
proxy/testing/mocks/inboundhandler.go

@@ -6,12 +6,11 @@ import (
 
 	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
-	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
 type InboundConnectionHandler struct {
 	Port       v2net.Port
-	space      app.Space
+	Space      app.Space
 	ConnInput  io.Reader
 	ConnOutput io.Writer
 }
@@ -22,7 +21,7 @@ func (this *InboundConnectionHandler) Listen(port v2net.Port) error {
 }
 
 func (this *InboundConnectionHandler) Communicate(packet v2net.Packet) error {
-	ray := this.space.PacketDispatcher().DispatchToOutbound(packet)
+	ray := this.Space.PacketDispatcher().DispatchToOutbound(packet)
 
 	input := ray.InboundInput()
 	output := ray.InboundOutput()
@@ -48,8 +47,3 @@ func (this *InboundConnectionHandler) Communicate(packet v2net.Packet) error {
 	writeFinish.Lock()
 	return nil
 }
-
-func (this *InboundConnectionHandler) Create(space app.Space, config interface{}) (connhandler.InboundConnectionHandler, error) {
-	this.space = space
-	return this, nil
-}

+ 35 - 0
proxy/testing/proxy.go

@@ -0,0 +1,35 @@
+package testing
+
+import (
+	"fmt"
+
+	"github.com/v2ray/v2ray-core/proxy"
+	"github.com/v2ray/v2ray-core/proxy/internal"
+)
+
+var count = 0
+
+func randomString() string {
+	count++
+	return fmt.Sprintf("-%d", count)
+}
+
+func RegisterInboundConnectionHandlerCreator(prefix string, creator internal.InboundConnectionHandlerCreator) (string, error) {
+	for {
+		name := prefix + randomString()
+		err := proxy.RegisterInboundConnectionHandlerFactory(name, creator)
+		if err != proxy.ErrorNameExists {
+			return name, err
+		}
+	}
+}
+
+func RegisterOutboundConnectionHandlerCreator(prefix string, creator internal.OutboundConnectionHandlerCreator) (string, error) {
+	for {
+		name := prefix + randomString()
+		err := proxy.RegisterOutboundConnectionHandlerFactory(name, creator)
+		if err != proxy.ErrorNameExists {
+			return name, err
+		}
+	}
+}

+ 11 - 13
proxy/vmess/inbound/inbound.go

@@ -12,6 +12,7 @@ import (
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/common/retry"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/proxy/vmess"
 	"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
@@ -139,20 +140,17 @@ func handleOutput(request *protocol.VMessRequest, writer io.Writer, output <-cha
 	finish.Unlock()
 }
 
-type VMessInboundHandlerFactory struct {
-}
+func init() {
+	if err := proxy.RegisterInboundConnectionHandlerFactory("vmess", func(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
+		config := rawConfig.(Config)
 
-func (this *VMessInboundHandlerFactory) Create(space app.Space, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
-	config := rawConfig.(Config)
+		allowedClients := user.NewTimedUserSet()
+		for _, user := range config.AllowedUsers() {
+			allowedClients.AddUser(user)
+		}
 
-	allowedClients := user.NewTimedUserSet()
-	for _, user := range config.AllowedUsers() {
-		allowedClients.AddUser(user)
+		return NewVMessInboundHandler(space, allowedClients), nil
+	}); err != nil {
+		panic(err)
 	}
-
-	return NewVMessInboundHandler(space, allowedClients), nil
-}
-
-func init() {
-	connhandler.RegisterInboundConnectionHandlerFactory("vmess", &VMessInboundHandlerFactory{})
 }

+ 10 - 1
proxy/vmess/outbound/outbound.go

@@ -11,6 +11,7 @@ import (
 	v2crypto "github.com/v2ray/v2ray-core/common/crypto"
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
 	"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user"
@@ -196,5 +197,13 @@ func (this *VMessOutboundHandlerFactory) Create(space app.Space, rawConfig inter
 }
 
 func init() {
-	connhandler.RegisterOutboundConnectionHandlerFactory("vmess", &VMessOutboundHandlerFactory{})
+	if err := proxy.RegisterOutboundConnectionHandlerFactory("vmess", func(space app.Space, rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) {
+		vOutConfig := rawConfig.(Config)
+		return &VMessOutboundHandler{
+			space:           space,
+			receiverManager: NewReceiverManager(vOutConfig.Receivers()),
+		}, nil
+	}); err != nil {
+		panic(err)
+	}
 }

+ 13 - 4
proxy/vmess/vmess_test.go

@@ -4,10 +4,12 @@ import (
 	"bytes"
 	"testing"
 
+	"github.com/v2ray/v2ray-core/app"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	v2nettesting "github.com/v2ray/v2ray-core/common/net/testing"
 	"github.com/v2ray/v2ray-core/common/uuid"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
+	proxytesting "github.com/v2ray/v2ray-core/proxy/testing"
 	proxymocks "github.com/v2ray/v2ray-core/proxy/testing/mocks"
 	vmess "github.com/v2ray/v2ray-core/proxy/vmess"
 	_ "github.com/v2ray/v2ray-core/proxy/vmess/inbound"
@@ -39,12 +41,16 @@ func TestVMessInAndOut(t *testing.T) {
 		ConnOutput: ichConnOutput,
 	}
 
-	connhandler.RegisterInboundConnectionHandlerFactory("mock_ich", ich)
+	protocol, err := proxytesting.RegisterInboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.InboundConnectionHandler, error) {
+		ich.Space = space
+		return ich, nil
+	})
+	assert.Error(err).IsNil()
 
 	configA := mocks.Config{
 		PortValue: portA,
 		InboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_ich",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
@@ -75,7 +81,10 @@ func TestVMessInAndOut(t *testing.T) {
 		ConnOutput: ochConnOutput,
 	}
 
-	connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
+	protocol, err = proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (connhandler.OutboundConnectionHandler, error) {
+		return och, nil
+	})
+	assert.Error(err).IsNil()
 
 	configB := mocks.Config{
 		PortValue: portB,
@@ -88,7 +97,7 @@ func TestVMessInAndOut(t *testing.T) {
 			},
 		},
 		OutboundConfigValue: &mocks.ConnectionConfig{
-			ProtocolValue: "mock_och",
+			ProtocolValue: protocol,
 			SettingsValue: nil,
 		},
 	}

+ 2 - 7
shell/point/inbound_detour.go

@@ -5,6 +5,7 @@ import (
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/common/retry"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 )
 
@@ -21,17 +22,11 @@ type InboundDetourHandler struct {
 }
 
 func (this *InboundDetourHandler) Initialize() error {
-	ichFactory := connhandler.GetInboundConnectionHandlerFactory(this.config.Protocol())
-	if ichFactory == nil {
-		log.Error("Unknown inbound connection handler factory %s", this.config.Protocol())
-		return BadConfiguration
-	}
-
 	ports := this.config.PortRange()
 	this.ich = make([]*InboundConnectionHandlerWithPort, 0, ports.To()-ports.From()+1)
 	for i := ports.From(); i <= ports.To(); i++ {
 		ichConfig := this.config.Settings()
-		ich, err := ichFactory.Create(this.space, ichConfig)
+		ich, err := proxy.CreateInboundConnectionHandler(this.config.Protocol(), this.space, ichConfig)
 		if err != nil {
 			log.Error("Failed to create inbound connection handler: %v", err)
 			return err

+ 4 - 18
shell/point/point.go

@@ -11,6 +11,7 @@ import (
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/common/retry"
+	"github.com/v2ray/v2ray-core/proxy"
 	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 	"github.com/v2ray/v2ray-core/transport/ray"
 )
@@ -54,26 +55,16 @@ func NewPoint(pConfig PointConfig) (*Point, error) {
 	vpoint.space = controller.New()
 	vpoint.space.Bind(vpoint)
 
-	ichFactory := connhandler.GetInboundConnectionHandlerFactory(pConfig.InboundConfig().Protocol())
-	if ichFactory == nil {
-		log.Error("Unknown inbound connection handler factory %s", pConfig.InboundConfig().Protocol())
-		return nil, BadConfiguration
-	}
 	ichConfig := pConfig.InboundConfig().Settings()
-	ich, err := ichFactory.Create(vpoint.space.ForContext("vpoint-default-inbound"), ichConfig)
+	ich, err := proxy.CreateInboundConnectionHandler(pConfig.InboundConfig().Protocol(), vpoint.space.ForContext("vpoint-default-inbound"), ichConfig)
 	if err != nil {
 		log.Error("Failed to create inbound connection handler: %v", err)
 		return nil, err
 	}
 	vpoint.ich = ich
 
-	ochFactory := connhandler.GetOutboundConnectionHandlerFactory(pConfig.OutboundConfig().Protocol())
-	if ochFactory == nil {
-		log.Error("Unknown outbound connection handler factory %s", pConfig.OutboundConfig().Protocol())
-		return nil, BadConfiguration
-	}
 	ochConfig := pConfig.OutboundConfig().Settings()
-	och, err := ochFactory.Create(vpoint.space.ForContext("vpoint-default-outbound"), ochConfig)
+	och, err := proxy.CreateOutboundConnectionHandler(pConfig.OutboundConfig().Protocol(), vpoint.space.ForContext("vpoint-default-outbound"), ochConfig)
 	if err != nil {
 		log.Error("Failed to create outbound connection handler: %v", err)
 		return nil, err
@@ -100,12 +91,7 @@ func NewPoint(pConfig PointConfig) (*Point, error) {
 	if len(outboundDetours) > 0 {
 		vpoint.odh = make(map[string]connhandler.OutboundConnectionHandler)
 		for _, detourConfig := range outboundDetours {
-			detourFactory := connhandler.GetOutboundConnectionHandlerFactory(detourConfig.Protocol())
-			if detourFactory == nil {
-				log.Error("Unknown detour outbound connection handler factory %s", detourConfig.Protocol())
-				return nil, BadConfiguration
-			}
-			detourHandler, err := detourFactory.Create(vpoint.space.ForContext(detourConfig.Tag()), detourConfig.Settings())
+			detourHandler, err := proxy.CreateOutboundConnectionHandler(detourConfig.Protocol(), vpoint.space.ForContext(detourConfig.Tag()), detourConfig.Settings())
 			if err != nil {
 				log.Error("Failed to create detour outbound connection handler: %v", err)
 				return nil, err