Przeglądaj źródła

remove use of any

Darien Raymond 9 lat temu
rodzic
commit
e33b7df34c
72 zmienionych plików z 727 dodań i 791 usunięć
  1. 5 3
      common/loader/json_conf.go
  2. 50 0
      common/loader/type.go
  3. 59 0
      common/loader/type.pb.go
  4. 11 0
      common/loader/type.proto
  5. 0 42
      common/log/config_json.go
  6. 0 27
      common/net/address_json.go
  7. 0 40
      common/net/address_json_test.go
  8. 2 2
      common/protocol/server_spec.go
  9. 15 15
      common/protocol/user.go
  10. 19 18
      common/protocol/user.pb.go
  11. 2 2
      common/protocol/user.proto
  12. 0 1
      config.go
  13. 65 67
      config.pb.go
  14. 4 7
      config.proto
  15. 1 1
      inbound_detour_always.go
  16. 2 2
      inbound_detour_dynamic.go
  17. 13 1
      main/main.go
  18. 3 2
      proxy/blackhole/blackhole.go
  19. 4 23
      proxy/blackhole/config.go
  20. 10 16
      proxy/blackhole/config_json.go
  21. 0 5
      proxy/dokodemo/config_json.go
  22. 2 1
      proxy/dokodemo/dokodemo.go
  23. 0 6
      proxy/freedom/config_json.go
  24. 2 1
      proxy/freedom/freedom.go
  25. 0 6
      proxy/http/config_json.go
  26. 2 1
      proxy/http/server.go
  27. 0 50
      proxy/registry/config_cache.go
  28. 0 25
      proxy/registry/config_cache_json.go
  29. 2 13
      proxy/shadowsocks/config_json.go
  30. 4 2
      proxy/shadowsocks/config_json_test.go
  31. 8 3
      proxy/shadowsocks/server.go
  32. 4 9
      proxy/socks/config.go
  33. 3 11
      proxy/socks/config_json.go
  34. 2 1
      proxy/socks/server.go
  35. 1 1
      proxy/vmess/encoding/client.go
  36. 2 1
      proxy/vmess/encoding/server.go
  37. 1 1
      proxy/vmess/inbound/command.go
  38. 2 15
      proxy/vmess/inbound/config_json.go
  39. 3 5
      proxy/vmess/inbound/inbound.go
  40. 3 4
      proxy/vmess/outbound/command.go
  41. 2 13
      proxy/vmess/outbound/config_json.go
  42. 2 1
      proxy/vmess/outbound/outbound.go
  43. 1 1
      proxy/vmess/vmess.go
  44. 76 0
      tools/conf/common.go
  45. 80 0
      tools/conf/common_test.go
  46. 43 0
      tools/conf/log.go
  47. 28 0
      tools/conf/v2ray.go
  48. 4 17
      transport/config_json.go
  49. 0 43
      transport/internet/authenticator.go
  50. 18 19
      transport/internet/authenticator.pb.go
  51. 2 2
      transport/internet/authenticator.proto
  52. 0 23
      transport/internet/authenticator_json.go
  53. 2 2
      transport/internet/authenticators/noop/noop.go
  54. 2 2
      transport/internet/authenticators/srtp/srtp.go
  55. 2 2
      transport/internet/authenticators/utp/utp.go
  56. 11 51
      transport/internet/config.go
  57. 30 73
      transport/internet/config.pb.go
  58. 4 15
      transport/internet/config.proto
  59. 5 13
      transport/internet/connection_json.go
  60. 7 4
      transport/internet/kcp/config.go
  61. 38 37
      transport/internet/kcp/config.pb.go
  62. 2 2
      transport/internet/kcp/config.proto
  63. 15 8
      transport/internet/kcp/config_json.go
  64. 10 7
      transport/internet/kcp/dialer.go
  65. 6 3
      transport/internet/kcp/listener.go
  66. 1 3
      transport/internet/tcp/config.go
  67. 9 6
      transport/internet/tcp/dialer.go
  68. 6 3
      transport/internet/tcp/hub.go
  69. 1 3
      transport/internet/ws/config.go
  70. 8 5
      transport/internet/ws/dialer.go
  71. 5 2
      transport/internet/ws/hub.go
  72. 1 1
      v2ray.go

+ 5 - 3
common/loader/json_conf.go

@@ -9,13 +9,15 @@ import (
 	"v2ray.com/core/common/log"
 )
 
+type NamedTypeMap map[string]string
+
 type JSONConfigLoader struct {
-	cache     ConfigCreatorCache
+	cache     NamedTypeMap
 	idKey     string
 	configKey string
 }
 
-func NewJSONConfigLoader(cache ConfigCreatorCache, idKey string, configKey string) *JSONConfigLoader {
+func NewJSONConfigLoader(cache NamedTypeMap, idKey string, configKey string) *JSONConfigLoader {
 	return &JSONConfigLoader{
 		idKey:     idKey,
 		configKey: configKey,
@@ -24,7 +26,7 @@ func NewJSONConfigLoader(cache ConfigCreatorCache, idKey string, configKey strin
 }
 
 func (this *JSONConfigLoader) LoadWithID(raw []byte, id string) (interface{}, error) {
-	config, err := this.cache.CreateConfig(id)
+	config, err := GetInstance(this.cache[id])
 	if err != nil {
 		return nil, err
 	}

+ 50 - 0
common/loader/type.go

@@ -0,0 +1,50 @@
+package loader
+
+import (
+	"errors"
+	"reflect"
+
+	"github.com/golang/protobuf/proto"
+)
+
+func NewTypedSettings(message proto.Message) *TypedSettings {
+	if message == nil {
+		return nil
+	}
+	settings, _ := proto.Marshal(message)
+	return &TypedSettings{
+		Type:     GetType(message),
+		Settings: settings,
+	}
+}
+
+func GetType(message proto.Message) string {
+	return proto.MessageName(message)
+}
+
+func GetInstance(messageType string) (interface{}, error) {
+	mType := proto.MessageType(messageType)
+	if mType == nil {
+		return nil, errors.New("Unknown type: " + messageType)
+	}
+	return reflect.New(mType).Interface(), nil
+}
+
+func (this *TypedSettings) Load(message proto.Message) error {
+	targetType := GetType(message)
+	if targetType != this.Type {
+		return errors.New("Have type " + this.Type + ", but retrieved for " + targetType)
+	}
+	return proto.Unmarshal(this.Settings, message)
+}
+
+func (this *TypedSettings) GetInstance() (interface{}, error) {
+	instance, err := GetInstance(this.Type)
+	if err != nil {
+		return nil, err
+	}
+	if err := proto.Unmarshal(this.Settings, instance.(proto.Message)); err != nil {
+		return nil, err
+	}
+	return instance, nil
+}

+ 59 - 0
common/loader/type.pb.go

@@ -0,0 +1,59 @@
+// Code generated by protoc-gen-go.
+// source: v2ray.com/core/common/loader/type.proto
+// DO NOT EDIT!
+
+/*
+Package loader is a generated protocol buffer package.
+
+It is generated from these files:
+	v2ray.com/core/common/loader/type.proto
+
+It has these top-level messages:
+	TypedSettings
+*/
+package loader
+
+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 TypedSettings struct {
+	Type     string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
+	Settings []byte `protobuf:"bytes,2,opt,name=settings,proto3" json:"settings,omitempty"`
+}
+
+func (m *TypedSettings) Reset()                    { *m = TypedSettings{} }
+func (m *TypedSettings) String() string            { return proto.CompactTextString(m) }
+func (*TypedSettings) ProtoMessage()               {}
+func (*TypedSettings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func init() {
+	proto.RegisterType((*TypedSettings)(nil), "v2ray.core.common.loader.TypedSettings")
+}
+
+func init() { proto.RegisterFile("v2ray.com/core/common/loader/type.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+	// 151 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x33, 0x2a, 0x4a,
+	0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcd, 0xcd,
+	0xcf, 0xd3, 0xcf, 0xc9, 0x4f, 0x4c, 0x49, 0x2d, 0xd2, 0x2f, 0xa9, 0x2c, 0x48, 0xd5, 0x2b, 0x28,
+	0xca, 0x2f, 0xc9, 0x17, 0x92, 0x80, 0x29, 0x2c, 0x4a, 0xd5, 0x83, 0x28, 0xd2, 0x83, 0x28, 0x52,
+	0xb2, 0xe7, 0xe2, 0x0d, 0xa9, 0x2c, 0x48, 0x4d, 0x09, 0x4e, 0x2d, 0x29, 0xc9, 0xcc, 0x4b, 0x2f,
+	0x16, 0x12, 0xe2, 0x62, 0x01, 0x69, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x85,
+	0xa4, 0xb8, 0x38, 0x8a, 0xa1, 0xf2, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x70, 0xbe, 0x93,
+	0x21, 0x97, 0x4c, 0x72, 0x7e, 0xae, 0x1e, 0x2e, 0x0b, 0x9c, 0x38, 0x41, 0xc6, 0x07, 0x80, 0x5c,
+	0x11, 0xc5, 0x06, 0x11, 0x4a, 0x62, 0x03, 0x3b, 0xca, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x24,
+	0xa2, 0x4d, 0x76, 0xbf, 0x00, 0x00, 0x00,
+}

+ 11 - 0
common/loader/type.proto

@@ -0,0 +1,11 @@
+syntax = "proto3";
+
+package v2ray.core.common.loader;
+option go_package = "loader";
+option java_package = "com.v2ray.core.common.loader";
+option java_outer_classname = "TypeProto";
+
+message TypedSettings {
+  string type = 1;
+  bytes settings = 2;
+}

+ 0 - 42
common/log/config_json.go

@@ -1,42 +0,0 @@
-package log
-
-import (
-	"encoding/json"
-	"errors"
-	"strings"
-)
-
-func (this *Config) UnmarshalJSON(data []byte) error {
-	type JsonLogConfig struct {
-		AccessLog string `json:"access"`
-		ErrorLog  string `json:"error"`
-		LogLevel  string `json:"loglevel"`
-	}
-	jsonConfig := new(JsonLogConfig)
-	if err := json.Unmarshal(data, jsonConfig); err != nil {
-		return errors.New("Log: Failed to parse log config: " + err.Error())
-	}
-	if len(jsonConfig.AccessLog) > 0 {
-		this.AccessLogPath = jsonConfig.AccessLog
-		this.AccessLogType = LogType_File
-	}
-	if len(jsonConfig.ErrorLog) > 0 {
-		this.ErrorLogPath = jsonConfig.ErrorLog
-		this.ErrorLogType = LogType_File
-	}
-
-	level := strings.ToLower(jsonConfig.LogLevel)
-	switch level {
-	case "debug":
-		this.ErrorLogLevel = LogLevel_Debug
-	case "info":
-		this.ErrorLogLevel = LogLevel_Info
-	case "error":
-		this.ErrorLogLevel = LogLevel_Error
-	case "none":
-		this.ErrorLogType = LogType_None
-	default:
-		this.ErrorLogLevel = LogLevel_Warning
-	}
-	return nil
-}

+ 0 - 27
common/net/address_json.go

@@ -1,27 +0,0 @@
-// +build json
-
-package net
-
-import (
-	"encoding/json"
-)
-
-func (this *IPOrDomain) UnmarshalJSON(data []byte) error {
-	var rawStr string
-	if err := json.Unmarshal(data, &rawStr); err != nil {
-		return err
-	}
-	addr := ParseAddress(rawStr)
-	switch addr.Family() {
-	case AddressFamilyIPv4, AddressFamilyIPv6:
-		this.Address = &IPOrDomain_Ip{
-			Ip: []byte(addr.IP()),
-		}
-	case AddressFamilyDomain:
-		this.Address = &IPOrDomain_Domain{
-			Domain: addr.Domain(),
-		}
-	}
-
-	return nil
-}

+ 0 - 40
common/net/address_json_test.go

@@ -1,40 +0,0 @@
-// +build json
-
-package net_test
-
-import (
-	"encoding/json"
-	"testing"
-
-	. "v2ray.com/core/common/net"
-	"v2ray.com/core/testing/assert"
-)
-
-func TestIPParsing(t *testing.T) {
-	assert := assert.On(t)
-
-	rawJson := "\"8.8.8.8\""
-	var address IPOrDomain
-	err := json.Unmarshal([]byte(rawJson), &address)
-	assert.Error(err).IsNil()
-	assert.Bytes(address.GetIp()).Equals([]byte{8, 8, 8, 8})
-}
-
-func TestDomainParsing(t *testing.T) {
-	assert := assert.On(t)
-
-	rawJson := "\"v2ray.com\""
-	var address IPOrDomain
-	err := json.Unmarshal([]byte(rawJson), &address)
-	assert.Error(err).IsNil()
-	assert.String(address.GetDomain()).Equals("v2ray.com")
-}
-
-func TestInvalidAddressJson(t *testing.T) {
-	assert := assert.On(t)
-
-	rawJson := "1234"
-	var address IPOrDomain
-	err := json.Unmarshal([]byte(rawJson), &address)
-	assert.Error(err).IsNotNil()
-}

+ 2 - 2
common/protocol/server_spec.go

@@ -73,12 +73,12 @@ func (this *ServerSpec) HasUser(user *User) bool {
 	this.RLock()
 	defer this.RUnlock()
 
-	accountA, err := user.GetTypedAccount(this.newAccount())
+	accountA, err := user.GetTypedAccount()
 	if err != nil {
 		return false
 	}
 	for _, u := range this.users {
-		accountB, err := u.GetTypedAccount(this.newAccount())
+		accountB, err := u.GetTypedAccount()
 		if err == nil && accountA.Equals(accountB) {
 			return true
 		}

+ 15 - 15
common/protocol/user.go

@@ -2,31 +2,31 @@ package protocol
 
 import (
 	"errors"
-
-	"github.com/golang/protobuf/proto"
-	"github.com/golang/protobuf/ptypes"
 )
 
 var (
-	ErrUserMissing    = errors.New("User is not specified.")
-	ErrAccountMissing = errors.New("Account is not specified.")
-	ErrNonMessageType = errors.New("Not a protobuf message.")
+	ErrUserMissing        = errors.New("User is not specified.")
+	ErrAccountMissing     = errors.New("Account is not specified.")
+	ErrNonMessageType     = errors.New("Not a protobuf message.")
+	ErrUnknownAccountType = errors.New("Unknown account type.")
 )
 
-func (this *User) GetTypedAccount(account AsAccount) (Account, error) {
-	anyAccount := this.GetAccount()
-	if anyAccount == nil {
+func (this *User) GetTypedAccount() (Account, error) {
+	if this.GetAccount() == nil {
 		return nil, ErrAccountMissing
 	}
-	protoAccount, ok := account.(proto.Message)
-	if !ok {
-		return nil, ErrNonMessageType
-	}
-	err := ptypes.UnmarshalAny(anyAccount, protoAccount)
+
+	rawAccount, err := this.Account.GetInstance()
 	if err != nil {
 		return nil, err
 	}
-	return account.AsAccount()
+	if asAccount, ok := rawAccount.(AsAccount); ok {
+		return asAccount.AsAccount()
+	}
+	if account, ok := rawAccount.(Account); ok {
+		return account, nil
+	}
+	return nil, errors.New("Unknown account type: " + this.Account.Type)
 }
 
 func (this *User) GetSettings() UserSettings {

+ 19 - 18
common/protocol/user.pb.go

@@ -7,7 +7,7 @@ package protocol
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
-import google_protobuf "github.com/golang/protobuf/ptypes/any"
+import v2ray_core_common_loader "v2ray.com/core/common/loader"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
@@ -15,9 +15,9 @@ var _ = fmt.Errorf
 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"`
-	Account *google_protobuf.Any `protobuf:"bytes,3,opt,name=account" json:"account,omitempty"`
+	Level   uint32                                  `protobuf:"varint,1,opt,name=level" json:"level,omitempty"`
+	Email   string                                  `protobuf:"bytes,2,opt,name=email" json:"email,omitempty"`
+	Account *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,3,opt,name=account" json:"account,omitempty"`
 }
 
 func (m *User) Reset()                    { *m = User{} }
@@ -25,7 +25,7 @@ func (m *User) String() string            { return proto.CompactTextString(m) }
 func (*User) ProtoMessage()               {}
 func (*User) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
 
-func (m *User) GetAccount() *google_protobuf.Any {
+func (m *User) GetAccount() *v2ray_core_common_loader.TypedSettings {
 	if m != nil {
 		return m.Account
 	}
@@ -39,17 +39,18 @@ func init() {
 func init() { proto.RegisterFile("v2ray.com/core/common/protocol/user.proto", fileDescriptor1) }
 
 var fileDescriptor1 = []byte{
-	// 192 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x8e, 0xbd, 0xea, 0xc2, 0x30,
-	0x14, 0xc5, 0xc9, 0xff, 0x43, 0x6d, 0xc4, 0xa5, 0x74, 0xa8, 0x1d, 0xa4, 0x38, 0xd5, 0xe5, 0x06,
-	0x2a, 0x3e, 0x80, 0x7d, 0x02, 0x29, 0xb8, 0xb8, 0xa5, 0xe1, 0x5a, 0x84, 0x24, 0x57, 0xd2, 0x0f,
-	0xe8, 0xdb, 0x4b, 0x1b, 0x32, 0xba, 0xe5, 0x77, 0xf2, 0xbb, 0x9c, 0xc3, 0x4f, 0x63, 0xe9, 0xe4,
-	0x04, 0x8a, 0x8c, 0x50, 0xe4, 0x50, 0x28, 0x32, 0x86, 0xac, 0x78, 0x3b, 0xea, 0x49, 0x91, 0x16,
-	0x43, 0x87, 0x0e, 0x16, 0x8a, 0xb3, 0xa0, 0x3a, 0x04, 0xaf, 0x41, 0xd0, 0xb2, 0x7d, 0x4b, 0xd4,
-	0x6a, 0xf4, 0x77, 0xcd, 0xf0, 0x14, 0xd2, 0x4e, 0xfe, 0xf7, 0xd8, 0xf0, 0xbf, 0x7b, 0x87, 0x2e,
-	0x4e, 0xf8, 0xbf, 0xc6, 0x11, 0x75, 0xca, 0x72, 0x56, 0xec, 0x6a, 0x0f, 0x73, 0x8a, 0x46, 0xbe,
-	0x74, 0xfa, 0x93, 0xb3, 0x22, 0xaa, 0x3d, 0xc4, 0xc0, 0xd7, 0x52, 0x29, 0x1a, 0x6c, 0x9f, 0xfe,
-	0xe6, 0xac, 0xd8, 0x96, 0x09, 0xf8, 0x02, 0x08, 0x05, 0x70, 0xb5, 0x53, 0x1d, 0xa4, 0xea, 0xc2,
-	0x0f, 0x8a, 0x0c, 0x7c, 0x1f, 0x58, 0x45, 0xf3, 0x86, 0xdb, 0x4c, 0x8f, 0x4d, 0x08, 0x9b, 0xd5,
-	0xf2, 0x3a, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xfc, 0x46, 0xc6, 0x05, 0x01, 0x00, 0x00,
+	// 200 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x8f, 0x3f, 0xef, 0x82, 0x30,
+	0x10, 0x86, 0xd3, 0xdf, 0x5f, 0xa9, 0x71, 0x21, 0x0e, 0x84, 0xc1, 0x10, 0x17, 0x70, 0x69, 0x13,
+	0x8c, 0x1f, 0x40, 0x3e, 0x81, 0x41, 0x5d, 0xdc, 0x6a, 0xb9, 0x18, 0x92, 0x96, 0x23, 0xa5, 0x90,
+	0xf0, 0xed, 0x0d, 0x34, 0x9d, 0xd4, 0xad, 0xcf, 0x9b, 0xa7, 0x77, 0xef, 0xd1, 0xdd, 0x90, 0x1b,
+	0x31, 0x32, 0x89, 0x9a, 0x4b, 0x34, 0xc0, 0x25, 0x6a, 0x8d, 0x0d, 0x6f, 0x0d, 0x5a, 0x94, 0xa8,
+	0x78, 0xdf, 0x81, 0x61, 0x33, 0x85, 0xb1, 0x57, 0x0d, 0x30, 0xa7, 0x31, 0xaf, 0xc5, 0xe9, 0xfb,
+	0x31, 0x0a, 0x45, 0x05, 0x86, 0xdb, 0xb1, 0x05, 0xe7, 0x6e, 0x7b, 0xfa, 0x73, 0xed, 0xc0, 0x84,
+	0x6b, 0xfa, 0xab, 0x60, 0x00, 0x15, 0x91, 0x84, 0x64, 0xab, 0xd2, 0xc1, 0x94, 0x82, 0x16, 0xb5,
+	0x8a, 0xbe, 0x12, 0x92, 0x05, 0xa5, 0x83, 0xf0, 0x48, 0xff, 0x85, 0x94, 0xd8, 0x37, 0x36, 0xfa,
+	0x4e, 0x48, 0xb6, 0xcc, 0x53, 0xf6, 0x5a, 0xc5, 0xad, 0x62, 0x97, 0xb1, 0x85, 0xea, 0x0c, 0xd6,
+	0xd6, 0xcd, 0xa3, 0x2b, 0xfd, 0xbf, 0xe2, 0x40, 0x37, 0x12, 0x35, 0xfb, 0x7c, 0x41, 0x11, 0x4c,
+	0xb5, 0x4e, 0x13, 0xdd, 0x16, 0x3e, 0xbc, 0xff, 0xcd, 0xaf, 0xfd, 0x33, 0x00, 0x00, 0xff, 0xff,
+	0x68, 0x83, 0xed, 0x6b, 0x26, 0x01, 0x00, 0x00,
 }

+ 2 - 2
common/protocol/user.proto

@@ -5,10 +5,10 @@ option go_package = "protocol";
 option java_package = "com.v2ray.core.common.protocol";
 option java_outer_classname = "UserProto";
 
-import "google/protobuf/any.proto";
+import "v2ray.com/core/common/loader/type.proto";
 
 message User {
   uint32 level = 1;
   string email = 2;
-  google.protobuf.Any account = 3;
+  v2ray.core.common.loader.TypedSettings account = 3;
 }

+ 0 - 1
config.go

@@ -2,7 +2,6 @@ package core
 
 import (
 	"v2ray.com/core/common"
-	"v2ray.com/core/proxy/registry"
 )
 
 func (this *AllocationStrategyConcurrency) GetValue() uint32 {

+ 65 - 67
config.pb.go

@@ -23,12 +23,12 @@ import fmt "fmt"
 import math "math"
 import v2ray_core_app_router "v2ray.com/core/app/router"
 import v2ray_core_app_dns "v2ray.com/core/app/dns"
+import v2ray_core_common_loader "v2ray.com/core/common/loader"
 import v2ray_core_common_net "v2ray.com/core/common/net"
 import v2ray_core_common_net2 "v2ray.com/core/common/net"
 import v2ray_core_common_log "v2ray.com/core/common/log"
 import v2ray_core_transport_internet "v2ray.com/core/transport/internet"
 import v2ray_core_transport "v2ray.com/core/transport"
-import google_protobuf "github.com/golang/protobuf/ptypes/any"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
@@ -136,14 +136,13 @@ func (m *AllocationStrategy) GetRefresh() *AllocationStrategyRefresh {
 
 // Config for an inbound connection handler.
 type InboundConnectionConfig struct {
-	Protocol               string                                      `protobuf:"bytes,1,opt,name=protocol" json:"protocol,omitempty"`
+	Settings               *v2ray_core_common_loader.TypedSettings     `protobuf:"bytes,1,opt,name=settings" json:"settings,omitempty"`
 	PortRange              *v2ray_core_common_net.PortRange            `protobuf:"bytes,2,opt,name=port_range,json=portRange" json:"port_range,omitempty"`
 	ListenOn               *v2ray_core_common_net2.IPOrDomain          `protobuf:"bytes,3,opt,name=listen_on,json=listenOn" json:"listen_on,omitempty"`
 	Tag                    string                                      `protobuf:"bytes,4,opt,name=tag" json:"tag,omitempty"`
 	AllocationStrategy     *AllocationStrategy                         `protobuf:"bytes,5,opt,name=allocation_strategy,json=allocationStrategy" json:"allocation_strategy,omitempty"`
 	StreamSettings         *v2ray_core_transport_internet.StreamConfig `protobuf:"bytes,6,opt,name=stream_settings,json=streamSettings" json:"stream_settings,omitempty"`
-	Settings               *google_protobuf.Any                        `protobuf:"bytes,7,opt,name=settings" json:"settings,omitempty"`
-	AllowPassiveConnection bool                                        `protobuf:"varint,8,opt,name=allow_passive_connection,json=allowPassiveConnection" json:"allow_passive_connection,omitempty"`
+	AllowPassiveConnection bool                                        `protobuf:"varint,7,opt,name=allow_passive_connection,json=allowPassiveConnection" json:"allow_passive_connection,omitempty"`
 }
 
 func (m *InboundConnectionConfig) Reset()                    { *m = InboundConnectionConfig{} }
@@ -151,6 +150,13 @@ func (m *InboundConnectionConfig) String() string            { return proto.Comp
 func (*InboundConnectionConfig) ProtoMessage()               {}
 func (*InboundConnectionConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
 
+func (m *InboundConnectionConfig) GetSettings() *v2ray_core_common_loader.TypedSettings {
+	if m != nil {
+		return m.Settings
+	}
+	return nil
+}
+
 func (m *InboundConnectionConfig) GetPortRange() *v2ray_core_common_net.PortRange {
 	if m != nil {
 		return m.PortRange
@@ -179,19 +185,11 @@ func (m *InboundConnectionConfig) GetStreamSettings() *v2ray_core_transport_inte
 	return nil
 }
 
-func (m *InboundConnectionConfig) GetSettings() *google_protobuf.Any {
-	if m != nil {
-		return m.Settings
-	}
-	return nil
-}
-
 type OutboundConnectionConfig struct {
-	Protocol       string                                      `protobuf:"bytes,1,opt,name=protocol" json:"protocol,omitempty"`
+	Settings       *v2ray_core_common_loader.TypedSettings     `protobuf:"bytes,1,opt,name=settings" json:"settings,omitempty"`
 	SendThrough    *v2ray_core_common_net2.IPOrDomain          `protobuf:"bytes,2,opt,name=send_through,json=sendThrough" json:"send_through,omitempty"`
 	StreamSettings *v2ray_core_transport_internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings" json:"stream_settings,omitempty"`
 	Tag            string                                      `protobuf:"bytes,4,opt,name=tag" json:"tag,omitempty"`
-	Settings       *google_protobuf.Any                        `protobuf:"bytes,5,opt,name=settings" json:"settings,omitempty"`
 }
 
 func (m *OutboundConnectionConfig) Reset()                    { *m = OutboundConnectionConfig{} }
@@ -199,23 +197,23 @@ func (m *OutboundConnectionConfig) String() string            { return proto.Com
 func (*OutboundConnectionConfig) ProtoMessage()               {}
 func (*OutboundConnectionConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
 
-func (m *OutboundConnectionConfig) GetSendThrough() *v2ray_core_common_net2.IPOrDomain {
+func (m *OutboundConnectionConfig) GetSettings() *v2ray_core_common_loader.TypedSettings {
 	if m != nil {
-		return m.SendThrough
+		return m.Settings
 	}
 	return nil
 }
 
-func (m *OutboundConnectionConfig) GetStreamSettings() *v2ray_core_transport_internet.StreamConfig {
+func (m *OutboundConnectionConfig) GetSendThrough() *v2ray_core_common_net2.IPOrDomain {
 	if m != nil {
-		return m.StreamSettings
+		return m.SendThrough
 	}
 	return nil
 }
 
-func (m *OutboundConnectionConfig) GetSettings() *google_protobuf.Any {
+func (m *OutboundConnectionConfig) GetStreamSettings() *v2ray_core_transport_internet.StreamConfig {
 	if m != nil {
-		return m.Settings
+		return m.StreamSettings
 	}
 	return nil
 }
@@ -290,52 +288,52 @@ func init() {
 func init() { proto.RegisterFile("v2ray.com/core/config.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-	// 751 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x95, 0xed, 0x6e, 0xeb, 0x34,
-	0x1c, 0xc6, 0xd7, 0x97, 0x75, 0xe9, 0xbf, 0x63, 0x54, 0x66, 0x82, 0xac, 0x30, 0x54, 0xba, 0x17,
-	0x0a, 0x4c, 0x09, 0x0c, 0x4d, 0x20, 0x24, 0x18, 0x7b, 0x01, 0x69, 0x20, 0xd1, 0x2a, 0xdd, 0x27,
-	0xbe, 0x54, 0x5e, 0xe2, 0x65, 0x91, 0x12, 0x3b, 0xb2, 0xdd, 0x8d, 0x5c, 0x02, 0x37, 0x70, 0x6e,
-	0x6e, 0x37, 0x73, 0x14, 0xdb, 0x49, 0xdf, 0x77, 0x76, 0x74, 0xbe, 0x25, 0xf1, 0xf3, 0x7b, 0x6c,
-	0x3f, 0x8f, 0xdd, 0xc2, 0xe7, 0x8f, 0xa7, 0x1c, 0x67, 0x8e, 0xcf, 0x12, 0xd7, 0x67, 0x9c, 0xb8,
-	0x3e, 0xa3, 0xf7, 0x51, 0xe8, 0xa4, 0x9c, 0x49, 0x86, 0xa0, 0x18, 0xe4, 0xa4, 0x73, 0xbc, 0x20,
-	0xc4, 0x69, 0xea, 0x72, 0x36, 0x91, 0x84, 0xcf, 0x31, 0x9d, 0x83, 0x15, 0xba, 0x80, 0x8a, 0x79,
-	0xd1, 0xe1, 0xd2, 0xac, 0x49, 0xc2, 0xa8, 0x4b, 0x89, 0x74, 0x53, 0xc6, 0xa5, 0x51, 0x7d, 0xbd,
-	0x5e, 0x85, 0x83, 0x80, 0x13, 0x21, 0x8c, 0xf0, 0x78, 0xb5, 0x30, 0x66, 0xe1, 0xfc, 0xb4, 0xce,
-	0x82, 0x4e, 0x72, 0x4c, 0x45, 0x3e, 0xa1, 0x1b, 0x51, 0x49, 0x78, 0x6e, 0x3c, 0xa7, 0x3f, 0x5a,
-	0xab, 0x9f, 0x93, 0xed, 0x85, 0x8c, 0x85, 0x31, 0x71, 0xd5, 0xdb, 0xdd, 0xe4, 0xde, 0xc5, 0x34,
-	0xd3, 0x43, 0xbd, 0x33, 0xd8, 0xbf, 0x88, 0x63, 0xe6, 0x63, 0x19, 0x31, 0x3a, 0x92, 0x1c, 0x4b,
-	0x12, 0x66, 0x57, 0x8c, 0xfa, 0x13, 0xce, 0x09, 0xf5, 0x33, 0xb4, 0x0b, 0x9b, 0x8f, 0x38, 0x9e,
-	0x10, 0xbb, 0xd2, 0xad, 0xf4, 0x3f, 0xf2, 0xf4, 0x4b, 0xef, 0x07, 0xd8, 0x5b, 0xc6, 0x3c, 0x72,
-	0xcf, 0x89, 0x78, 0x58, 0x83, 0xfc, 0x5f, 0x05, 0xb4, 0xcc, 0xa0, 0x9f, 0xa0, 0x2e, 0xb3, 0x54,
-	0x6b, 0x77, 0x4e, 0x0f, 0x9c, 0x69, 0xa3, 0xce, 0xb2, 0xda, 0xb9, 0xcd, 0x52, 0xe2, 0x29, 0x00,
-	0xfd, 0x0d, 0x2d, 0x7f, 0xba, 0x4e, 0xbb, 0xda, 0xad, 0xf4, 0x5b, 0xa7, 0xdf, 0xbc, 0xcc, 0xcf,
-	0x6c, 0xcc, 0x9b, 0xa5, 0xd1, 0x39, 0x6c, 0x71, 0xbd, 0x7a, 0xbb, 0xa6, 0x8c, 0x8e, 0x5e, 0x36,
-	0x32, 0x5b, 0xf5, 0x0a, 0xaa, 0x77, 0x02, 0xf5, 0x7c, 0x6d, 0x08, 0xa0, 0x71, 0x11, 0x3f, 0xe1,
-	0x4c, 0xb4, 0x37, 0xf2, 0x67, 0x0f, 0xd3, 0x80, 0x25, 0xed, 0x0a, 0xda, 0x06, 0xeb, 0x8f, 0xff,
-	0xf2, 0x0a, 0x71, 0xdc, 0xae, 0xf6, 0x9e, 0x6b, 0xf0, 0xd9, 0x0d, 0xbd, 0x63, 0x13, 0x1a, 0x5c,
-	0x31, 0x4a, 0x89, 0x9f, 0x7b, 0x5f, 0xa9, 0xca, 0x50, 0x07, 0x2c, 0x55, 0x8d, 0xcf, 0x62, 0x15,
-	0x4a, 0xd3, 0x2b, 0xdf, 0xd1, 0x39, 0x40, 0xde, 0xee, 0x98, 0x63, 0x1a, 0x12, 0xb3, 0xe5, 0xee,
-	0xec, 0x4a, 0xf5, 0xc1, 0x72, 0x28, 0x91, 0xce, 0x90, 0x71, 0xe9, 0xe5, 0x3a, 0xaf, 0x99, 0x16,
-	0x8f, 0xe8, 0x37, 0x68, 0xc6, 0x91, 0x90, 0x84, 0x8e, 0x19, 0x35, 0x3b, 0xfd, 0x6a, 0x0d, 0x7f,
-	0x33, 0x1c, 0xf0, 0x6b, 0x96, 0xe0, 0x88, 0x7a, 0x96, 0x66, 0x06, 0x14, 0xb5, 0xa1, 0x26, 0x71,
-	0x68, 0xd7, 0xd5, 0xba, 0xf2, 0x47, 0x34, 0x80, 0x4f, 0x70, 0x19, 0xcf, 0x58, 0x98, 0x7c, 0xec,
-	0x4d, 0xe5, 0xfd, 0xe5, 0x3b, 0x52, 0x44, 0x78, 0xf9, 0x40, 0xdc, 0xc2, 0xc7, 0x42, 0x72, 0x82,
-	0x93, 0xb1, 0x20, 0x52, 0x46, 0x34, 0x14, 0x76, 0x43, 0x99, 0x7d, 0x37, 0x6b, 0x56, 0x9e, 0x74,
-	0xa7, 0xb8, 0x19, 0xce, 0x48, 0x51, 0x3a, 0x45, 0x6f, 0x47, 0x7b, 0x8c, 0x8c, 0x05, 0xfa, 0x1e,
-	0xac, 0xd2, 0x6e, 0x4b, 0xd9, 0xed, 0x3a, 0xfa, 0x56, 0x38, 0xc5, 0xad, 0x70, 0x2e, 0x68, 0xe6,
-	0x95, 0x2a, 0xf4, 0x33, 0xd8, 0xf9, 0xea, 0x9e, 0xc6, 0x29, 0x16, 0x22, 0x7a, 0x24, 0x63, 0xbf,
-	0x6c, 0xca, 0xb6, 0xba, 0x95, 0xbe, 0xe5, 0x7d, 0xaa, 0xc6, 0x87, 0x7a, 0x78, 0xda, 0x63, 0xef,
-	0x4d, 0x15, 0xec, 0xc1, 0x44, 0xbe, 0x7f, 0xbd, 0xd7, 0xb0, 0x2d, 0x08, 0x0d, 0xc6, 0xf2, 0x81,
-	0xb3, 0x49, 0xf8, 0x60, 0x0a, 0x7e, 0x45, 0x41, 0xad, 0x1c, 0xbb, 0xd5, 0xd4, 0xaa, 0x00, 0x6b,
-	0x1f, 0x1e, 0xe0, 0x72, 0xf3, 0xb3, 0x91, 0x6e, 0xbe, 0x26, 0xd2, 0xde, 0x73, 0x15, 0x1a, 0x26,
-	0x86, 0x5f, 0x61, 0x2b, 0xd2, 0x17, 0xc0, 0xae, 0x74, 0x6b, 0xfd, 0xd6, 0xfc, 0xcd, 0x5f, 0x73,
-	0x37, 0xbc, 0x82, 0x41, 0xbf, 0x83, 0xc5, 0x4c, 0xc2, 0x76, 0x55, 0xf1, 0x87, 0xb3, 0xfc, 0xba,
-	0xf4, 0xbd, 0x92, 0x42, 0x2e, 0xd4, 0x62, 0x16, 0x9a, 0x64, 0xf6, 0x57, 0x44, 0x1c, 0xb3, 0xd0,
-	0x31, 0x54, 0xae, 0x44, 0x67, 0xd0, 0xd0, 0x7f, 0x27, 0x2a, 0x83, 0x05, 0x06, 0xa7, 0xa9, 0xa3,
-	0x47, 0x0b, 0xc6, 0x88, 0xd1, 0x09, 0xd4, 0x02, 0x5a, 0x04, 0xd4, 0x59, 0x64, 0x02, 0x2a, 0xca,
-	0x49, 0x02, 0x2a, 0xd0, 0x2f, 0xd0, 0x2c, 0x8b, 0x31, 0xc7, 0xfe, 0x8b, 0xd5, 0xad, 0x19, 0x6a,
-	0x2a, 0xff, 0xf6, 0x18, 0xb6, 0xf5, 0xc7, 0x3f, 0x19, 0x4f, 0xb0, 0xcc, 0x7f, 0x72, 0x86, 0xa6,
-	0x87, 0xf6, 0x06, 0xb2, 0xa0, 0xfe, 0xd7, 0x68, 0xf0, 0x4f, 0xbb, 0x72, 0x79, 0x00, 0x3b, 0x3e,
-	0x4b, 0x66, 0x5c, 0x2f, 0x5b, 0x9a, 0x53, 0xea, 0x7f, 0xeb, 0xf9, 0xa7, 0xbb, 0x86, 0xaa, 0xf0,
-	0xc7, 0xb7, 0x01, 0x00, 0x00, 0xff, 0xff, 0xba, 0x3e, 0xa7, 0x09, 0x7f, 0x07, 0x00, 0x00,
+	// 737 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x95, 0xdf, 0x6e, 0xdb, 0x36,
+	0x14, 0xc6, 0x23, 0xdb, 0x71, 0xec, 0xe3, 0x2c, 0x33, 0xb8, 0x61, 0xd3, 0xb2, 0x65, 0xf0, 0x9c,
+	0x7f, 0x5e, 0x1b, 0x48, 0xa8, 0x8b, 0xa0, 0x45, 0x81, 0x36, 0x4d, 0x9c, 0x16, 0x48, 0x0b, 0xd4,
+	0x06, 0x9d, 0xab, 0xde, 0x18, 0x8c, 0xc4, 0x28, 0x02, 0x24, 0x52, 0x20, 0xe9, 0xa4, 0x7e, 0x84,
+	0x5e, 0xf4, 0xe5, 0x7a, 0xdb, 0x97, 0x29, 0x28, 0xd1, 0xf2, 0xff, 0xb4, 0x40, 0xd1, 0x3b, 0x4a,
+	0xfc, 0x7e, 0x87, 0xe4, 0xf7, 0x1d, 0x4a, 0xf0, 0xf7, 0x6d, 0x5b, 0x90, 0x91, 0xe3, 0xf1, 0xd8,
+	0xf5, 0xb8, 0xa0, 0xae, 0xc7, 0xd9, 0x75, 0x18, 0x38, 0x89, 0xe0, 0x8a, 0x23, 0x18, 0x4f, 0x0a,
+	0xba, 0x7d, 0x30, 0x27, 0x24, 0x49, 0xe2, 0x0a, 0x3e, 0x54, 0x54, 0xcc, 0x30, 0xdb, 0xbb, 0x4b,
+	0x74, 0x3e, 0x93, 0xb3, 0xa2, 0xc3, 0x85, 0x55, 0xe3, 0x98, 0x33, 0x37, 0xe2, 0xc4, 0xa7, 0xc2,
+	0x55, 0xa3, 0x84, 0x1a, 0xe1, 0xde, 0x72, 0x21, 0xa3, 0xca, 0x4d, 0xb8, 0x50, 0xf7, 0x97, 0xd3,
+	0x2a, 0xe2, 0xfb, 0x82, 0x4a, 0x69, 0x84, 0x07, 0xab, 0xd6, 0x0d, 0x66, 0xf7, 0xe7, 0xcc, 0xe9,
+	0x94, 0x20, 0x4c, 0xea, 0x05, 0xdd, 0x90, 0x29, 0x2a, 0x74, 0xe1, 0x19, 0xfd, 0xfe, 0x4a, 0xfd,
+	0xb4, 0xac, 0x79, 0x0c, 0x3b, 0xa7, 0x51, 0xc4, 0x3d, 0xa2, 0x42, 0xce, 0xfa, 0x4a, 0x10, 0x45,
+	0x83, 0x51, 0x87, 0x33, 0x6f, 0x28, 0x04, 0x65, 0xde, 0x08, 0xfd, 0x0e, 0xeb, 0xb7, 0x24, 0x1a,
+	0x52, 0xdb, 0x6a, 0x58, 0xad, 0x5f, 0x70, 0xf6, 0xd0, 0x7c, 0x04, 0x7f, 0x2d, 0x62, 0x98, 0x5e,
+	0x0b, 0x2a, 0x6f, 0x56, 0x20, 0x1f, 0x0b, 0x80, 0x16, 0x19, 0xf4, 0x04, 0x4a, 0xda, 0xdc, 0x54,
+	0xbb, 0xd5, 0xde, 0x75, 0x26, 0xf9, 0x3a, 0x8b, 0x6a, 0xe7, 0x72, 0x94, 0x50, 0x9c, 0x02, 0xe8,
+	0x2d, 0xd4, 0xbc, 0xc9, 0x3e, 0xed, 0x42, 0xc3, 0x6a, 0xd5, 0xda, 0xff, 0xdf, 0xcf, 0x4f, 0x1d,
+	0x0c, 0x4f, 0xd3, 0xe8, 0x04, 0x36, 0x44, 0xb6, 0x7b, 0xbb, 0x98, 0x16, 0xda, 0xbf, 0xbf, 0x90,
+	0x39, 0x2a, 0x1e, 0x53, 0xcd, 0x23, 0x28, 0xe9, 0xbd, 0x21, 0x80, 0xf2, 0x69, 0x74, 0x47, 0x46,
+	0xb2, 0xbe, 0xa6, 0xc7, 0x98, 0x30, 0x9f, 0xc7, 0x75, 0x0b, 0x6d, 0x42, 0xe5, 0xd5, 0x07, 0x9d,
+	0x13, 0x89, 0xea, 0x85, 0xe6, 0xe7, 0x22, 0xfc, 0x79, 0xc1, 0xae, 0xf8, 0x90, 0xf9, 0x1d, 0xce,
+	0x18, 0xf5, 0x74, 0xed, 0x4e, 0x9a, 0x0b, 0xea, 0x40, 0x45, 0x52, 0xa5, 0x42, 0x16, 0xc8, 0xd4,
+	0x94, 0x5a, 0xfb, 0x70, 0x7a, 0x2f, 0x59, 0x7f, 0x38, 0x59, 0x5f, 0xa6, 0x7e, 0xf8, 0x7d, 0x23,
+	0xc7, 0x39, 0x88, 0x4e, 0x00, 0x74, 0xd6, 0x03, 0x41, 0x58, 0x40, 0x8d, 0x37, 0x8d, 0x25, 0x65,
+	0x18, 0x55, 0x4e, 0x8f, 0x0b, 0x85, 0xb5, 0x0e, 0x57, 0x93, 0xf1, 0x10, 0xbd, 0x80, 0x6a, 0x14,
+	0x4a, 0x45, 0xd9, 0x80, 0x33, 0x63, 0xc9, 0x7f, 0x2b, 0xf8, 0x8b, 0x5e, 0x57, 0x9c, 0xf3, 0x98,
+	0x84, 0x0c, 0x57, 0x32, 0xa6, 0xcb, 0x50, 0x1d, 0x8a, 0x8a, 0x04, 0x76, 0xa9, 0x61, 0xb5, 0xaa,
+	0x58, 0x0f, 0x51, 0x17, 0x7e, 0x23, 0xb9, 0x8f, 0x03, 0x69, 0x8c, 0xb4, 0xd7, 0xd3, 0xda, 0xff,
+	0x7e, 0xc3, 0x6e, 0x44, 0x16, 0x3b, 0xe7, 0x12, 0x7e, 0x95, 0x4a, 0x50, 0x12, 0x0f, 0x72, 0xbf,
+	0xca, 0x69, 0xb1, 0x87, 0xd3, 0xc5, 0xf2, 0xbe, 0x77, 0xc6, 0xf7, 0xc4, 0xe9, 0xa7, 0x54, 0x66,
+	0x37, 0xde, 0xca, 0x6a, 0x8c, 0x3d, 0x44, 0x4f, 0xc1, 0xd6, 0x6b, 0xdd, 0x0d, 0x12, 0x22, 0x65,
+	0x78, 0x4b, 0x07, 0x5e, 0x1e, 0x90, 0xbd, 0xd1, 0xb0, 0x5a, 0x15, 0xfc, 0x47, 0x3a, 0xdf, 0xcb,
+	0xa6, 0x27, 0xf1, 0x35, 0x3f, 0x15, 0xc0, 0xee, 0x0e, 0xd5, 0x4f, 0x4c, 0xf5, 0x1c, 0x36, 0x25,
+	0x65, 0xfe, 0x40, 0xdd, 0x08, 0x3e, 0x0c, 0x6e, 0x4c, 0xae, 0xdf, 0x91, 0x4b, 0x4d, 0x63, 0x97,
+	0x19, 0xb5, 0xcc, 0xb7, 0xe2, 0x8f, 0xfb, 0xb6, 0x10, 0x78, 0xf3, 0x4b, 0x01, 0xca, 0xe6, 0xf4,
+	0xcf, 0x61, 0x23, 0xcc, 0xda, 0xdd, 0xb6, 0x1a, 0xc5, 0x56, 0x6d, 0xf6, 0x9e, 0xaf, 0xb8, 0x09,
+	0x78, 0xcc, 0xa0, 0x97, 0x50, 0xe1, 0xc6, 0x58, 0xbb, 0x90, 0xf2, 0x7b, 0xd3, 0xfc, 0x2a, 0xd3,
+	0x71, 0x4e, 0x21, 0x17, 0x8a, 0x11, 0x0f, 0xcc, 0x39, 0x77, 0x96, 0x3a, 0x1f, 0x38, 0x86, 0xd2,
+	0x4a, 0x74, 0x0c, 0xe5, 0xec, 0x57, 0x92, 0x9e, 0x68, 0x8e, 0x21, 0x49, 0xe2, 0x64, 0xb3, 0x63,
+	0xc6, 0x88, 0xd1, 0x11, 0x14, 0x7d, 0x26, 0x4d, 0x53, 0x6f, 0xcf, 0x33, 0x3e, 0x93, 0xf9, 0x22,
+	0x3e, 0x93, 0xe8, 0x19, 0x54, 0x73, 0x9b, 0x4d, 0xef, 0xfe, 0xb3, 0x3c, 0x03, 0x43, 0x4d, 0xe4,
+	0x0f, 0x0e, 0x60, 0x33, 0x7b, 0xf9, 0x9a, 0x8b, 0x98, 0x28, 0xfd, 0x81, 0xe9, 0xe9, 0x2f, 0xfa,
+	0xd5, 0xf0, 0xba, 0xbe, 0x86, 0x2a, 0x50, 0x7a, 0xd3, 0xef, 0xbe, 0xab, 0x5b, 0x67, 0xbb, 0xb0,
+	0xe5, 0xf1, 0x78, 0xaa, 0xea, 0x59, 0x2d, 0xe3, 0x52, 0xf5, 0xfb, 0x92, 0x7e, 0x75, 0x55, 0x4e,
+	0x7f, 0x06, 0x8f, 0xbf, 0x06, 0x00, 0x00, 0xff, 0xff, 0x4c, 0xd4, 0x2c, 0xd9, 0x7b, 0x07, 0x00,
+	0x00,
 }

+ 4 - 7
config.proto

@@ -7,14 +7,13 @@ option java_outer_classname = "ConfigProto";
 
 import "v2ray.com/core/app/router/config.proto";
 import "v2ray.com/core/app/dns/config.proto";
+import "v2ray.com/core/common/loader/type.proto";
 import "v2ray.com/core/common/net/port.proto";
 import "v2ray.com/core/common/net/address.proto";
 import "v2ray.com/core/common/log/config.proto";
 import "v2ray.com/core/transport/internet/config.proto";
 import "v2ray.com/core/transport/config.proto";
 
-import "google/protobuf/any.proto";
-
 enum ConfigFormat {
   Protobuf = 0;
   JSON = 1;
@@ -51,22 +50,20 @@ message AllocationStrategy {
 
 // Config for an inbound connection handler.
 message InboundConnectionConfig {
-  string protocol = 1;
+  v2ray.core.common.loader.TypedSettings settings = 1;
   v2ray.core.common.net.PortRange port_range = 2;
   v2ray.core.common.net.IPOrDomain listen_on = 3;
   string tag = 4;
   AllocationStrategy allocation_strategy = 5;
   v2ray.core.transport.internet.StreamConfig stream_settings = 6;
-  google.protobuf.Any settings = 7;
-  bool allow_passive_connection = 8;
+  bool allow_passive_connection = 7;
 }
 
 message OutboundConnectionConfig {
-  string protocol = 1;
+  v2ray.core.common.loader.TypedSettings settings = 1;
   v2ray.core.common.net.IPOrDomain send_through = 2;
   v2ray.core.transport.internet.StreamConfig stream_settings = 3;
   string tag = 4;
-  google.protobuf.Any settings = 5;
 }
 
 message Config {

+ 1 - 1
inbound_detour_always.go

@@ -28,7 +28,7 @@ func NewInboundDetourHandlerAlways(space app.Space, config *InboundConnectionCon
 		if err != nil {
 			return nil, err
 		}
-		ich, err := proxyregistry.CreateInboundHandler(config.Protocol, space, ichConfig, &proxy.InboundHandlerMeta{
+		ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, space, ichConfig, &proxy.InboundHandlerMeta{
 			Address:                config.ListenOn.AsAddress(),
 			Port:                   i,
 			Tag:                    config.Tag,

+ 2 - 2
inbound_detour_dynamic.go

@@ -36,7 +36,7 @@ func NewInboundDetourHandlerDynamic(space app.Space, config *InboundConnectionCo
 	if err != nil {
 		return nil, err
 	}
-	ich, err := proxyregistry.CreateInboundHandler(config.Protocol, space, ichConfig, &proxy.InboundHandlerMeta{
+	ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, space, ichConfig, &proxy.InboundHandlerMeta{
 		Address:                config.ListenOn.AsAddress(),
 		Port:                   0,
 		Tag:                    config.Tag,
@@ -107,7 +107,7 @@ func (this *InboundDetourHandlerDynamic) refresh() error {
 	for idx := range newIchs {
 		err := retry.Timed(5, 100).On(func() error {
 			port := this.pickUnusedPort()
-			ich, err := proxyregistry.CreateInboundHandler(config.Protocol, this.space, config.Settings, &proxy.InboundHandlerMeta{
+			ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, this.space, config.Settings, &proxy.InboundHandlerMeta{
 				Address: config.ListenOn.AsAddress(), Port: port, Tag: config.Tag, StreamSettings: config.StreamSettings})
 			if err != nil {
 				delete(this.portsInUse, port)

+ 13 - 1
main/main.go

@@ -7,6 +7,7 @@ import (
 	"os"
 	"os/signal"
 	"path/filepath"
+	"strings"
 	"syscall"
 
 	"v2ray.com/core"
@@ -29,6 +30,17 @@ func init() {
 	flag.StringVar(&configFile, "config", defaultConfigFile, "Config file for this Point server.")
 }
 
+func GetConfigFormat() core.ConfigFormat {
+	switch strings.ToLower(*format) {
+	case "json":
+		return core.ConfigFormat_JSON
+	case "pb", "protobuf":
+		return core.ConfigFormat_Protobuf
+	default:
+		return core.ConfigFormat_JSON
+	}
+}
+
 func startV2Ray() *core.Point {
 	if len(configFile) == 0 {
 		log.Error("Config file is not set.")
@@ -47,7 +59,7 @@ func startV2Ray() *core.Point {
 		defer file.Close()
 		configInput = file
 	}
-	config, err := core.LoadConfig(configInput)
+	config, err := core.LoadConfig(GetConfigFormat(), configInput)
 	if err != nil {
 		log.Error("Failed to read config file (", configFile, "): ", configFile, err)
 		return nil

+ 3 - 2
proxy/blackhole/blackhole.go

@@ -3,6 +3,7 @@ package blackhole
 import (
 	"v2ray.com/core/app"
 	"v2ray.com/core/common/alloc"
+	"v2ray.com/core/common/loader"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/proxy"
 	"v2ray.com/core/proxy/registry"
@@ -16,7 +17,7 @@ type BlackHole struct {
 }
 
 func NewBlackHole(space app.Space, config *Config, meta *proxy.OutboundHandlerMeta) (*BlackHole, error) {
-	response, err := config.Response.GetInternalResponse()
+	response, err := config.GetInternalResponse()
 	if err != nil {
 		return nil, err
 	}
@@ -50,5 +51,5 @@ func (this *Factory) Create(space app.Space, config interface{}, meta *proxy.Out
 }
 
 func init() {
-	registry.MustRegisterOutboundHandlerCreator("blackhole", new(Factory))
+	registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
 }

+ 4 - 23
proxy/blackhole/config.go

@@ -4,11 +4,8 @@ import (
 	"v2ray.com/core/common/alloc"
 	v2io "v2ray.com/core/common/io"
 
-	"github.com/golang/protobuf/proto"
 	"github.com/golang/protobuf/ptypes"
 	"github.com/golang/protobuf/ptypes/any"
-	"strings"
-	"v2ray.com/core/common/loader"
 )
 
 const (
@@ -42,30 +39,14 @@ func (this *HTTPResponse) AsAny() *any.Any {
 	return r
 }
 
-func (this *Response) GetInternalResponse() (ResponseConfig, error) {
-	if this == nil {
+func (this *Config) GetInternalResponse() (ResponseConfig, error) {
+	if this.GetResponse() == nil {
 		return new(NoneResponse), nil
 	}
 
-	var r ResponseConfig
-	switch this.Type {
-	case Response_None:
-		r = new(NoneResponse)
-	case Response_HTTP:
-		r = new(HTTPResponse)
-	}
-	err := ptypes.UnmarshalAny(this.Settings, r.(proto.Message))
+	config, err := this.GetResponse().GetInstance()
 	if err != nil {
 		return nil, err
 	}
-	return r, nil
-}
-
-var (
-	cache = loader.ConfigCreatorCache{}
-)
-
-func init() {
-	cache.RegisterCreator(strings.ToLower(Response_Type_name[int32(Response_None)]), func() interface{} { return new(NoneResponse) })
-	cache.RegisterCreator(strings.ToLower(Response_Type_name[int32(Response_HTTP)]), func() interface{} { return new(HTTPResponse) })
+	return config.(ResponseConfig), nil
 }

+ 10 - 16
proxy/blackhole/config_json.go

@@ -6,9 +6,8 @@ import (
 	"encoding/json"
 	"errors"
 
-	"strings"
+	"github.com/golang/protobuf/proto"
 	"v2ray.com/core/common/loader"
-	"v2ray.com/core/proxy/registry"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -21,27 +20,22 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 	}
 
 	if jsonConfig.Response != nil {
-		response, rType, err := configLoader.Load(jsonConfig.Response)
+		response, _, err := configLoader.Load(jsonConfig.Response)
 		if err != nil {
 			return errors.New("Blackhole: Failed to parse response config: " + err.Error())
 		}
-		this.Response = new(Response)
-		switch rType {
-		case strings.ToLower(Response_Type_name[int32(Response_None)]):
-			this.Response.Type = Response_None
-		case strings.ToLower(Response_Type_name[int32(Response_HTTP)]):
-			this.Response.Type = Response_HTTP
-		}
-		this.Response.Settings = response.(ResponseConfig).AsAny()
+		this.Response = loader.NewTypedSettings(response.(proto.Message))
 	}
 
 	return nil
 }
 
 var (
-	configLoader = loader.NewJSONConfigLoader(cache, "type", "")
+	configLoader = loader.NewJSONConfigLoader(
+		loader.NamedTypeMap{
+			"none": loader.GetType(new(NoneResponse)),
+			"http": loader.GetType(new(HTTPResponse)),
+		},
+		"type",
+		"")
 )
-
-func init() {
-	registry.RegisterOutboundConfig("blackhole", func() interface{} { return new(Config) })
-}

+ 0 - 5
proxy/dokodemo/config_json.go

@@ -7,7 +7,6 @@ import (
 	"errors"
 
 	v2net "v2ray.com/core/common/net"
-	"v2ray.com/core/proxy/registry"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -31,7 +30,3 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 	this.FollowRedirect = rawConfig.Redirect
 	return nil
 }
-
-func init() {
-	registry.RegisterInboundConfig("dokodemo-door", func() interface{} { return new(Config) })
-}

+ 2 - 1
proxy/dokodemo/dokodemo.go

@@ -7,6 +7,7 @@ import (
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/common/alloc"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/proxy"
@@ -205,5 +206,5 @@ func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.
 }
 
 func init() {
-	registry.MustRegisterInboundHandlerCreator("dokodemo-door", new(Factory))
+	registry.MustRegisterInboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
 }

+ 0 - 6
proxy/freedom/config_json.go

@@ -6,8 +6,6 @@ import (
 	"encoding/json"
 	"errors"
 	"strings"
-
-	"v2ray.com/core/proxy/registry"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -27,7 +25,3 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 	this.Timeout = jsonConfig.Timeout
 	return nil
 }
-
-func init() {
-	registry.RegisterOutboundConfig("freedom", func() interface{} { return new(Config) })
-}

+ 2 - 1
proxy/freedom/freedom.go

@@ -8,6 +8,7 @@ import (
 	"v2ray.com/core/common/alloc"
 	"v2ray.com/core/common/dice"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/retry"
@@ -140,5 +141,5 @@ func (this *FreedomFactory) Create(space app.Space, config interface{}, meta *pr
 }
 
 func init() {
-	registry.MustRegisterOutboundHandlerCreator("freedom", new(FreedomFactory))
+	registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(FreedomFactory))
 }

+ 0 - 6
proxy/http/config_json.go

@@ -5,8 +5,6 @@ package http
 import (
 	"encoding/json"
 	"errors"
-
-	"v2ray.com/core/proxy/registry"
 )
 
 // UnmarshalJSON implements json.Unmarshaler
@@ -22,7 +20,3 @@ func (this *ServerConfig) UnmarshalJSON(data []byte) error {
 
 	return nil
 }
-
-func init() {
-	registry.RegisterInboundConfig("http", func() interface{} { return new(ServerConfig) })
-}

+ 2 - 1
proxy/http/server.go

@@ -13,6 +13,7 @@ import (
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/common"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/proxy"
@@ -281,5 +282,5 @@ func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *
 }
 
 func init() {
-	registry.MustRegisterInboundHandlerCreator("http", new(ServerFactory))
+	registry.MustRegisterInboundHandlerCreator(loader.GetType(new(ServerConfig)), new(ServerFactory))
 }

+ 0 - 50
proxy/registry/config_cache.go

@@ -1,50 +0,0 @@
-package registry
-
-import (
-	"v2ray.com/core/common/loader"
-
-	"github.com/golang/protobuf/proto"
-	"github.com/golang/protobuf/ptypes"
-	"github.com/golang/protobuf/ptypes/any"
-)
-
-var (
-	inboundConfigCreatorCache  = loader.ConfigCreatorCache{}
-	outboundConfigCreatorCache = loader.ConfigCreatorCache{}
-)
-
-func RegisterInboundConfig(protocol string, creator loader.ConfigCreator) error {
-	return inboundConfigCreatorCache.RegisterCreator(protocol, creator)
-}
-
-func RegisterOutboundConfig(protocol string, creator loader.ConfigCreator) error {
-	return outboundConfigCreatorCache.RegisterCreator(protocol, creator)
-}
-
-func MarshalInboundConfig(protocol string, settings *any.Any) (interface{}, error) {
-	config, err := inboundConfigCreatorCache.CreateConfig(protocol)
-	if err != nil {
-		return nil, err
-	}
-	if settings == nil {
-		return config, nil
-	}
-	if err := ptypes.UnmarshalAny(settings, config.(proto.Message)); err != nil {
-		return nil, err
-	}
-	return config, nil
-}
-
-func MarshalOutboundConfig(protocol string, settings *any.Any) (interface{}, error) {
-	config, err := outboundConfigCreatorCache.CreateConfig(protocol)
-	if err != nil {
-		return nil, err
-	}
-	if settings == nil {
-		return config, nil
-	}
-	if err := ptypes.UnmarshalAny(settings, config.(proto.Message)); err != nil {
-		return nil, err
-	}
-	return config, nil
-}

+ 0 - 25
proxy/registry/config_cache_json.go

@@ -1,25 +0,0 @@
-// +build json
-
-package registry
-
-import (
-	"v2ray.com/core/common/loader"
-)
-
-var (
-	inboundConfigCache  loader.ConfigLoader
-	outboundConfigCache loader.ConfigLoader
-)
-
-func CreateInboundConfig(protocol string, data []byte) (interface{}, error) {
-	return inboundConfigCache.LoadWithID(data, protocol)
-}
-
-func CreateOutboundConfig(protocol string, data []byte) (interface{}, error) {
-	return outboundConfigCache.LoadWithID(data, protocol)
-}
-
-func init() {
-	inboundConfigCache = loader.NewJSONConfigLoader(inboundConfigCreatorCache, "protocol", "settings")
-	outboundConfigCache = loader.NewJSONConfigLoader(outboundConfigCreatorCache, "protocol", "settings")
-}

+ 2 - 13
proxy/shadowsocks/config_json.go

@@ -8,11 +8,9 @@ import (
 	"strings"
 
 	"v2ray.com/core/common"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	"v2ray.com/core/common/protocol"
-	"v2ray.com/core/proxy/registry"
-
-	"github.com/golang/protobuf/ptypes"
 )
 
 func (this *ServerConfig) UnmarshalJSON(data []byte) error {
@@ -52,20 +50,11 @@ func (this *ServerConfig) UnmarshalJSON(data []byte) error {
 		return common.ErrBadConfiguration
 	}
 
-	anyAccount, err := ptypes.MarshalAny(account)
-	if err != nil {
-		log.Error("Shadowsocks: Failed to create account: ", err)
-		return common.ErrBadConfiguration
-	}
 	this.User = &protocol.User{
 		Email:   jsonConfig.Email,
 		Level:   uint32(jsonConfig.Level),
-		Account: anyAccount,
+		Account: loader.NewTypedSettings(account),
 	}
 
 	return nil
 }
-
-func init() {
-	registry.RegisterInboundConfig("shadowsocks", func() interface{} { return new(ServerConfig) })
-}

+ 4 - 2
proxy/shadowsocks/config_json_test.go

@@ -21,10 +21,12 @@ func TestConfigParsing(t *testing.T) {
 	err := json.Unmarshal([]byte(rawJson), config)
 	assert.Error(err).IsNil()
 
-	account := new(Account)
-	_, err = config.User.GetTypedAccount(account)
+	rawAccount, err = config.User.GetTypedAccount()
 	assert.Error(err).IsNil()
 
+	account, ok := rawAccount.(*Account)
+	assert.Bool(ok).IsTrue()
+
 	cipher, err := account.GetCipher()
 	assert.Error(err).IsNil()
 	assert.Int(cipher.KeySize()).Equals(16)

+ 8 - 3
proxy/shadowsocks/server.go

@@ -12,6 +12,7 @@ import (
 	"v2ray.com/core/common/alloc"
 	"v2ray.com/core/common/crypto"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
@@ -37,10 +38,14 @@ func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandler
 	if config.GetUser() == nil {
 		return nil, protocol.ErrUserMissing
 	}
-	account := new(Account)
-	if _, err := config.GetUser().GetTypedAccount(account); err != nil {
+	rawAccount, err := config.GetUser().GetTypedAccount()
+	if err != nil {
 		return nil, err
 	}
+	account, ok := rawAccount.(*Account)
+	if !ok {
+		return nil, protocol.ErrUnknownAccountType
+	}
 	cipher, err := account.GetCipher()
 	if err != nil {
 		return nil, err
@@ -292,5 +297,5 @@ func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *
 }
 
 func init() {
-	registry.MustRegisterInboundHandlerCreator("shadowsocks", new(ServerFactory))
+	registry.MustRegisterInboundHandlerCreator(loader.GetType(new(ServerConfig)), new(ServerFactory))
 }

+ 4 - 9
proxy/socks/config.go

@@ -8,7 +8,6 @@ import (
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
-	"v2ray.com/core/proxy/registry"
 
 	"github.com/golang/protobuf/ptypes"
 	google_protobuf "github.com/golang/protobuf/ptypes/any"
@@ -58,11 +57,11 @@ const (
 
 func (this *ServerConfig) UnmarshalJSON(data []byte) error {
 	type SocksConfig struct {
-		AuthMethod string           `json:"auth"`
-		Accounts   []*Account       `json:"accounts"`
-		UDP        bool             `json:"udp"`
+		AuthMethod string            `json:"auth"`
+		Accounts   []*Account        `json:"accounts"`
+		UDP        bool              `json:"udp"`
 		Host       *v2net.IPOrDomain `json:"ip"`
-		Timeout    uint32           `json:"timeout"`
+		Timeout    uint32            `json:"timeout"`
 	}
 
 	rawConfig := new(SocksConfig)
@@ -95,7 +94,3 @@ func (this *ServerConfig) UnmarshalJSON(data []byte) error {
 	}
 	return nil
 }
-
-func init() {
-	registry.RegisterInboundConfig("socks", func() interface{} { return new(ServerConfig) })
-}

+ 3 - 11
proxy/socks/config_json.go

@@ -6,9 +6,9 @@ import (
 	"encoding/json"
 	"errors"
 
+	"v2ray.com/core/common/loader"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
-	"v2ray.com/core/proxy/registry"
 )
 
 func (this *Account) UnmarshalJSON(data []byte) error {
@@ -27,7 +27,7 @@ func (this *Account) UnmarshalJSON(data []byte) error {
 
 func (this *ClientConfig) UnmarshalJSON(data []byte) error {
 	type ServerConfig struct {
-		Address *v2net.IPOrDomain  `json:"address"`
+		Address *v2net.IPOrDomain `json:"address"`
 		Port    v2net.Port        `json:"port"`
 		Users   []json.RawMessage `json:"users"`
 	}
@@ -53,18 +53,10 @@ func (this *ClientConfig) UnmarshalJSON(data []byte) error {
 			if err := json.Unmarshal(rawUser, account); err != nil {
 				return errors.New("Socks|Client: Failed to parse socks account: " + err.Error())
 			}
-			anyAccount, err := account.AsAny()
-			if err != nil {
-				return err
-			}
-			user.Account = anyAccount
+			user.Account = loader.NewTypedSettings(account)
 			server.User = append(server.User, user)
 		}
 		this.Server[idx] = server
 	}
 	return nil
 }
-
-func init() {
-	registry.RegisterOutboundConfig("socks", func() interface{} { return new(ClientConfig) })
-}

+ 2 - 1
proxy/socks/server.go

@@ -9,6 +9,7 @@ import (
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/proxy"
@@ -326,5 +327,5 @@ func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *
 }
 
 func init() {
-	registry.MustRegisterInboundHandlerCreator("socks", new(ServerFactory))
+	registry.MustRegisterInboundHandlerCreator(loader.GetType(new(ServerConfig)), new(ServerFactory))
 }

+ 1 - 1
proxy/vmess/encoding/client.go

@@ -52,7 +52,7 @@ func NewClientSession(idHash protocol.IDHash) *ClientSession {
 
 func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) {
 	timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)()
-	account, err := header.User.GetTypedAccount(&vmess.Account{})
+	account, err := header.User.GetTypedAccount()
 	if err != nil {
 		log.Error("VMess: Failed to get user account: ", err)
 		return

+ 2 - 1
proxy/vmess/encoding/server.go

@@ -59,11 +59,12 @@ func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Requ
 	timestampHash := md5.New()
 	timestampHash.Write(hashTimestamp(timestamp))
 	iv := timestampHash.Sum(nil)
-	account, err := user.GetTypedAccount(&vmess.Account{})
+	account, err := user.GetTypedAccount()
 	if err != nil {
 		log.Error("Vmess: Failed to get user account: ", err)
 		return nil, err
 	}
+
 	aesStream := crypto.NewAesDecryptionStream(account.(*vmess.InternalAccount).ID.CmdKey(), iv)
 	decryptor := crypto.NewCryptionReader(aesStream, reader)
 

+ 1 - 1
proxy/vmess/inbound/command.go

@@ -22,7 +22,7 @@ func (this *VMessInboundHandler) generateCommand(request *protocol.RequestHeader
 				if user == nil {
 					return nil
 				}
-				account, _ := user.GetTypedAccount(&vmess.Account{})
+				account, _ := user.GetTypedAccount()
 				return &protocol.CommandSwitchAccount{
 					Port:     inboundHandler.Port(),
 					ID:       account.(*vmess.InternalAccount).ID.UUID(),

+ 2 - 15
proxy/vmess/inbound/config_json.go

@@ -6,13 +6,9 @@ import (
 	"encoding/json"
 	"errors"
 
-	"v2ray.com/core/common"
-	"v2ray.com/core/common/log"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/protocol"
-	"v2ray.com/core/proxy/registry"
 	"v2ray.com/core/proxy/vmess"
-
-	"github.com/golang/protobuf/ptypes"
 )
 
 func (this *DetourConfig) UnmarshalJSON(data []byte) error {
@@ -81,18 +77,9 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 		if err := json.Unmarshal(rawData, account); err != nil {
 			return errors.New("VMess|Inbound: Invalid user: " + err.Error())
 		}
-		anyAccount, err := ptypes.MarshalAny(account)
-		if err != nil {
-			log.Error("VMess|Inbound: Failed to create account: ", err)
-			return common.ErrBadConfiguration
-		}
-		user.Account = anyAccount
+		user.Account = loader.NewTypedSettings(account)
 		this.User[idx] = user
 	}
 
 	return nil
 }
-
-func init() {
-	registry.RegisterInboundConfig("vmess", func() interface{} { return new(Config) })
-}

+ 3 - 5
proxy/vmess/inbound/inbound.go

@@ -10,6 +10,7 @@ import (
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/alloc"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
@@ -20,8 +21,6 @@ import (
 	"v2ray.com/core/proxy/vmess/encoding"
 	vmessio "v2ray.com/core/proxy/vmess/io"
 	"v2ray.com/core/transport/internet"
-
-	"github.com/golang/protobuf/ptypes"
 )
 
 type userByEmail struct {
@@ -57,11 +56,10 @@ func (this *userByEmail) Get(email string) (*protocol.User, bool) {
 				Id:      uuid.New().String(),
 				AlterId: uint32(this.defaultAlterIDs),
 			}
-			anyAccount, _ := ptypes.MarshalAny(account)
 			user = &protocol.User{
 				Level:   this.defaultLevel,
 				Email:   email,
-				Account: anyAccount,
+				Account: loader.NewTypedSettings(account),
 			}
 			this.cache[email] = user
 		}
@@ -282,5 +280,5 @@ func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.
 }
 
 func init() {
-	registry.MustRegisterInboundHandlerCreator("vmess", new(Factory))
+	registry.MustRegisterInboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
 }

+ 3 - 4
proxy/vmess/outbound/command.go

@@ -3,11 +3,10 @@ package outbound
 import (
 	"time"
 
+	"v2ray.com/core/common/loader"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/proxy/vmess"
-
-	"github.com/golang/protobuf/ptypes"
 )
 
 func (this *VMessOutboundHandler) handleSwitchAccount(cmd *protocol.CommandSwitchAccount) {
@@ -15,11 +14,11 @@ func (this *VMessOutboundHandler) handleSwitchAccount(cmd *protocol.CommandSwitc
 		Id:      cmd.ID.String(),
 		AlterId: uint32(cmd.AlterIds),
 	}
-	anyAccount, _ := ptypes.MarshalAny(account)
+
 	user := &protocol.User{
 		Email:   "",
 		Level:   cmd.Level,
-		Account: anyAccount,
+		Account: loader.NewTypedSettings(account),
 	}
 	dest := v2net.TCPDestination(cmd.Host, cmd.Port)
 	until := time.Now().Add(time.Duration(cmd.ValidMin) * time.Minute)

+ 2 - 13
proxy/vmess/outbound/config_json.go

@@ -7,14 +7,12 @@ import (
 	"errors"
 
 	"v2ray.com/core/common"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/serial"
-	"v2ray.com/core/proxy/registry"
 	"v2ray.com/core/proxy/vmess"
-
-	"github.com/golang/protobuf/ptypes"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -65,12 +63,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 				log.Error("VMess|Outbound: Invalid user: ", err)
 				return err
 			}
-			anyAccount, err := ptypes.MarshalAny(account)
-			if err != nil {
-				log.Error("VMess|Outbound: Failed to create account: ", err)
-				return common.ErrBadConfiguration
-			}
-			user.Account = anyAccount
+			user.Account = loader.NewTypedSettings(account)
 			spec.User = append(spec.User, user)
 		}
 		serverSpecs[idx] = spec
@@ -78,7 +71,3 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 	this.Receiver = serverSpecs
 	return nil
 }
-
-func init() {
-	registry.RegisterOutboundConfig("vmess", func() interface{} { return new(Config) })
-}

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

@@ -7,6 +7,7 @@ import (
 	"v2ray.com/core/app"
 	"v2ray.com/core/common/alloc"
 	v2io "v2ray.com/core/common/io"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
@@ -183,5 +184,5 @@ func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.
 }
 
 func init() {
-	registry.MustRegisterOutboundHandlerCreator("vmess", new(Factory))
+	registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
 }

+ 1 - 1
proxy/vmess/vmess.go

@@ -118,7 +118,7 @@ L:
 func (this *TimedUserValidator) Add(user *protocol.User) error {
 	idx := len(this.validUsers)
 	this.validUsers = append(this.validUsers, user)
-	rawAccount, err := user.GetTypedAccount(&Account{})
+	rawAccount, err := user.GetTypedAccount()
 	if err != nil {
 		return err
 	}

+ 76 - 0
tools/conf/common.go

@@ -0,0 +1,76 @@
+package conf
+
+import (
+	"encoding/json"
+	"errors"
+
+	"strings"
+	v2net "v2ray.com/core/common/net"
+)
+
+type Address struct {
+	v2net.Address
+}
+
+func (this *Address) UnmarshalJSON(data []byte) error {
+	var rawStr string
+	if err := json.Unmarshal(data, &rawStr); err != nil {
+		return err
+	}
+	this.Address = v2net.ParseAddress(rawStr)
+
+	return nil
+}
+
+func (this *Address) Build() *v2net.IPOrDomain {
+	if this.Family().IsDomain() {
+		return &v2net.IPOrDomain{
+			Address: &v2net.IPOrDomain_Domain{
+				Domain: this.Domain(),
+			},
+		}
+	}
+
+	return &v2net.IPOrDomain{
+		Address: &v2net.IPOrDomain_Ip{
+			Ip: []byte(this.IP()),
+		},
+	}
+}
+
+type Network string
+
+func (this Network) Build() v2net.Network {
+	return v2net.ParseNetwork(string(this))
+}
+
+type NetworkList []Network
+
+func (this *NetworkList) UnmarshalJSON(data []byte) error {
+	var strarray []Network
+	if err := json.Unmarshal(data, &strarray); err == nil {
+		nl := NetworkList(strarray)
+		*this = nl
+		return nil
+	}
+
+	var rawstr Network
+	if err := json.Unmarshal(data, &rawstr); err == nil {
+		strlist := strings.Split(string(rawstr), ",")
+		nl := make([]Network, len(strlist))
+		for idx, network := range strlist {
+			nl[idx] = Network(network)
+		}
+		*this = nl
+		return nil
+	}
+	return errors.New("Unknown format of a string list: " + string(data))
+}
+
+func (this *NetworkList) Build() *v2net.NetworkList {
+	list := new(v2net.NetworkList)
+	for _, network := range *this {
+		list.Network = append(list.Network, network.Build())
+	}
+	return list
+}

+ 80 - 0
tools/conf/common_test.go

@@ -0,0 +1,80 @@
+package conf_test
+
+import (
+	"encoding/json"
+	"testing"
+
+	v2net "v2ray.com/core/common/net"
+	"v2ray.com/core/testing/assert"
+	. "v2ray.com/core/tools/conf"
+)
+
+func TestIPParsing(t *testing.T) {
+	assert := assert.On(t)
+
+	rawJson := "\"8.8.8.8\""
+	var address Address
+	err := json.Unmarshal([]byte(rawJson), &address)
+	assert.Error(err).IsNil()
+	assert.Bytes([]byte(address.IP())).Equals([]byte{8, 8, 8, 8})
+}
+
+func TestDomainParsing(t *testing.T) {
+	assert := assert.On(t)
+
+	rawJson := "\"v2ray.com\""
+	var address Address
+	err := json.Unmarshal([]byte(rawJson), &address)
+	assert.Error(err).IsNil()
+	assert.String(address.Domain()).Equals("v2ray.com")
+}
+
+func TestInvalidAddressJson(t *testing.T) {
+	assert := assert.On(t)
+
+	rawJson := "1234"
+	var address Address
+	err := json.Unmarshal([]byte(rawJson), &address)
+	assert.Error(err).IsNotNil()
+}
+
+func TestStringNetwork(t *testing.T) {
+	assert := assert.On(t)
+
+	var network Network
+	err := json.Unmarshal([]byte(`"tcp"`), &network)
+	assert.Error(err).IsNil()
+	assert.Bool(network.Build() == v2net.Network_TCP).IsTrue()
+}
+
+func TestArrayNetworkList(t *testing.T) {
+	assert := assert.On(t)
+
+	var list NetworkList
+	err := json.Unmarshal([]byte("[\"Tcp\"]"), &list)
+	assert.Error(err).IsNil()
+
+	nlist := list.Build()
+	assert.Bool(nlist.HasNetwork(v2net.ParseNetwork("tcp"))).IsTrue()
+	assert.Bool(nlist.HasNetwork(v2net.ParseNetwork("udp"))).IsFalse()
+}
+
+func TestStringNetworkList(t *testing.T) {
+	assert := assert.On(t)
+
+	var list NetworkList
+	err := json.Unmarshal([]byte("\"TCP, ip\""), &list)
+	assert.Error(err).IsNil()
+
+	nlist := list.Build()
+	assert.Bool(nlist.HasNetwork(v2net.ParseNetwork("tcp"))).IsTrue()
+	assert.Bool(nlist.HasNetwork(v2net.ParseNetwork("udp"))).IsFalse()
+}
+
+func TestInvalidNetworkJson(t *testing.T) {
+	assert := assert.On(t)
+
+	var list NetworkList
+	err := json.Unmarshal([]byte("0"), &list)
+	assert.Error(err).IsNotNil()
+}

+ 43 - 0
tools/conf/log.go

@@ -0,0 +1,43 @@
+package conf
+
+import (
+	"strings"
+
+	"v2ray.com/core/common/log"
+)
+
+type LogConfig struct {
+	AccessLog string `json:"access"`
+	ErrorLog  string `json:"error"`
+	LogLevel  string `json:"loglevel"`
+}
+
+func (this *LogConfig) Build() *log.Config {
+	if this == nil {
+		return nil
+	}
+	config := new(log.Config)
+	if len(this.AccessLog) > 0 {
+		config.AccessLogPath = this.AccessLog
+		config.AccessLogType = log.LogType_File
+	}
+	if len(this.ErrorLog) > 0 {
+		config.ErrorLogPath = this.ErrorLog
+		config.ErrorLogType = log.LogType_File
+	}
+
+	level := strings.ToLower(this.LogLevel)
+	switch level {
+	case "debug":
+		config.ErrorLogLevel = log.LogLevel_Debug
+	case "info":
+		config.ErrorLogLevel = log.LogLevel_Info
+	case "error":
+		config.ErrorLogLevel = log.LogLevel_Error
+	case "none":
+		config.ErrorLogType = log.LogType_None
+	default:
+		config.ErrorLogLevel = log.LogLevel_Warning
+	}
+	return config
+}

+ 28 - 0
tools/conf/v2ray.go

@@ -0,0 +1,28 @@
+package conf
+
+/*
+import (
+	"encoding/json"
+	"errors"
+	"io"
+
+	"v2ray.com/core/app/dns"
+	"v2ray.com/core/app/router"
+	"v2ray.com/core/common"
+	v2net "v2ray.com/core/common/net"
+	"v2ray.com/core/transport"
+	"v2ray.com/core/transport/internet"
+)
+
+type Config struct {
+	Port            uint16                    `json:"port"` // Port of this Point server.
+	LogConfig       *LogConfig                `json:"log"`
+	RouterConfig    *router.Config            `json:"routing"`
+	DNSConfig       *dns.Config               `json:"dns"`
+	InboundConfig   *InboundConnectionConfig  `json:"inbound"`
+	OutboundConfig  *OutboundConnectionConfig `json:"outbound"`
+	InboundDetours  []*InboundDetourConfig    `json:"inboundDetour"`
+	OutboundDetours []*OutboundDetourConfig   `json:"outboundDetour"`
+	Transport       *transport.Config         `json:"transport"`
+}
+*/

+ 4 - 17
transport/config_json.go

@@ -5,13 +5,12 @@ package transport
 import (
 	"encoding/json"
 
+	"v2ray.com/core/common/loader"
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
 	"v2ray.com/core/transport/internet/kcp"
 	"v2ray.com/core/transport/internet/tcp"
 	"v2ray.com/core/transport/internet/ws"
-
-	"github.com/golang/protobuf/ptypes"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -26,35 +25,23 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 	}
 
 	if jsonConfig.TCPConfig != nil {
-		any, err := ptypes.MarshalAny(jsonConfig.TCPConfig)
-		if err != nil {
-			return err
-		}
 		this.NetworkSettings = append(this.NetworkSettings, &internet.NetworkSettings{
 			Network:  v2net.Network_TCP,
-			Settings: any,
+			Settings: loader.NewTypedSettings(jsonConfig.TCPConfig),
 		})
 	}
 
 	if jsonConfig.KCPConfig != nil {
-		any, err := ptypes.MarshalAny(jsonConfig.KCPConfig)
-		if err != nil {
-			return err
-		}
 		this.NetworkSettings = append(this.NetworkSettings, &internet.NetworkSettings{
 			Network:  v2net.Network_KCP,
-			Settings: any,
+			Settings: loader.NewTypedSettings(jsonConfig.KCPConfig),
 		})
 	}
 
 	if jsonConfig.WSConfig != nil {
-		any, err := ptypes.MarshalAny(jsonConfig.WSConfig)
-		if err != nil {
-			return err
-		}
 		this.NetworkSettings = append(this.NetworkSettings, &internet.NetworkSettings{
 			Network:  v2net.Network_WebSocket,
-			Settings: any,
+			Settings: loader.NewTypedSettings(jsonConfig.WSConfig),
 		})
 	}
 	return nil

+ 0 - 43
transport/internet/authenticator.go

@@ -1,14 +1,9 @@
 package internet
 
 import (
-	"errors"
-
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/alloc"
 	"v2ray.com/core/common/loader"
-
-	"github.com/golang/protobuf/proto"
-	"github.com/golang/protobuf/ptypes"
 )
 
 type Authenticator interface {
@@ -21,40 +16,6 @@ type AuthenticatorFactory interface {
 	Create(interface{}) Authenticator
 }
 
-func (this *AuthenticatorConfig) GetInternalConfig() (interface{}, error) {
-	config, err := configCache.CreateConfig(this.Name)
-	if err != nil {
-		return nil, err
-	}
-	if err := ptypes.UnmarshalAny(this.Settings, config.(proto.Message)); err != nil {
-		return nil, err
-	}
-	return config, nil
-}
-
-func NewAuthenticatorConfig(name string, config interface{}) (*AuthenticatorConfig, error) {
-	pbMsg, ok := config.(proto.Message)
-	if !ok {
-		return nil, errors.New("Internet|Authenticator: Failed to convert config into proto message.")
-	}
-	anyConfig, err := ptypes.MarshalAny(pbMsg)
-	if err != nil {
-		return nil, err
-	}
-	return &AuthenticatorConfig{
-		Name:     name,
-		Settings: anyConfig,
-	}, nil
-}
-
-func (this *AuthenticatorConfig) CreateAuthenticator() (Authenticator, error) {
-	config, err := this.GetInternalConfig()
-	if err != nil {
-		return nil, err
-	}
-	return CreateAuthenticator(this.Name, config)
-}
-
 var (
 	authenticatorCache = make(map[string]AuthenticatorFactory)
 	configCache        = loader.ConfigCreatorCache{}
@@ -68,10 +29,6 @@ func RegisterAuthenticator(name string, factory AuthenticatorFactory) error {
 	return nil
 }
 
-func RegisterAuthenticatorConfig(name string, configCreator loader.ConfigCreator) error {
-	return configCache.RegisterCreator(name, configCreator)
-}
-
 func CreateAuthenticator(name string, config interface{}) (Authenticator, error) {
 	factory, found := authenticatorCache[name]
 	if !found {

+ 18 - 19
transport/internet/authenticator.pb.go

@@ -11,7 +11,6 @@ It is generated from these files:
 
 It has these top-level messages:
 	AuthenticatorConfig
-	SecuritySettings
 	NetworkSettings
 	StreamConfig
 */
@@ -20,7 +19,7 @@ package internet
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
-import google_protobuf "github.com/golang/protobuf/ptypes/any"
+import v2ray_core_common_loader "v2ray.com/core/common/loader"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
@@ -34,8 +33,8 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 type AuthenticatorConfig struct {
-	Name     string               `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
-	Settings *google_protobuf.Any `protobuf:"bytes,2,opt,name=settings" json:"settings,omitempty"`
+	Name     string                                  `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+	Settings *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,2,opt,name=settings" json:"settings,omitempty"`
 }
 
 func (m *AuthenticatorConfig) Reset()                    { *m = AuthenticatorConfig{} }
@@ -43,7 +42,7 @@ func (m *AuthenticatorConfig) String() string            { return proto.CompactT
 func (*AuthenticatorConfig) ProtoMessage()               {}
 func (*AuthenticatorConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
 
-func (m *AuthenticatorConfig) GetSettings() *google_protobuf.Any {
+func (m *AuthenticatorConfig) GetSettings() *v2ray_core_common_loader.TypedSettings {
 	if m != nil {
 		return m.Settings
 	}
@@ -59,18 +58,18 @@ func init() {
 }
 
 var fileDescriptor0 = []byte{
-	// 197 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x8e, 0xc1, 0x4a, 0xc4, 0x40,
-	0x0c, 0x40, 0xa9, 0x88, 0xac, 0xe3, 0x6d, 0xf4, 0xb0, 0x0a, 0xc2, 0xea, 0x69, 0x4f, 0x19, 0xa9,
-	0xf8, 0x01, 0xad, 0x3f, 0x20, 0x3d, 0xea, 0x69, 0x3a, 0xa4, 0xe3, 0x80, 0x4d, 0x4a, 0x9a, 0x0a,
-	0xfd, 0x7b, 0xb1, 0x65, 0x8a, 0x5e, 0xf6, 0x16, 0xc8, 0x7b, 0x2f, 0x31, 0x2f, 0xdf, 0xa5, 0xf8,
-	0x19, 0x02, 0xf7, 0x2e, 0xb0, 0xa0, 0x53, 0xf1, 0x34, 0x0e, 0x2c, 0xea, 0x12, 0x29, 0x0a, 0xa1,
-	0x3a, 0x3f, 0xe9, 0x27, 0x92, 0xa6, 0xe0, 0x95, 0x05, 0x06, 0x61, 0x65, 0x7b, 0x9f, 0x35, 0x41,
-	0xd8, 0x14, 0xc8, 0xca, 0xdd, 0x6d, 0x64, 0x8e, 0x5f, 0xe8, 0x16, 0xb8, 0x9d, 0x3a, 0xe7, 0x69,
-	0x5e, 0xcd, 0xc7, 0x0f, 0x73, 0x5d, 0xfd, 0x0d, 0xbe, 0x32, 0x75, 0x29, 0x5a, 0x6b, 0xce, 0xc9,
-	0xf7, 0xb8, 0x2f, 0x0e, 0xc5, 0xf1, 0xb2, 0x59, 0x66, 0xfb, 0x64, 0x76, 0x23, 0xaa, 0x26, 0x8a,
-	0xe3, 0xfe, 0xec, 0x50, 0x1c, 0xaf, 0xca, 0x1b, 0x58, 0xc3, 0x90, 0xc3, 0x50, 0xd1, 0xdc, 0x6c,
-	0x54, 0x5d, 0x99, 0x87, 0xc0, 0x3d, 0x9c, 0x7c, 0xae, 0xb6, 0xff, 0xee, 0xbf, 0xfd, 0x96, 0xde,
-	0x77, 0x79, 0xdb, 0x5e, 0x2c, 0xe9, 0xe7, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x59, 0x3f, 0x6f,
-	0x4b, 0x19, 0x01, 0x00, 0x00,
+	// 207 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x8e, 0xc1, 0x4a, 0xc4, 0x30,
+	0x10, 0x86, 0xa9, 0x88, 0xac, 0xf1, 0x16, 0x2f, 0x8b, 0x20, 0xac, 0x5e, 0x76, 0x4f, 0x13, 0x58,
+	0xf1, 0x01, 0xda, 0xbe, 0x80, 0x54, 0x4f, 0xde, 0x62, 0x3a, 0xd6, 0x80, 0x99, 0x09, 0xd3, 0x51,
+	0xe8, 0xdb, 0x8b, 0xad, 0x2d, 0xd5, 0x83, 0xb7, 0x40, 0xe6, 0xfb, 0xfe, 0xcf, 0xdc, 0x7f, 0x1e,
+	0xc5, 0x0f, 0x10, 0x38, 0xb9, 0xc0, 0x82, 0x4e, 0xc5, 0x53, 0x9f, 0x59, 0xd4, 0x45, 0x52, 0x14,
+	0x42, 0x75, 0xfe, 0x43, 0xdf, 0x90, 0x34, 0x06, 0xaf, 0x2c, 0x90, 0x85, 0x95, 0xed, 0xf5, 0x8c,
+	0x09, 0xc2, 0x82, 0xc0, 0x8c, 0x5c, 0xed, 0xff, 0x58, 0x03, 0xa7, 0xc4, 0xe4, 0xde, 0xd9, 0xb7,
+	0x28, 0x4e, 0x87, 0x8c, 0x93, 0xe7, 0x96, 0xcc, 0x65, 0xb9, 0xd6, 0xd7, 0x4c, 0xaf, 0xb1, 0xb3,
+	0xd6, 0x9c, 0x92, 0x4f, 0xb8, 0x2d, 0x76, 0xc5, 0xe1, 0xbc, 0x19, 0xdf, 0xb6, 0x36, 0x9b, 0x1e,
+	0x55, 0x23, 0x75, 0xfd, 0xf6, 0x64, 0x57, 0x1c, 0x2e, 0x8e, 0x7b, 0x58, 0x55, 0x4c, 0x13, 0x30,
+	0x4d, 0xc0, 0xd3, 0x90, 0xb1, 0x7d, 0xfc, 0x39, 0x6f, 0x16, 0xb0, 0x2a, 0xcd, 0x4d, 0xe0, 0x04,
+	0xff, 0xd6, 0x57, 0xf6, 0x57, 0xd2, 0xc3, 0x77, 0xe8, 0xf3, 0x66, 0xfe, 0x7d, 0x39, 0x1b, 0xcb,
+	0xef, 0xbe, 0x02, 0x00, 0x00, 0xff, 0xff, 0x86, 0xf6, 0xf6, 0xdf, 0x3a, 0x01, 0x00, 0x00,
 }

+ 2 - 2
transport/internet/authenticator.proto

@@ -5,9 +5,9 @@ option go_package = "internet";
 option java_package = "com.v2ray.core.transport.internet";
 option java_outer_classname = "AuthenticatorProto";
 
-import "google/protobuf/any.proto";
+import "v2ray.com/core/common/loader/type.proto";
 
 message AuthenticatorConfig {
   string name = 1;
-  google.protobuf.Any settings = 2;
+  v2ray.core.common.loader.TypedSettings settings = 2;
 }

+ 0 - 23
transport/internet/authenticator_json.go

@@ -1,23 +0,0 @@
-// +build json
-
-package internet
-
-import (
-	"v2ray.com/core/common/loader"
-)
-
-func CreateAuthenticatorConfig(rawConfig []byte) (string, interface{}, error) {
-	config, name, err := configLoader.Load(rawConfig)
-	if err != nil {
-		return name, nil, err
-	}
-	return name, config, nil
-}
-
-var (
-	configLoader loader.ConfigLoader
-)
-
-func init() {
-	configLoader = loader.NewJSONConfigLoader(configCache, "type", "")
-}

+ 2 - 2
transport/internet/authenticators/noop/noop.go

@@ -2,6 +2,7 @@ package noop
 
 import (
 	"v2ray.com/core/common/alloc"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/transport/internet"
 )
 
@@ -22,6 +23,5 @@ func (this NoOpAuthenticatorFactory) Create(config interface{}) internet.Authent
 }
 
 func init() {
-	internet.RegisterAuthenticator("none", NoOpAuthenticatorFactory{})
-	internet.RegisterAuthenticatorConfig("none", func() interface{} { return &Config{} })
+	internet.RegisterAuthenticator(loader.GetType(new(Config)), NoOpAuthenticatorFactory{})
 }

+ 2 - 2
transport/internet/authenticators/srtp/srtp.go

@@ -4,6 +4,7 @@ import (
 	"math/rand"
 
 	"v2ray.com/core/common/alloc"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/transport/internet"
 )
 
@@ -38,6 +39,5 @@ func (this SRTPFactory) Create(rawSettings interface{}) internet.Authenticator {
 }
 
 func init() {
-	internet.RegisterAuthenticator("srtp", SRTPFactory{})
-	internet.RegisterAuthenticatorConfig("srtp", func() interface{} { return &Config{} })
+	internet.RegisterAuthenticator(loader.GetType(new(Config)), SRTPFactory{})
 }

+ 2 - 2
transport/internet/authenticators/utp/utp.go

@@ -4,6 +4,7 @@ import (
 	"math/rand"
 
 	"v2ray.com/core/common/alloc"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/transport/internet"
 )
 
@@ -38,6 +39,5 @@ func (this UTPFactory) Create(rawSettings interface{}) internet.Authenticator {
 }
 
 func init() {
-	internet.RegisterAuthenticator("utp", UTPFactory{})
-	internet.RegisterAuthenticatorConfig("utp", func() interface{} { return &Config{} })
+	internet.RegisterAuthenticator(loader.GetType(new(Config)), UTPFactory{})
 }

+ 11 - 51
transport/internet/config.go

@@ -3,32 +3,26 @@ package internet
 import (
 	"errors"
 
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
 	v2net "v2ray.com/core/common/net"
-	v2tls "v2ray.com/core/transport/internet/tls"
-
-	"github.com/golang/protobuf/proto"
-	"github.com/golang/protobuf/ptypes"
 )
 
-type NetworkConfigCreator func() proto.Message
-
 var (
-	globalNetworkConfigCreatorCache  = make(map[v2net.Network]NetworkConfigCreator)
-	globalSecurityConfigCreatorCache = make(map[SecurityType]NetworkConfigCreator)
+	globalNetworkConfigCreatorCache = make(map[v2net.Network]loader.ConfigCreator)
 
 	globalNetworkSettings []*NetworkSettings
 
 	ErrUnconfiguredNetwork = errors.New("Network config creator not set.")
 )
 
-func RegisterNetworkConfigCreator(network v2net.Network, creator NetworkConfigCreator) error {
+func RegisterNetworkConfigCreator(network v2net.Network, creator loader.ConfigCreator) error {
 	// TODO: check duplicate
 	globalNetworkConfigCreatorCache[network] = creator
 	return nil
 }
 
-func CreateNetworkConfig(network v2net.Network) (proto.Message, error) {
+func CreateNetworkConfig(network v2net.Network) (interface{}, error) {
 	creator, ok := globalNetworkConfigCreatorCache[network]
 	if !ok {
 		log.Warning("Internet: Network config creator not found: ", network)
@@ -37,40 +31,8 @@ func CreateNetworkConfig(network v2net.Network) (proto.Message, error) {
 	return creator(), nil
 }
 
-func RegisterSecurityConfigCreator(securityType SecurityType, creator NetworkConfigCreator) error {
-	globalSecurityConfigCreatorCache[securityType] = creator
-	return nil
-}
-
-func CreateSecurityConfig(securityType SecurityType) (proto.Message, error) {
-	creator, ok := globalSecurityConfigCreatorCache[securityType]
-	if !ok {
-		log.Warning("Internet: Security config creator not found: ", securityType)
-		return nil, ErrUnconfiguredNetwork
-	}
-	return creator(), nil
-}
-
 func (this *NetworkSettings) GetTypedSettings() (interface{}, error) {
-	message, err := CreateNetworkConfig(this.Network)
-	if err != nil {
-		return nil, err
-	}
-	if err := ptypes.UnmarshalAny(this.Settings, message); err != nil {
-		return nil, err
-	}
-	return message, nil
-}
-
-func (this *SecuritySettings) GetTypeSettings() (interface{}, error) {
-	message, err := CreateSecurityConfig(this.Type)
-	if err != nil {
-		return nil, err
-	}
-	if err := ptypes.UnmarshalAny(this.Settings, message); err != nil {
-		return nil, err
-	}
-	return message, nil
+	return this.Settings.GetInstance()
 }
 
 func (this *StreamConfig) GetEffectiveNetworkSettings() (interface{}, error) {
@@ -90,19 +52,17 @@ func (this *StreamConfig) GetEffectiveNetworkSettings() (interface{}, error) {
 func (this *StreamConfig) GetEffectiveSecuritySettings() (interface{}, error) {
 	for _, settings := range this.SecuritySettings {
 		if settings.Type == this.SecurityType {
-			return settings.GetTypeSettings()
+			return settings.GetInstance()
 		}
 	}
-	return CreateSecurityConfig(this.SecurityType)
+	return loader.GetInstance(this.SecurityType)
+}
+
+func (this *StreamConfig) HasSecuritySettings() bool {
+	return len(this.SecurityType) > 0
 }
 
 func ApplyGlobalNetworkSettings(settings []*NetworkSettings) error {
 	globalNetworkSettings = settings
 	return nil
 }
-
-func init() {
-	RegisterSecurityConfigCreator(SecurityType_TLS, func() proto.Message {
-		return new(v2tls.Config)
-	})
-}

+ 30 - 73
transport/internet/config.pb.go

@@ -8,62 +8,24 @@ import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
 import v2ray_core_common_net "v2ray.com/core/common/net"
-import google_protobuf "github.com/golang/protobuf/ptypes/any"
+import v2ray_core_common_loader "v2ray.com/core/common/loader"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = fmt.Errorf
 var _ = math.Inf
 
-type SecurityType int32
-
-const (
-	SecurityType_None SecurityType = 0
-	SecurityType_TLS  SecurityType = 1
-)
-
-var SecurityType_name = map[int32]string{
-	0: "None",
-	1: "TLS",
-}
-var SecurityType_value = map[string]int32{
-	"None": 0,
-	"TLS":  1,
-}
-
-func (x SecurityType) String() string {
-	return proto.EnumName(SecurityType_name, int32(x))
-}
-func (SecurityType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
-
-type SecuritySettings struct {
-	Type     SecurityType         `protobuf:"varint,1,opt,name=type,enum=v2ray.core.transport.internet.SecurityType" json:"type,omitempty"`
-	Settings *google_protobuf.Any `protobuf:"bytes,2,opt,name=settings" json:"settings,omitempty"`
-}
-
-func (m *SecuritySettings) Reset()                    { *m = SecuritySettings{} }
-func (m *SecuritySettings) String() string            { return proto.CompactTextString(m) }
-func (*SecuritySettings) ProtoMessage()               {}
-func (*SecuritySettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
-
-func (m *SecuritySettings) GetSettings() *google_protobuf.Any {
-	if m != nil {
-		return m.Settings
-	}
-	return nil
-}
-
 type NetworkSettings struct {
-	Network  v2ray_core_common_net.Network `protobuf:"varint,1,opt,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
-	Settings *google_protobuf.Any          `protobuf:"bytes,2,opt,name=settings" json:"settings,omitempty"`
+	Network  v2ray_core_common_net.Network           `protobuf:"varint,1,opt,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
+	Settings *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,2,opt,name=settings" json:"settings,omitempty"`
 }
 
 func (m *NetworkSettings) Reset()                    { *m = NetworkSettings{} }
 func (m *NetworkSettings) String() string            { return proto.CompactTextString(m) }
 func (*NetworkSettings) ProtoMessage()               {}
-func (*NetworkSettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
+func (*NetworkSettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
 
-func (m *NetworkSettings) GetSettings() *google_protobuf.Any {
+func (m *NetworkSettings) GetSettings() *v2ray_core_common_loader.TypedSettings {
 	if m != nil {
 		return m.Settings
 	}
@@ -71,16 +33,16 @@ func (m *NetworkSettings) GetSettings() *google_protobuf.Any {
 }
 
 type StreamConfig struct {
-	Network          v2ray_core_common_net.Network `protobuf:"varint,1,opt,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
-	NetworkSettings  []*NetworkSettings            `protobuf:"bytes,2,rep,name=network_settings,json=networkSettings" json:"network_settings,omitempty"`
-	SecurityType     SecurityType                  `protobuf:"varint,3,opt,name=security_type,json=securityType,enum=v2ray.core.transport.internet.SecurityType" json:"security_type,omitempty"`
-	SecuritySettings []*SecuritySettings           `protobuf:"bytes,4,rep,name=security_settings,json=securitySettings" json:"security_settings,omitempty"`
+	Network          v2ray_core_common_net.Network             `protobuf:"varint,1,opt,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
+	NetworkSettings  []*NetworkSettings                        `protobuf:"bytes,2,rep,name=network_settings,json=networkSettings" json:"network_settings,omitempty"`
+	SecurityType     string                                    `protobuf:"bytes,3,opt,name=security_type,json=securityType" json:"security_type,omitempty"`
+	SecuritySettings []*v2ray_core_common_loader.TypedSettings `protobuf:"bytes,4,rep,name=security_settings,json=securitySettings" json:"security_settings,omitempty"`
 }
 
 func (m *StreamConfig) Reset()                    { *m = StreamConfig{} }
 func (m *StreamConfig) String() string            { return proto.CompactTextString(m) }
 func (*StreamConfig) ProtoMessage()               {}
-func (*StreamConfig) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
+func (*StreamConfig) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
 
 func (m *StreamConfig) GetNetworkSettings() []*NetworkSettings {
 	if m != nil {
@@ -89,7 +51,7 @@ func (m *StreamConfig) GetNetworkSettings() []*NetworkSettings {
 	return nil
 }
 
-func (m *StreamConfig) GetSecuritySettings() []*SecuritySettings {
+func (m *StreamConfig) GetSecuritySettings() []*v2ray_core_common_loader.TypedSettings {
 	if m != nil {
 		return m.SecuritySettings
 	}
@@ -97,36 +59,31 @@ func (m *StreamConfig) GetSecuritySettings() []*SecuritySettings {
 }
 
 func init() {
-	proto.RegisterType((*SecuritySettings)(nil), "v2ray.core.transport.internet.SecuritySettings")
 	proto.RegisterType((*NetworkSettings)(nil), "v2ray.core.transport.internet.NetworkSettings")
 	proto.RegisterType((*StreamConfig)(nil), "v2ray.core.transport.internet.StreamConfig")
-	proto.RegisterEnum("v2ray.core.transport.internet.SecurityType", SecurityType_name, SecurityType_value)
 }
 
 func init() { proto.RegisterFile("v2ray.com/core/transport/internet/config.proto", fileDescriptor1) }
 
 var fileDescriptor1 = []byte{
-	// 347 bytes of a gzipped FileDescriptorProto
+	// 296 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x91, 0x4f, 0x4b, 0xc3, 0x40,
-	0x10, 0xc5, 0x4d, 0x5b, 0x6c, 0x99, 0x56, 0x1b, 0x83, 0x87, 0x5a, 0x50, 0xda, 0x5e, 0x0c, 0x8a,
-	0xbb, 0x12, 0x2f, 0xde, 0x44, 0xbd, 0x4a, 0x91, 0xa4, 0x17, 0x45, 0x28, 0x69, 0x98, 0x86, 0xa0,
-	0xd9, 0x09, 0x9b, 0xad, 0x92, 0x83, 0x47, 0x3f, 0xa1, 0x5f, 0x48, 0x9a, 0x7f, 0x84, 0x1c, 0xea,
-	0xbf, 0xdb, 0x6e, 0xf2, 0xe6, 0xcd, 0x6f, 0xdf, 0x03, 0xf6, 0x6a, 0x49, 0x37, 0x61, 0x1e, 0x85,
-	0xdc, 0x23, 0x89, 0x5c, 0x49, 0x57, 0xc4, 0x11, 0x49, 0xc5, 0x03, 0xa1, 0x50, 0x0a, 0x54, 0xdc,
-	0x23, 0xb1, 0x0c, 0x7c, 0x16, 0x49, 0x52, 0x64, 0x1c, 0x16, 0x7a, 0x89, 0xac, 0xd4, 0xb2, 0x42,
-	0x3b, 0x3c, 0xae, 0xd9, 0x79, 0x14, 0x86, 0x24, 0xf8, 0xda, 0x46, 0xa0, 0x7a, 0x23, 0xf9, 0x9c,
-	0xf9, 0x0c, 0x0f, 0x7c, 0x22, 0xff, 0x05, 0x79, 0x7a, 0x5b, 0xac, 0x96, 0xdc, 0x15, 0x49, 0xf6,
-	0x6b, 0xf2, 0xa1, 0x81, 0xee, 0xa0, 0xb7, 0x92, 0x81, 0x4a, 0x1c, 0x54, 0x2a, 0x10, 0x7e, 0x6c,
-	0x5c, 0x41, 0x4b, 0x25, 0x11, 0x0e, 0xb4, 0x91, 0x66, 0xee, 0x5a, 0xa7, 0x6c, 0x23, 0x06, 0x2b,
-	0xc6, 0x67, 0x49, 0x84, 0x76, 0x3a, 0x68, 0x9c, 0x43, 0x27, 0xce, 0xcd, 0x06, 0x8d, 0x91, 0x66,
-	0x76, 0xad, 0x7d, 0x96, 0x31, 0xb0, 0x82, 0x81, 0x5d, 0x8b, 0xc4, 0x2e, 0x55, 0x93, 0x77, 0xe8,
-	0x4f, 0x33, 0xe6, 0x92, 0xe2, 0x12, 0xda, 0xf9, 0x33, 0x72, 0x90, 0xa3, 0x2a, 0x48, 0xf6, 0x58,
-	0xb6, 0x06, 0xc8, 0x07, 0xed, 0x42, 0xfe, 0x87, 0xf5, 0x9f, 0x0d, 0xe8, 0x39, 0x4a, 0xa2, 0x1b,
-	0xde, 0xa6, 0x05, 0xfc, 0x63, 0xf9, 0x03, 0xe8, 0xf9, 0x71, 0x5e, 0x81, 0x68, 0x9a, 0x5d, 0x8b,
-	0x7d, 0x13, 0x64, 0x2d, 0x00, 0xbb, 0x2f, 0x6a, 0x89, 0xdc, 0xc3, 0x4e, 0x9c, 0x87, 0x3d, 0x4f,
-	0x0b, 0x6a, 0xfe, 0xbe, 0xa0, 0x5e, 0x5c, 0xb9, 0x19, 0x4f, 0xb0, 0x57, 0x3a, 0x96, 0xb4, 0xad,
-	0x94, 0x96, 0xff, 0xd0, 0xb5, 0xc4, 0xd5, 0xe3, 0xda, 0x97, 0x93, 0x31, 0xf4, 0xaa, 0xbb, 0x8d,
-	0x0e, 0xb4, 0xa6, 0x24, 0x50, 0xdf, 0x32, 0xda, 0xd0, 0x9c, 0xdd, 0x39, 0xba, 0x76, 0x73, 0x06,
-	0x63, 0x8f, 0xc2, 0xcd, 0xab, 0x1e, 0x3b, 0xc5, 0x69, 0xb1, 0x9d, 0xf6, 0x77, 0xf1, 0x15, 0x00,
-	0x00, 0xff, 0xff, 0xb2, 0x2e, 0x36, 0x52, 0x4a, 0x03, 0x00, 0x00,
+	0x10, 0xc5, 0x49, 0x2b, 0x5a, 0xb7, 0xd5, 0xd6, 0x9c, 0x82, 0xa0, 0xc4, 0x7a, 0x68, 0x2e, 0xce,
+	0x42, 0xbc, 0x78, 0xb6, 0x77, 0x0f, 0x69, 0x2f, 0x7a, 0x29, 0x71, 0x3b, 0x96, 0xa0, 0xd9, 0x0d,
+	0x93, 0x51, 0xc9, 0xb7, 0xf0, 0x13, 0xf8, 0x59, 0x25, 0x7f, 0x36, 0x94, 0xa0, 0x45, 0xe8, 0x6d,
+	0x18, 0xde, 0xfb, 0xed, 0x9b, 0xb7, 0x02, 0x3e, 0x42, 0x8a, 0x0b, 0x50, 0x26, 0x95, 0xca, 0x10,
+	0x4a, 0xa6, 0x58, 0xe7, 0x99, 0x21, 0x96, 0x89, 0x66, 0x24, 0x8d, 0x2c, 0x95, 0xd1, 0x2f, 0xc9,
+	0x06, 0x32, 0x32, 0x6c, 0xdc, 0x0b, 0xab, 0x27, 0x84, 0x56, 0x0b, 0x56, 0x7b, 0x3e, 0xeb, 0xe0,
+	0x94, 0x49, 0x53, 0xa3, 0x65, 0x89, 0xd1, 0xc8, 0x9f, 0x86, 0x5e, 0x6b, 0xce, 0x5f, 0xc2, 0x37,
+	0x13, 0xaf, 0x91, 0x24, 0x17, 0x19, 0xd6, 0xc2, 0xe9, 0x97, 0x23, 0xc6, 0x0f, 0xb5, 0x75, 0x81,
+	0xcc, 0x89, 0xde, 0xe4, 0xee, 0x9d, 0x38, 0x6a, 0x68, 0x9e, 0xe3, 0x3b, 0xc1, 0x69, 0x78, 0x09,
+	0x5b, 0xb1, 0x6a, 0x14, 0x68, 0x64, 0x68, 0x8c, 0x91, 0x95, 0xbb, 0x73, 0x31, 0xc8, 0x1b, 0x8a,
+	0xd7, 0xf3, 0x9d, 0x60, 0x18, 0xce, 0x7e, 0xb1, 0xd6, 0x29, 0x60, 0x59, 0x64, 0xb8, 0xb6, 0x8f,
+	0x46, 0xad, 0x71, 0xfa, 0xdd, 0x13, 0xa3, 0x05, 0x13, 0xc6, 0xe9, 0xbc, 0xaa, 0x66, 0x8f, 0x3c,
+	0x8f, 0x62, 0xd2, 0x8c, 0xab, 0xad, 0x5c, 0xfd, 0x60, 0x18, 0x02, 0xec, 0x6c, 0x1a, 0x3a, 0x9d,
+	0x44, 0x63, 0xdd, 0x29, 0xe9, 0x5a, 0x9c, 0xe4, 0xa8, 0xde, 0x29, 0xe1, 0x62, 0x55, 0xf6, 0xe9,
+	0xf5, 0x7d, 0x27, 0x38, 0x8e, 0x46, 0x76, 0x59, 0x5e, 0xe7, 0x2e, 0xc5, 0x59, 0x2b, 0x6a, 0x03,
+	0x1c, 0x54, 0x01, 0xfe, 0x5d, 0xcc, 0xc4, 0x12, 0xec, 0xe6, 0xfe, 0x46, 0x5c, 0x29, 0x93, 0xee,
+	0x3e, 0xe0, 0x69, 0x60, 0xa7, 0xe7, 0xc3, 0xea, 0xa7, 0x6f, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff,
+	0xf6, 0x3d, 0x07, 0x73, 0x8c, 0x02, 0x00, 0x00,
 }

+ 4 - 15
transport/internet/config.proto

@@ -5,27 +5,16 @@ option go_package = "internet";
 option java_package = "com.v2ray.core.transport.internet";
 
 import "v2ray.com/core/common/net/network.proto";
-
-import "google/protobuf/any.proto";
-
-enum SecurityType {
-  None = 0;
-  TLS = 1;
-}
-
-message SecuritySettings {
-  SecurityType type = 1;
-  google.protobuf.Any settings = 2;
-}
+import "v2ray.com/core/common/loader/type.proto";
 
 message NetworkSettings {
   v2ray.core.common.net.Network network = 1;
-  google.protobuf.Any settings = 2;
+  v2ray.core.common.loader.TypedSettings settings = 2;
 }
 
 message StreamConfig {
   v2ray.core.common.net.Network network = 1;
   repeated NetworkSettings network_settings = 2;
-  SecurityType security_type = 3;
-  repeated SecuritySettings security_settings = 4;
+  string security_type = 3;
+  repeated v2ray.core.common.loader.TypedSettings security_settings = 4;
 }

+ 5 - 13
transport/internet/connection_json.go

@@ -6,8 +6,7 @@ import (
 	"encoding/json"
 	"strings"
 
-	"errors"
-	"github.com/golang/protobuf/ptypes"
+	"v2ray.com/core/common/loader"
 	v2net "v2ray.com/core/common/net"
 	v2tls "v2ray.com/core/transport/internet/tls"
 )
@@ -26,19 +25,12 @@ func (this *StreamConfig) UnmarshalJSON(data []byte) error {
 	if jsonConfig.Network != nil {
 		this.Network = *jsonConfig.Network
 	}
-	this.SecurityType = SecurityType_None
 	if strings.ToLower(jsonConfig.Security) == "tls" {
-		this.SecurityType = SecurityType_TLS
-	}
-	if jsonConfig.TLSSettings != nil {
-		anyTLSSettings, err := ptypes.MarshalAny(jsonConfig.TLSSettings)
-		if err != nil {
-			return errors.New("Internet: Failed to parse TLS settings: " + err.Error())
+		tlsSettings := jsonConfig.TLSSettings
+		if tlsSettings == nil {
+			tlsSettings = &v2tls.Config{}
 		}
-		this.SecuritySettings = append(this.SecuritySettings, &SecuritySettings{
-			Type:     SecurityType_TLS,
-			Settings: anyTLSSettings,
-		})
+		this.SecuritySettings = append(this.SecuritySettings, loader.NewTypedSettings(tlsSettings))
 	}
 	return nil
 }

+ 7 - 4
transport/internet/kcp/config.go

@@ -3,8 +3,6 @@ package kcp
 import (
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
-
-	"github.com/golang/protobuf/proto"
 )
 
 func (this *MTU) GetValue() uint32 {
@@ -52,7 +50,12 @@ func (this *ReadBuffer) GetSize() uint32 {
 func (this *Config) GetAuthenticator() (internet.Authenticator, error) {
 	auth := NewSimpleAuthenticator()
 	if this.HeaderConfig != nil {
-		header, err := this.HeaderConfig.CreateAuthenticator()
+		rawConfig, err := this.HeaderConfig.GetInstance()
+		if err != nil {
+			return nil, err
+		}
+
+		header, err := internet.CreateAuthenticator(this.HeaderConfig.Type, rawConfig)
 		if err != nil {
 			return nil, err
 		}
@@ -86,7 +89,7 @@ func (this *Config) GetReceivingBufferSize() uint32 {
 }
 
 func init() {
-	internet.RegisterNetworkConfigCreator(v2net.Network_KCP, func() proto.Message {
+	internet.RegisterNetworkConfigCreator(v2net.Network_KCP, func() interface{} {
 		return new(Config)
 	})
 }

+ 38 - 37
transport/internet/kcp/config.pb.go

@@ -22,7 +22,7 @@ package kcp
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
-import v2ray_core_transport_internet "v2ray.com/core/transport/internet"
+import v2ray_core_common_loader "v2ray.com/core/common/loader"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
@@ -96,14 +96,14 @@ func (*ReadBuffer) ProtoMessage()               {}
 func (*ReadBuffer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
 
 type Config struct {
-	Mtu              *MTU                                               `protobuf:"bytes,1,opt,name=mtu" json:"mtu,omitempty"`
-	Tti              *TTI                                               `protobuf:"bytes,2,opt,name=tti" json:"tti,omitempty"`
-	UplinkCapacity   *UplinkCapacity                                    `protobuf:"bytes,3,opt,name=uplink_capacity,json=uplinkCapacity" json:"uplink_capacity,omitempty"`
-	DownlinkCapacity *DownlinkCapacity                                  `protobuf:"bytes,4,opt,name=downlink_capacity,json=downlinkCapacity" json:"downlink_capacity,omitempty"`
-	Congestion       bool                                               `protobuf:"varint,5,opt,name=congestion" json:"congestion,omitempty"`
-	WriteBuffer      *WriteBuffer                                       `protobuf:"bytes,6,opt,name=write_buffer,json=writeBuffer" json:"write_buffer,omitempty"`
-	ReadBuffer       *ReadBuffer                                        `protobuf:"bytes,7,opt,name=read_buffer,json=readBuffer" json:"read_buffer,omitempty"`
-	HeaderConfig     *v2ray_core_transport_internet.AuthenticatorConfig `protobuf:"bytes,8,opt,name=header_config,json=headerConfig" json:"header_config,omitempty"`
+	Mtu              *MTU                                    `protobuf:"bytes,1,opt,name=mtu" json:"mtu,omitempty"`
+	Tti              *TTI                                    `protobuf:"bytes,2,opt,name=tti" json:"tti,omitempty"`
+	UplinkCapacity   *UplinkCapacity                         `protobuf:"bytes,3,opt,name=uplink_capacity,json=uplinkCapacity" json:"uplink_capacity,omitempty"`
+	DownlinkCapacity *DownlinkCapacity                       `protobuf:"bytes,4,opt,name=downlink_capacity,json=downlinkCapacity" json:"downlink_capacity,omitempty"`
+	Congestion       bool                                    `protobuf:"varint,5,opt,name=congestion" json:"congestion,omitempty"`
+	WriteBuffer      *WriteBuffer                            `protobuf:"bytes,6,opt,name=write_buffer,json=writeBuffer" json:"write_buffer,omitempty"`
+	ReadBuffer       *ReadBuffer                             `protobuf:"bytes,7,opt,name=read_buffer,json=readBuffer" json:"read_buffer,omitempty"`
+	HeaderConfig     *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,8,opt,name=header_config,json=headerConfig" json:"header_config,omitempty"`
 }
 
 func (m *Config) Reset()                    { *m = Config{} }
@@ -153,7 +153,7 @@ func (m *Config) GetReadBuffer() *ReadBuffer {
 	return nil
 }
 
-func (m *Config) GetHeaderConfig() *v2ray_core_transport_internet.AuthenticatorConfig {
+func (m *Config) GetHeaderConfig() *v2ray_core_common_loader.TypedSettings {
 	if m != nil {
 		return m.HeaderConfig
 	}
@@ -173,31 +173,32 @@ func init() {
 func init() { proto.RegisterFile("v2ray.com/core/transport/internet/kcp/config.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-	// 411 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x93, 0x51, 0xab, 0xda, 0x30,
-	0x1c, 0xc5, 0x71, 0xf5, 0xba, 0xcb, 0xbf, 0xf7, 0xde, 0xb9, 0xb2, 0x87, 0xb2, 0xc1, 0x50, 0x61,
-	0xe2, 0xcb, 0x52, 0x56, 0x19, 0x6c, 0x8f, 0xd3, 0xbd, 0xf8, 0xe0, 0xd8, 0x42, 0x45, 0xf0, 0xc5,
-	0xc5, 0x34, 0x6a, 0xa8, 0x26, 0x25, 0xa6, 0x8a, 0xfb, 0xa0, 0xfb, 0x3c, 0xa3, 0xa9, 0x9d, 0x55,
-	0xf0, 0xb6, 0x6f, 0x4d, 0x73, 0xce, 0x2f, 0xed, 0x39, 0xf9, 0x83, 0xbf, 0xf7, 0x15, 0x39, 0x22,
-	0x2a, 0xb7, 0x1e, 0x95, 0x8a, 0x79, 0x5a, 0x11, 0xb1, 0x8b, 0xa5, 0xd2, 0x1e, 0x17, 0x9a, 0x29,
-	0xc1, 0xb4, 0x17, 0xd1, 0xd8, 0xa3, 0x52, 0x2c, 0xf9, 0x0a, 0xc5, 0x4a, 0x6a, 0xe9, 0xb4, 0x73,
-	0x8f, 0x62, 0xe8, 0xbf, 0x1e, 0xe5, 0x7a, 0x14, 0xd1, 0xf8, 0xed, 0xe7, 0x72, 0x2c, 0x49, 0xf4,
-	0x9a, 0x09, 0xcd, 0x29, 0xd1, 0x52, 0x65, 0xe4, 0xce, 0x3b, 0xb0, 0xc6, 0xc1, 0xc4, 0x79, 0x03,
-	0x77, 0x7b, 0xb2, 0x49, 0x98, 0x5b, 0x6b, 0xd5, 0x7a, 0x8f, 0x38, 0x5b, 0xa4, 0x9b, 0x41, 0x30,
-	0xba, 0xb1, 0xd9, 0x85, 0xa7, 0x49, 0xbc, 0xe1, 0x22, 0x1a, 0x92, 0x98, 0x50, 0xae, 0x8f, 0x37,
-	0x74, 0x3d, 0x68, 0x7e, 0x97, 0x07, 0x51, 0x41, 0xd9, 0x06, 0x7b, 0xaa, 0xb8, 0x66, 0x83, 0x64,
-	0xb9, 0x64, 0xca, 0x71, 0xa0, 0xbe, 0xe3, 0x7f, 0x72, 0x8d, 0x79, 0xee, 0xb4, 0x00, 0x30, 0x23,
-	0xe1, 0x33, 0x8a, 0xbf, 0x75, 0x68, 0x0c, 0x4d, 0x76, 0xce, 0x17, 0xb0, 0xb6, 0x3a, 0x31, 0xbb,
-	0xb6, 0xdf, 0x45, 0xa5, 0x19, 0xa2, 0x71, 0x30, 0xc1, 0xa9, 0x25, 0x75, 0x6a, 0xcd, 0xdd, 0x17,
-	0x95, 0x9d, 0x41, 0x30, 0xc2, 0xa9, 0xc5, 0x99, 0xc1, 0xab, 0xc4, 0xa4, 0x32, 0xa7, 0xa7, 0x9f,
-	0x75, 0x2d, 0x43, 0xf9, 0x54, 0x81, 0x72, 0x99, 0x27, 0x7e, 0x4a, 0x2e, 0xf3, 0xfd, 0x0d, 0xaf,
-	0xc3, 0x53, 0x92, 0x67, 0x7a, 0xdd, 0xd0, 0xfb, 0x15, 0xe8, 0xd7, 0x2d, 0xe0, 0x66, 0x78, 0xdd,
-	0xcb, 0x7b, 0x00, 0x2a, 0xc5, 0x8a, 0xed, 0x34, 0x97, 0xc2, 0xbd, 0x6b, 0xd5, 0x7a, 0xf7, 0xb8,
-	0xf0, 0xc6, 0xf9, 0x05, 0x0f, 0x87, 0xb4, 0xa1, 0xf9, 0xc2, 0x14, 0xe0, 0x36, 0xcc, 0xe1, 0xa8,
-	0xc2, 0xe1, 0x85, 0x62, 0xb1, 0x7d, 0x28, 0xb4, 0xfc, 0x03, 0x6c, 0xc5, 0x48, 0x98, 0x13, 0x5f,
-	0x1a, 0xe2, 0xc7, 0x0a, 0xc4, 0xf3, 0x3d, 0xc0, 0xa0, 0xce, 0x77, 0x62, 0x0a, 0x8f, 0x6b, 0x46,
-	0x42, 0xa6, 0xe6, 0xd9, 0x04, 0xb9, 0xf7, 0x86, 0xe8, 0x97, 0x10, 0xbf, 0x15, 0x67, 0x23, 0xbb,
-	0x3f, 0xf8, 0x21, 0x03, 0x65, 0xab, 0xc1, 0x57, 0xf8, 0x40, 0xe5, 0xb6, 0xfc, 0xc3, 0x06, 0x76,
-	0x66, 0xf8, 0x99, 0xce, 0xd7, 0xcc, 0x8a, 0x68, 0xbc, 0x68, 0x98, 0x59, 0xeb, 0xff, 0x0b, 0x00,
-	0x00, 0xff, 0xff, 0xe8, 0xba, 0x79, 0x48, 0xfb, 0x03, 0x00, 0x00,
+	// 426 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x93, 0xc1, 0x6f, 0xd3, 0x30,
+	0x18, 0xc5, 0x55, 0xd2, 0x95, 0xe9, 0xcb, 0x36, 0x46, 0xc4, 0x21, 0x02, 0x09, 0x75, 0x93, 0xd8,
+	0x7a, 0xc1, 0x11, 0xdd, 0x05, 0xae, 0x1d, 0x97, 0x49, 0x0c, 0x81, 0x49, 0x85, 0xd4, 0x4b, 0x71,
+	0x1d, 0xb7, 0x58, 0x69, 0x6c, 0xcb, 0x71, 0x5a, 0x85, 0x7f, 0x91, 0x7f, 0x0a, 0xc5, 0x6e, 0x68,
+	0x5a, 0xa9, 0x6b, 0x6e, 0x6d, 0xfc, 0xde, 0xcf, 0xc9, 0x7b, 0xdf, 0x07, 0xc3, 0xd5, 0x50, 0x93,
+	0x12, 0x51, 0x99, 0x45, 0x54, 0x6a, 0x16, 0x19, 0x4d, 0x44, 0xae, 0xa4, 0x36, 0x11, 0x17, 0x86,
+	0x69, 0xc1, 0x4c, 0x94, 0x52, 0x15, 0x51, 0x29, 0xe6, 0x7c, 0x81, 0x94, 0x96, 0x46, 0x06, 0x57,
+	0xb5, 0x47, 0x33, 0xf4, 0x5f, 0x8f, 0x6a, 0x3d, 0x4a, 0xa9, 0x7a, 0x7d, 0xbb, 0x87, 0xa5, 0x32,
+	0xcb, 0xa4, 0x88, 0x96, 0x92, 0x24, 0x4c, 0x47, 0xa6, 0x54, 0xcc, 0xb1, 0xae, 0xdf, 0x80, 0xf7,
+	0x18, 0x8f, 0x83, 0x57, 0x70, 0xb2, 0x22, 0xcb, 0x82, 0x85, 0x9d, 0x7e, 0x67, 0x70, 0x8e, 0xdd,
+	0x9f, 0xea, 0x30, 0x8e, 0x1f, 0x0e, 0x1c, 0xde, 0xc0, 0xc5, 0x58, 0x2d, 0xb9, 0x48, 0xef, 0x89,
+	0x22, 0x94, 0x9b, 0xf2, 0x80, 0x6e, 0x00, 0x97, 0x9f, 0xe5, 0x5a, 0xb4, 0x50, 0x5e, 0x81, 0xff,
+	0x53, 0x73, 0xc3, 0x46, 0xc5, 0x7c, 0xce, 0x74, 0x10, 0x40, 0x37, 0xe7, 0x7f, 0x6a, 0x8d, 0xfd,
+	0x7d, 0xdd, 0x07, 0xc0, 0x8c, 0x24, 0x4f, 0x28, 0xfe, 0x76, 0xa1, 0x77, 0x6f, 0xd3, 0x0a, 0x3e,
+	0x82, 0x97, 0x99, 0xc2, 0x9e, 0xfa, 0xc3, 0x1b, 0x74, 0x34, 0x35, 0xf4, 0x18, 0x8f, 0x71, 0x65,
+	0xa9, 0x9c, 0xc6, 0xf0, 0xf0, 0x59, 0x6b, 0x67, 0x1c, 0x3f, 0xe0, 0xca, 0x12, 0x4c, 0xe0, 0x45,
+	0x61, 0x53, 0x99, 0xd2, 0xcd, 0xc7, 0x86, 0x9e, 0xa5, 0x7c, 0x68, 0x41, 0xd9, 0xcd, 0x13, 0x5f,
+	0x14, 0xbb, 0xf9, 0xfe, 0x82, 0x97, 0xc9, 0x26, 0xc9, 0x2d, 0xbd, 0x6b, 0xe9, 0x77, 0x2d, 0xe8,
+	0xfb, 0x2d, 0xe0, 0xcb, 0x64, 0xbf, 0x97, 0xb7, 0x00, 0x54, 0x8a, 0x05, 0xcb, 0x0d, 0x97, 0x22,
+	0x3c, 0xe9, 0x77, 0x06, 0xa7, 0xb8, 0xf1, 0x24, 0xf8, 0x0e, 0x67, 0xeb, 0xaa, 0xa1, 0xe9, 0xcc,
+	0x16, 0x10, 0xf6, 0xec, 0xe5, 0xa8, 0xc5, 0xe5, 0x8d, 0x62, 0xb1, 0xbf, 0x6e, 0xb4, 0xfc, 0x15,
+	0x7c, 0xcd, 0x48, 0x52, 0x13, 0x9f, 0x5b, 0xe2, 0xfb, 0x16, 0xc4, 0xed, 0x1c, 0x60, 0xd0, 0xdb,
+	0x99, 0xf8, 0x02, 0xe7, 0xbf, 0x59, 0x35, 0xe5, 0x53, 0xb7, 0x33, 0xe1, 0xa9, 0x25, 0xde, 0x36,
+	0x89, 0x6e, 0x1b, 0x90, 0xdb, 0x06, 0x14, 0x97, 0x8a, 0x25, 0x3f, 0x98, 0x31, 0x5c, 0x2c, 0x72,
+	0x7c, 0xe6, 0xdc, 0x6e, 0x84, 0x46, 0x9f, 0xe0, 0x1d, 0x95, 0xd9, 0xf1, 0xb7, 0x19, 0xf9, 0xce,
+	0xf0, 0xad, 0x5a, 0xaa, 0x89, 0x97, 0x52, 0x35, 0xeb, 0xd9, 0x05, 0xbb, 0xfb, 0x17, 0x00, 0x00,
+	0xff, 0xff, 0x02, 0xb7, 0x81, 0x10, 0xe2, 0x03, 0x00, 0x00,
 }

+ 2 - 2
transport/internet/kcp/config.proto

@@ -5,7 +5,7 @@ option go_package = "kcp";
 option java_package = "com.v2ray.core.transport.internet.kcp";
 option java_outer_classname = "ConfigProto";
 
-import "v2ray.com/core/transport/internet/authenticator.proto";
+import "v2ray.com/core/common/loader/type.proto";
 
 // Maximum Transmission Unit, in bytes.
 message MTU {
@@ -45,5 +45,5 @@ message Config {
   bool congestion = 5;
   WriteBuffer write_buffer = 6;
   ReadBuffer read_buffer = 7;
-  v2ray.core.transport.internet.AuthenticatorConfig header_config = 8;
+  v2ray.core.common.loader.TypedSettings header_config = 8;
 }

+ 15 - 8
transport/internet/kcp/config_json.go

@@ -5,9 +5,13 @@ package kcp
 import (
 	"encoding/json"
 
+	"github.com/golang/protobuf/proto"
 	"v2ray.com/core/common"
+	"v2ray.com/core/common/loader"
 	"v2ray.com/core/common/log"
-	"v2ray.com/core/transport/internet"
+	"v2ray.com/core/transport/internet/authenticators/noop"
+	"v2ray.com/core/transport/internet/authenticators/srtp"
+	"v2ray.com/core/transport/internet/authenticators/utp"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -67,18 +71,21 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 		}
 	}
 	if len(jsonConfig.HeaderConfig) > 0 {
-		name, config, err := internet.CreateAuthenticatorConfig(jsonConfig.HeaderConfig)
+		config, _, err := headerLoader.Load(jsonConfig.HeaderConfig)
 		if err != nil {
 			log.Error("KCP|Config: Failed to parse header config: ", err)
 			return err
 		}
-		authConfig, err := internet.NewAuthenticatorConfig(name, config)
-		if err != nil {
-			log.Error("KCP:Config: Failed to create header config: ", err)
-			return err
-		}
-		this.HeaderConfig = authConfig
+		this.HeaderConfig = loader.NewTypedSettings(config.(proto.Message))
 	}
 
 	return nil
 }
+
+var (
+	headerLoader = loader.NewJSONConfigLoader(loader.NamedTypeMap{
+		"none": loader.GetType(new(noop.Config)),
+		"srtp": loader.GetType(new(srtp.Config)),
+		"utp":  loader.GetType(new(utp.Config)),
+	}, "type", "")
+)

+ 10 - 7
transport/internet/kcp/dialer.go

@@ -44,18 +44,21 @@ func DialKCP(src v2net.Address, dest v2net.Destination, options internet.DialerO
 	var iConn internet.Connection
 	iConn = session
 
-	if options.Stream != nil && options.Stream.SecurityType == internet.SecurityType_TLS {
+	if options.Stream != nil && options.Stream.HasSecuritySettings() {
 		securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
 		if err != nil {
-			log.Error("KCP|Dialer: Failed to apply TLS config: ", err)
+			log.Error("KCP|Dialer: Failed to get security settings: ", err)
 			return nil, err
 		}
-		config := securitySettings.(*v2tls.Config).GetTLSConfig()
-		if dest.Address.Family().IsDomain() {
-			config.ServerName = dest.Address.Domain()
+		switch securitySettings := securitySettings.(type) {
+		case *v2tls.Config:
+			config := securitySettings.GetTLSConfig()
+			if dest.Address.Family().IsDomain() {
+				config.ServerName = dest.Address.Domain()
+			}
+			tlsConn := tls.Client(conn, config)
+			iConn = v2tls.NewConnection(tlsConn)
 		}
-		tlsConn := tls.Client(conn, config)
-		iConn = v2tls.NewConnection(tlsConn)
 	}
 
 	return iConn, nil

+ 6 - 3
transport/internet/kcp/listener.go

@@ -47,13 +47,16 @@ func NewListener(address v2net.Address, port v2net.Port, options internet.Listen
 		running:       true,
 		config:        kcpSettings,
 	}
-	if options.Stream != nil && options.Stream.SecurityType == internet.SecurityType_TLS {
+	if options.Stream != nil && options.Stream.HasSecuritySettings() {
 		securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
 		if err != nil {
-			log.Error("KCP|Listener: Failed to apply TLS config: ", err)
+			log.Error("KCP|Listener: Failed to get security settings: ", err)
 			return nil, err
 		}
-		l.tlsConfig = securitySettings.(*v2tls.Config).GetTLSConfig()
+		switch securitySettings := securitySettings.(type) {
+		case *v2tls.Config:
+			l.tlsConfig = securitySettings.GetTLSConfig()
+		}
 	}
 	hub, err := udp.ListenUDP(address, port, udp.ListenOption{Callback: l.OnReceive})
 	if err != nil {

+ 1 - 3
transport/internet/tcp/config.go

@@ -3,12 +3,10 @@ package tcp
 import (
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
-
-	"github.com/golang/protobuf/proto"
 )
 
 func init() {
-	internet.RegisterNetworkConfigCreator(v2net.Network_TCP, func() proto.Message {
+	internet.RegisterNetworkConfigCreator(v2net.Network_TCP, func() interface{} {
 		return new(Config)
 	})
 }

+ 9 - 6
transport/internet/tcp/dialer.go

@@ -37,17 +37,20 @@ func Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOpti
 			return nil, err
 		}
 	}
-	if options.Stream != nil && options.Stream.SecurityType == internet.SecurityType_TLS {
+	if options.Stream != nil && options.Stream.HasSecuritySettings() {
 		securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
 		if err != nil {
-			log.Error("TCP: Failed to apply TLS config: ", err)
+			log.Error("TCP: Failed to get security settings: ", err)
 			return nil, err
 		}
-		config := securitySettings.(*v2tls.Config).GetTLSConfig()
-		if dest.Address.Family().IsDomain() {
-			config.ServerName = dest.Address.Domain()
+		tlsConfig, ok := securitySettings.(*v2tls.Config)
+		if ok {
+			config := tlsConfig.GetTLSConfig()
+			if dest.Address.Family().IsDomain() {
+				config.ServerName = dest.Address.Domain()
+			}
+			conn = tls.Client(conn, config)
 		}
-		conn = tls.Client(conn, config)
 	}
 	return NewConnection(id, conn, globalCache, tcpSettings), nil
 }

+ 6 - 3
transport/internet/tcp/hub.go

@@ -51,13 +51,16 @@ func ListenTCP(address v2net.Address, port v2net.Port, options internet.ListenOp
 		awaitingConns: make(chan *ConnectionWithError, 32),
 		config:        tcpSettings,
 	}
-	if options.Stream != nil && options.Stream.SecurityType == internet.SecurityType_TLS {
+	if options.Stream != nil && options.Stream.HasSecuritySettings() {
 		securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
 		if err != nil {
-			log.Error("TCP: Failed to apply TLS config: ", err)
+			log.Error("TCP: Failed to get security config: ", err)
 			return nil, err
 		}
-		l.tlsConfig = securitySettings.(*v2tls.Config).GetTLSConfig()
+		tlsConfig, ok := securitySettings.(*v2tls.Config)
+		if ok {
+			l.tlsConfig = tlsConfig.GetTLSConfig()
+		}
 	}
 	go l.KeepAccepting()
 	return l, nil

+ 1 - 3
transport/internet/ws/config.go

@@ -3,12 +3,10 @@ package ws
 import (
 	v2net "v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
-
-	"github.com/golang/protobuf/proto"
 )
 
 func init() {
-	internet.RegisterNetworkConfigCreator(v2net.Network_WebSocket, func() proto.Message {
+	internet.RegisterNetworkConfigCreator(v2net.Network_WebSocket, func() interface{} {
 		return new(Config)
 	})
 }

+ 8 - 5
transport/internet/ws/dialer.go

@@ -69,16 +69,19 @@ func wsDial(src v2net.Address, dest v2net.Destination, options internet.DialerOp
 
 	protocol := "ws"
 
-	if options.Stream != nil && options.Stream.SecurityType == internet.SecurityType_TLS {
+	if options.Stream != nil && options.Stream.HasSecuritySettings() {
 		protocol = "wss"
 		securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
 		if err != nil {
-			log.Error("WebSocket: Failed to create apply TLS config: ", err)
+			log.Error("WebSocket: Failed to create security settings: ", err)
 			return nil, err
 		}
-		dialer.TLSClientConfig = securitySettings.(*v2tls.Config).GetTLSConfig()
-		if dest.Address.Family().IsDomain() {
-			dialer.TLSClientConfig.ServerName = dest.Address.Domain()
+		tlsConfig, ok := securitySettings.(*v2tls.Config)
+		if ok {
+			dialer.TLSClientConfig = tlsConfig.GetTLSConfig()
+			if dest.Address.Family().IsDomain() {
+				dialer.TLSClientConfig.ServerName = dest.Address.Domain()
+			}
 		}
 	}
 

+ 5 - 2
transport/internet/ws/hub.go

@@ -46,13 +46,16 @@ func ListenWS(address v2net.Address, port v2net.Port, options internet.ListenOpt
 		awaitingConns: make(chan *ConnectionWithError, 32),
 		config:        wsSettings,
 	}
-	if options.Stream != nil && options.Stream.SecurityType == internet.SecurityType_TLS {
+	if options.Stream != nil && options.Stream.HasSecuritySettings() {
 		securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
 		if err != nil {
 			log.Error("WebSocket: Failed to create apply TLS config: ", err)
 			return nil, err
 		}
-		l.tlsConfig = securitySettings.(*v2tls.Config).GetTLSConfig()
+		tlsConfig, ok := securitySettings.(*v2tls.Config)
+		if ok {
+			l.tlsConfig = tlsConfig.GetTLSConfig()
+		}
 	}
 
 	err = l.listenws(address, port)

+ 1 - 1
v2ray.go

@@ -97,7 +97,7 @@ func NewPoint(pConfig *Config) (*Point, error) {
 			return nil, err
 		}
 		outboundHandler, err := proxyregistry.CreateOutboundHandler(
-			outbound.Protocol, vpoint.space, outboundSettings, &proxy.OutboundHandlerMeta{
+			outbound.Settings.Type, vpoint.space, outboundSettings, &proxy.OutboundHandlerMeta{
 				Tag:            outbound.Tag,
 				Address:        outbound.SendThrough.AsAddress(),
 				StreamSettings: outbound.StreamSettings,