v2ray пре 9 година
родитељ
комит
e732ba62a6

+ 61 - 0
common/loader/json_conf.go

@@ -0,0 +1,61 @@
+// +build json
+
+package loader
+
+import (
+	"encoding/json"
+
+	"github.com/v2ray/v2ray-core/common/log"
+)
+
+type JSONConfigLoader struct {
+	*BaseConfigLoader
+	idKey     string
+	configKey string
+}
+
+func NewJSONConfigLoader(idKey string, configKey string) *JSONConfigLoader {
+	return &JSONConfigLoader{
+		idKey:            idKey,
+		configKey:        configKey,
+		BaseConfigLoader: NewBaseConfigLoader(),
+	}
+}
+
+func (this *JSONConfigLoader) LoadWithID(raw []byte, id string) (interface{}, error) {
+	config, err := this.CreateConfig(id)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := json.Unmarshal(raw, config); err != nil {
+		return nil, err
+	}
+	return config, nil
+}
+
+func (this *JSONConfigLoader) Load(raw []byte) (interface{}, error) {
+	obj := make(map[string]json.RawMessage)
+	if err := json.Unmarshal(raw, obj); err != nil {
+		return nil, err
+	}
+	rawID, found := obj[this.idKey]
+	if !found {
+		log.Error(this.idKey, " not found in JSON content.")
+		return nil, ErrConfigIDKeyNotFound
+	}
+	var id string
+	if err := json.Unmarshal(rawID, id); err != nil {
+		return nil, err
+	}
+	rawConfig := json.RawMessage(raw)
+	if len(this.configKey) > 0 {
+		configValue, found := obj[this.configKey]
+		if !found {
+			log.Error(this.configKey, " not found in JSON content.")
+			return nil, ErrConfigIDKeyNotFound
+		}
+		rawConfig = configValue
+	}
+	return this.LoadWithID([]byte(rawConfig), id)
+}

+ 47 - 0
common/loader/loader.go

@@ -0,0 +1,47 @@
+package loader
+
+import (
+	"errors"
+)
+
+var (
+	ErrConfigIDKeyNotFound = errors.New("Config ID key is not found.")
+	ErrConfigIDExists      = errors.New("Config ID already exists.")
+	ErrUnknownConfigID     = errors.New("Unknown config ID.")
+)
+
+type ConfigCreator func() interface{}
+
+type ConfigLoader interface {
+	RegisterCreator(string, ConfigCreator) error
+	CreateConfig(string) (interface{}, error)
+	Load([]byte) (interface{}, error)
+	LoadWithID([]byte, string) (interface{}, error)
+}
+
+type BaseConfigLoader struct {
+	creators map[string]ConfigCreator
+}
+
+func NewBaseConfigLoader() *BaseConfigLoader {
+	return &BaseConfigLoader{
+		creators: make(map[string]ConfigCreator),
+	}
+}
+
+func (this *BaseConfigLoader) RegisterCreator(id string, creator ConfigCreator) error {
+	if _, found := this.creators[id]; found {
+		return ErrConfigIDExists
+	}
+
+	this.creators[id] = creator
+	return nil
+}
+
+func (this *BaseConfigLoader) CreateConfig(id string) (interface{}, error) {
+	creator, found := this.creators[id]
+	if !found {
+		return nil, ErrUnknownConfigID
+	}
+	return creator(), nil
+}

+ 5 - 4
proxy/blackhole/blackhole.go

@@ -11,22 +11,23 @@ import (
 
 // BlackHole is an outbound connection that sliently swallow the entire payload.
 type BlackHole struct {
-	meta *proxy.OutboundHandlerMeta
+	meta     *proxy.OutboundHandlerMeta
+	response Response
 }
 
 func NewBlackHole(space app.Space, config *Config, meta *proxy.OutboundHandlerMeta) *BlackHole {
 	return &BlackHole{
-		meta: meta,
+		meta:     meta,
+		response: config.Response,
 	}
 }
 
 func (this *BlackHole) Dispatch(destination v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error {
 	payload.Release()
 
+	this.response.WriteTo(ray.OutboundOutput())
 	ray.OutboundOutput().Close()
-	ray.OutboundOutput().Release()
 
-	ray.OutboundInput().Close()
 	ray.OutboundInput().Release()
 
 	return nil

+ 30 - 0
proxy/blackhole/config.go

@@ -1,4 +1,34 @@
 package blackhole
 
+import (
+	"github.com/v2ray/v2ray-core/common/alloc"
+	v2io "github.com/v2ray/v2ray-core/common/io"
+)
+
 type Config struct {
+	Response Response
+}
+
+type Response interface {
+	WriteTo(v2io.Writer)
+}
+
+type NoneResponse struct{}
+
+func (this *NoneResponse) WriteTo(writer v2io.Writer) {}
+
+type HTTPResponse struct {
+}
+
+const (
+	http403response = `HTTP/1.1 403 Forbidden
+Connection: close
+Cache-Control: max-age=3600, public
+Content-Length: 0
+ 
+`
+)
+
+func (this *HTTPResponse) WriteTo(writer v2io.Writer) {
+	writer.Write(alloc.NewSmallBuffer().Clear().AppendString(http403response))
 }

+ 6 - 5
proxy/blackhole/config_json.go

@@ -3,12 +3,13 @@
 package blackhole
 
 import (
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
+	"github.com/v2ray/v2ray-core/proxy/internal"
 )
 
+func (this *Config) UnmarshalJSON(data []byte) error {
+	return nil
+}
+
 func init() {
-	config.RegisterOutboundConfig("blackhole",
-		func(data []byte) (interface{}, error) {
-			return new(Config), nil
-		})
+	internal.RegisterOutboundConfig("blackhole", func() interface{} { return new(Config) })
 }

+ 20 - 20
proxy/dokodemo/config_json.go

@@ -6,27 +6,27 @@ import (
 	"encoding/json"
 
 	v2net "github.com/v2ray/v2ray-core/common/net"
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
+	"github.com/v2ray/v2ray-core/proxy/internal"
 )
 
+func (this *Config) UnmarshalJSON(data []byte) error {
+	type DokodemoConfig struct {
+		Host         *v2net.AddressJson `json:"address"`
+		PortValue    v2net.Port         `json:"port"`
+		NetworkList  *v2net.NetworkList `json:"network"`
+		TimeoutValue int                `json:"timeout"`
+	}
+	rawConfig := new(DokodemoConfig)
+	if err := json.Unmarshal(data, rawConfig); err != nil {
+		return err
+	}
+	this.Address = rawConfig.Host.Address
+	this.Port = rawConfig.PortValue
+	this.Network = rawConfig.NetworkList
+	this.Timeout = rawConfig.TimeoutValue
+	return nil
+}
+
 func init() {
-	config.RegisterInboundConfig("dokodemo-door",
-		func(data []byte) (interface{}, error) {
-			type DokodemoConfig struct {
-				Host         *v2net.AddressJson `json:"address"`
-				PortValue    v2net.Port         `json:"port"`
-				NetworkList  *v2net.NetworkList `json:"network"`
-				TimeoutValue int                `json:"timeout"`
-			}
-			rawConfig := new(DokodemoConfig)
-			if err := json.Unmarshal(data, rawConfig); err != nil {
-				return nil, err
-			}
-			return &Config{
-				Address: rawConfig.Host.Address,
-				Port:    rawConfig.PortValue,
-				Network: rawConfig.NetworkList,
-				Timeout: rawConfig.TimeoutValue,
-			}, nil
-		})
+	internal.RegisterInboundConfig("dokodemo-door", func() interface{} { return new(Config) })
 }

+ 2 - 9
proxy/freedom/config_json.go

@@ -6,7 +6,7 @@ import (
 	"encoding/json"
 	"strings"
 
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
+	"github.com/v2ray/v2ray-core/proxy/internal"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -28,12 +28,5 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 }
 
 func init() {
-	config.RegisterOutboundConfig("freedom",
-		func(data []byte) (interface{}, error) {
-			c := new(Config)
-			if err := json.Unmarshal(data, c); err != nil {
-				return nil, err
-			}
-			return c, nil
-		})
+	internal.RegisterOutboundConfig("freedom", func() interface{} { return new(Config) })
 }

+ 2 - 7
proxy/http/config_json.go

@@ -6,7 +6,7 @@ import (
 	"crypto/tls"
 	"encoding/json"
 
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
+	"github.com/v2ray/v2ray-core/proxy/internal"
 )
 
 // UnmarshalJSON implements json.Unmarshaler
@@ -62,10 +62,5 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 }
 
 func init() {
-	config.RegisterInboundConfig("http",
-		func(data []byte) (interface{}, error) {
-			rawConfig := new(Config)
-			err := json.Unmarshal(data, rawConfig)
-			return rawConfig, err
-		})
+	internal.RegisterInboundConfig("http", func() interface{} { return new(Config) })
 }

+ 0 - 53
proxy/internal/config/config_cache.go

@@ -1,53 +0,0 @@
-package config
-
-import (
-	"errors"
-)
-
-type ConfigObjectCreator func(data []byte) (interface{}, error)
-
-var (
-	configCache map[string]ConfigObjectCreator
-)
-
-func getConfigKey(protocol string, proxyType string) string {
-	return protocol + "_" + proxyType
-}
-
-func registerConfigType(protocol string, proxyType string, creator ConfigObjectCreator) error {
-	// TODO: check name
-	configCache[getConfigKey(protocol, proxyType)] = creator
-	return nil
-}
-
-func RegisterInboundConfig(protocol string, creator ConfigObjectCreator) error {
-	return registerConfigType(protocol, "inbound", creator)
-}
-
-func RegisterOutboundConfig(protocol string, creator ConfigObjectCreator) error {
-	return registerConfigType(protocol, "outbound", creator)
-}
-
-func CreateInboundConfig(protocol string, data []byte) (interface{}, error) {
-	creator, found := configCache[getConfigKey(protocol, "inbound")]
-	if !found {
-		return nil, errors.New(protocol + " not found.")
-	}
-	return creator(data)
-}
-
-func CreateOutboundConfig(protocol string, data []byte) (interface{}, error) {
-	creator, found := configCache[getConfigKey(protocol, "outbound")]
-	if !found {
-		return nil, errors.New(protocol + " not found.")
-	}
-	return creator(data)
-}
-
-func initializeConfigCache() {
-	configCache = make(map[string]ConfigObjectCreator)
-}
-
-func init() {
-	initializeConfigCache()
-}

+ 0 - 49
proxy/internal/config/config_cache_test.go

@@ -1,49 +0,0 @@
-package config
-
-import (
-	"testing"
-
-	"github.com/v2ray/v2ray-core/testing/assert"
-)
-
-func TestRegisterInboundConfig(t *testing.T) {
-	assert := assert.On(t)
-	initializeConfigCache()
-
-	protocol := "test_protocol"
-	creator := func([]byte) (interface{}, error) {
-		return true, nil
-	}
-
-	err := RegisterInboundConfig(protocol, creator)
-	assert.Error(err).IsNil()
-
-	configObj, err := CreateInboundConfig(protocol, nil)
-	assert.Bool(configObj.(bool)).IsTrue()
-	assert.Error(err).IsNil()
-
-	configObj, err = CreateOutboundConfig(protocol, nil)
-	assert.Error(err).IsNotNil()
-	assert.Pointer(configObj).IsNil()
-}
-
-func TestRegisterOutboundConfig(t *testing.T) {
-	assert := assert.On(t)
-	initializeConfigCache()
-
-	protocol := "test_protocol"
-	creator := func([]byte) (interface{}, error) {
-		return true, nil
-	}
-
-	err := RegisterOutboundConfig(protocol, creator)
-	assert.Error(err).IsNil()
-
-	configObj, err := CreateOutboundConfig(protocol, nil)
-	assert.Bool(configObj.(bool)).IsTrue()
-	assert.Error(err).IsNil()
-
-	configObj, err = CreateInboundConfig(protocol, nil)
-	assert.Error(err).IsNotNil()
-	assert.Pointer(configObj).IsNil()
-}

+ 24 - 0
proxy/internal/config_cache.go

@@ -0,0 +1,24 @@
+package internal
+
+import "github.com/v2ray/v2ray-core/common/loader"
+
+var (
+	inboundConfigCache  loader.ConfigLoader
+	outboundConfigCache loader.ConfigLoader
+)
+
+func RegisterInboundConfig(protocol string, creator loader.ConfigCreator) error {
+	return inboundConfigCache.RegisterCreator(protocol, creator)
+}
+
+func RegisterOutboundConfig(protocol string, creator loader.ConfigCreator) error {
+	return outboundConfigCache.RegisterCreator(protocol, creator)
+}
+
+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)
+}

+ 12 - 0
proxy/internal/config_cache_json.go

@@ -0,0 +1,12 @@
+// +build json
+
+package internal
+
+import (
+	"github.com/v2ray/v2ray-core/common/loader"
+)
+
+func init() {
+	inboundConfigCache = loader.NewJSONConfigLoader("protocol", "settings")
+	outboundConfigCache = loader.NewJSONConfigLoader("protocol", "settings")
+}

+ 2 - 3
proxy/internal/handler_cache.go

@@ -5,7 +5,6 @@ import (
 
 	"github.com/v2ray/v2ray-core/app"
 	"github.com/v2ray/v2ray-core/proxy"
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
 )
 
 var (
@@ -51,7 +50,7 @@ func CreateInboundHandler(name string, space app.Space, rawConfig []byte, meta *
 		return nil, ErrorProxyNotFound
 	}
 	if len(rawConfig) > 0 {
-		proxyConfig, err := config.CreateInboundConfig(name, rawConfig)
+		proxyConfig, err := CreateInboundConfig(name, rawConfig)
 		if err != nil {
 			return nil, err
 		}
@@ -67,7 +66,7 @@ func CreateOutboundHandler(name string, space app.Space, rawConfig []byte, meta
 	}
 
 	if len(rawConfig) > 0 {
-		proxyConfig, err := config.CreateOutboundConfig(name, rawConfig)
+		proxyConfig, err := CreateOutboundConfig(name, rawConfig)
 		if err != nil {
 			return nil, err
 		}

+ 1 - 6
proxy/shadowsocks/config_json.go

@@ -9,7 +9,6 @@ import (
 	"github.com/v2ray/v2ray-core/common/log"
 	"github.com/v2ray/v2ray-core/common/protocol"
 	"github.com/v2ray/v2ray-core/proxy/internal"
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -62,9 +61,5 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 }
 
 func init() {
-	config.RegisterInboundConfig("shadowsocks", func(data []byte) (interface{}, error) {
-		rawConfig := new(Config)
-		err := json.Unmarshal(data, rawConfig)
-		return rawConfig, err
-	})
+	internal.RegisterInboundConfig("shadowsocks", func() interface{} { return new(Config) })
 }

+ 43 - 44
proxy/socks/config_json.go

@@ -8,7 +8,6 @@ import (
 	"github.com/v2ray/v2ray-core/common/log"
 	v2net "github.com/v2ray/v2ray-core/common/net"
 	"github.com/v2ray/v2ray-core/proxy/internal"
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
 )
 
 const (
@@ -16,48 +15,48 @@ const (
 	AuthMethodUserPass = "password"
 )
 
+func (this *Config) UnmarshalJSON(data []byte) error {
+	type SocksAccount struct {
+		Username string `json:"user"`
+		Password string `json:"pass"`
+	}
+
+	type SocksConfig struct {
+		AuthMethod string             `json:"auth"`
+		Accounts   []*SocksAccount    `json:"accounts"`
+		UDP        bool               `json:"udp"`
+		Host       *v2net.AddressJson `json:"ip"`
+	}
+
+	rawConfig := new(SocksConfig)
+	if err := json.Unmarshal(data, rawConfig); err != nil {
+		return err
+	}
+	if rawConfig.AuthMethod == AuthMethodNoAuth {
+		this.AuthType = AuthTypeNoAuth
+	} else if rawConfig.AuthMethod == AuthMethodUserPass {
+		this.AuthType = AuthTypePassword
+	} else {
+		log.Error("Socks: Unknown auth method: ", rawConfig.AuthMethod)
+		return internal.ErrorBadConfiguration
+	}
+
+	if len(rawConfig.Accounts) > 0 {
+		this.Accounts = make(map[string]string, len(rawConfig.Accounts))
+		for _, account := range rawConfig.Accounts {
+			this.Accounts[account.Username] = account.Password
+		}
+	}
+
+	this.UDPEnabled = rawConfig.UDP
+	if rawConfig.Host != nil {
+		this.Address = rawConfig.Host.Address
+	} else {
+		this.Address = v2net.LocalHostIP
+	}
+	return nil
+}
+
 func init() {
-	config.RegisterInboundConfig("socks",
-		func(data []byte) (interface{}, error) {
-			type SocksAccount struct {
-				Username string `json:"user"`
-				Password string `json:"pass"`
-			}
-
-			type SocksConfig struct {
-				AuthMethod string             `json:"auth"`
-				Accounts   []*SocksAccount    `json:"accounts"`
-				UDP        bool               `json:"udp"`
-				Host       *v2net.AddressJson `json:"ip"`
-			}
-
-			rawConfig := new(SocksConfig)
-			if err := json.Unmarshal(data, rawConfig); err != nil {
-				return nil, err
-			}
-			socksConfig := new(Config)
-			if rawConfig.AuthMethod == AuthMethodNoAuth {
-				socksConfig.AuthType = AuthTypeNoAuth
-			} else if rawConfig.AuthMethod == AuthMethodUserPass {
-				socksConfig.AuthType = AuthTypePassword
-			} else {
-				log.Error("Socks: Unknown auth method: ", rawConfig.AuthMethod)
-				return nil, internal.ErrorBadConfiguration
-			}
-
-			if len(rawConfig.Accounts) > 0 {
-				socksConfig.Accounts = make(map[string]string, len(rawConfig.Accounts))
-				for _, account := range rawConfig.Accounts {
-					socksConfig.Accounts[account.Username] = account.Password
-				}
-			}
-
-			socksConfig.UDPEnabled = rawConfig.UDP
-			if rawConfig.Host != nil {
-				socksConfig.Address = rawConfig.Host.Address
-			} else {
-				socksConfig.Address = v2net.LocalHostIP
-			}
-			return socksConfig, nil
-		})
+	internal.RegisterInboundConfig("socks", func() interface{} { return new(Config) })
 }

+ 2 - 2
proxy/socks/config_json_test.go

@@ -5,7 +5,7 @@ package socks_test
 import (
 	"testing"
 
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
+	"github.com/v2ray/v2ray-core/proxy/internal"
 	"github.com/v2ray/v2ray-core/proxy/socks"
 	"github.com/v2ray/v2ray-core/testing/assert"
 )
@@ -13,7 +13,7 @@ import (
 func TestDefaultIPAddress(t *testing.T) {
 	assert := assert.On(t)
 
-	socksConfig, err := config.CreateInboundConfig("socks", []byte(`{
+	socksConfig, err := internal.CreateInboundConfig("socks", []byte(`{
     "auth": "noauth"
   }`))
 	assert.Error(err).IsNil()

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

@@ -6,7 +6,7 @@ import (
 	"encoding/json"
 
 	"github.com/v2ray/v2ray-core/common/protocol"
-	"github.com/v2ray/v2ray-core/proxy/internal/config"
+	"github.com/v2ray/v2ray-core/proxy/internal"
 )
 
 func (this *DetourConfig) UnmarshalJSON(data []byte) error {
@@ -79,10 +79,5 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 }
 
 func init() {
-	config.RegisterInboundConfig("vmess",
-		func(data []byte) (interface{}, error) {
-			config := new(Config)
-			err := json.Unmarshal(data, config)
-			return config, err
-		})
+	internal.RegisterInboundConfig("vmess", func() interface{} { return new(Config) })
 }

+ 1 - 9
proxy/vmess/outbound/config_json.go

@@ -7,7 +7,6 @@ import (
 
 	"github.com/v2ray/v2ray-core/common/log"
 	"github.com/v2ray/v2ray-core/proxy/internal"
-	proxyconfig "github.com/v2ray/v2ray-core/proxy/internal/config"
 )
 
 func (this *Config) UnmarshalJSON(data []byte) error {
@@ -28,12 +27,5 @@ func (this *Config) UnmarshalJSON(data []byte) error {
 }
 
 func init() {
-	proxyconfig.RegisterOutboundConfig("vmess",
-		func(data []byte) (interface{}, error) {
-			rawConfig := new(Config)
-			if err := json.Unmarshal(data, rawConfig); err != nil {
-				return nil, err
-			}
-			return rawConfig, nil
-		})
+	internal.RegisterOutboundConfig("vmess", func() interface{} { return new(Config) })
 }