1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-05 01:36:34 -05:00

unified config loader

This commit is contained in:
v2ray 2016-06-10 22:26:39 +02:00
parent 3f7b70a465
commit e732ba62a6
18 changed files with 259 additions and 217 deletions

View File

@ -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
common/loader/loader.go Normal file
View File

@ -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
}

View File

@ -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

View File

@ -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))
}

View File

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

View File

@ -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 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
})
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() {
internal.RegisterInboundConfig("dokodemo-door", func() interface{} { return new(Config) })
}

View File

@ -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) })
}

View File

@ -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) })
}

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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")
}

View File

@ -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
}

View File

@ -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) })
}

View File

@ -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 init() {
config.RegisterInboundConfig("socks",
func(data []byte) (interface{}, error) {
type SocksAccount struct {
Username string `json:"user"`
Password string `json:"pass"`
}
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"`
}
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
}
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 {
socksConfig.Accounts = make(map[string]string, len(rawConfig.Accounts))
for _, account := range rawConfig.Accounts {
socksConfig.Accounts[account.Username] = account.Password
}
}
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
}
}
socksConfig.UDPEnabled = rawConfig.UDP
if rawConfig.Host != nil {
socksConfig.Address = rawConfig.Host.Address
} else {
socksConfig.Address = v2net.LocalHostIP
}
return socksConfig, nil
})
this.UDPEnabled = rawConfig.UDP
if rawConfig.Host != nil {
this.Address = rawConfig.Host.Address
} else {
this.Address = v2net.LocalHostIP
}
return nil
}
func init() {
internal.RegisterInboundConfig("socks", func() interface{} { return new(Config) })
}

View File

@ -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()

View File

@ -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) })
}

View File

@ -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) })
}