json config parser

pull/314/head
Darien Raymond 2016-10-17 14:35:13 +02:00
parent e866ff24a4
commit 5a311cbe08
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
85 changed files with 9358 additions and 9053 deletions

View File

@ -1,34 +0,0 @@
// +build json
package dns
import (
"encoding/json"
v2net "v2ray.com/core/common/net"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Servers []*v2net.IPOrDomain `json:"servers"`
Hosts map[string]*v2net.IPOrDomain `json:"hosts"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
this.NameServers = make([]*v2net.Endpoint, len(jsonConfig.Servers))
for idx, server := range jsonConfig.Servers {
this.NameServers[idx] = &v2net.Endpoint{
Network: v2net.Network_UDP,
Address: server,
Port: 53,
}
}
if jsonConfig.Hosts != nil {
this.Hosts = jsonConfig.Hosts
}
return nil
}

View File

@ -1,3 +0,0 @@
package router
//go:generate go run chinaip_gen.go

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
// +build json
package router
import (
"encoding/json"
"v2ray.com/core/common/log"
)
func parseChinaIPRule(data []byte) (*RoutingRule, error) {
rawRule := new(JsonRule)
err := json.Unmarshal(data, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
return nil, err
}
return &RoutingRule{
Tag: rawRule.OutboundTag,
Ip: chinaIPs,
}, nil
}

View File

@ -1,34 +0,0 @@
// +build json
package router_test
import (
"net"
"testing"
. "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
)
func makeDestination(ip string) v2net.Destination {
return v2net.TCPDestination(v2net.IPAddress(net.ParseIP(ip)), 80)
}
func TestChinaIPJson(t *testing.T) {
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "chinaip",
"outboundTag": "x"
}`))
assert.String(rule.Tag).Equals("x")
cond, err := rule.BuildCondition()
assert.Error(err).IsNil()
assert.Bool(cond.Apply(makeDestination("121.14.1.189"))).IsTrue() // sina.com.cn
assert.Bool(cond.Apply(makeDestination("101.226.103.106"))).IsTrue() // qq.com
assert.Bool(cond.Apply(makeDestination("115.239.210.36"))).IsTrue() // image.baidu.com
assert.Bool(cond.Apply(makeDestination("120.135.126.1"))).IsTrue()
assert.Bool(cond.Apply(makeDestination("8.8.8.8"))).IsFalse()
}

View File

@ -1,21 +0,0 @@
// +build json
package router
import (
"encoding/json"
"v2ray.com/core/common/log"
)
func parseChinaSitesRule(data []byte) (*RoutingRule, error) {
rawRule := new(JsonRule)
err := json.Unmarshal(data, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
return nil, err
}
return &RoutingRule{
Tag: rawRule.OutboundTag,
Domain: chinaSitesDomains,
}, nil
}

View File

@ -1,33 +0,0 @@
// +build json
package router_test
import (
"testing"
. "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
)
func makeDomainDestination(domain string) v2net.Destination {
return v2net.TCPDestination(v2net.DomainAddress(domain), 80)
}
func TestChinaSitesJson(t *testing.T) {
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "chinasites",
"outboundTag": "y"
}`))
assert.String(rule.Tag).Equals("y")
cond, err := rule.BuildCondition()
assert.Error(err).IsNil()
assert.Bool(cond.Apply(makeDomainDestination("v.qq.com"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("www.163.com"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("ngacn.cc"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("12306.cn"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("v2ray.com"))).IsFalse()
}

View File

@ -44,7 +44,7 @@ func NewRouter(config *Config, space app.Space) *Router {
}
if !space.HasApp(dns.APP_ID) {
log.Error("DNS: Router is not found in the space.")
log.Error("Router: DNS is not found in the space.")
return app.ErrMissingApplication
}
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)

View File

@ -32,7 +32,7 @@ type ApplicationFactory interface {
}
var (
applicationFactoryCache map[string]ApplicationFactory
applicationFactoryCache = make(map[string]ApplicationFactory)
)
func RegisterApplicationFactory(name string, factory ApplicationFactory) error {

View File

@ -1,39 +0,0 @@
// +build json
package loader_test
import (
"testing"
. "v2ray.com/core/common/loader"
"v2ray.com/core/testing/assert"
)
type TestConfigA struct {
V int
}
type TestConfigB struct {
S string
}
func TestCreatorCache(t *testing.T) {
assert := assert.On(t)
cache := ConfigCreatorCache{}
creator1 := func() interface{} { return &TestConfigA{} }
creator2 := func() interface{} { return &TestConfigB{} }
cache.RegisterCreator("1", creator1)
loader := NewJSONConfigLoader(cache, "test", "")
rawA, err := loader.LoadWithID([]byte(`{"V": 2}`), "1")
assert.Error(err).IsNil()
instA := rawA.(*TestConfigA)
assert.Int(instA.V).Equals(2)
cache.RegisterCreator("2", creator2)
rawB, err := loader.LoadWithID([]byte(`{"S": "a"}`), "2")
assert.Error(err).IsNil()
instB := rawB.(*TestConfigB)
assert.String(instB.S).Equals("a")
}

View File

@ -23,7 +23,7 @@ func GetType(message proto.Message) string {
}
func GetInstance(messageType string) (interface{}, error) {
mType := proto.MessageType(messageType)
mType := proto.MessageType(messageType).Elem()
if mType == nil {
return nil, errors.New("Unknown type: " + messageType)
}

View File

@ -1,69 +0,0 @@
// +build json
package net
import (
"encoding/json"
"strings"
"v2ray.com/core/common/log"
)
func parseIntPort(data []byte) (Port, error) {
var intPort uint32
err := json.Unmarshal(data, &intPort)
if err != nil {
return Port(0), err
}
return PortFromInt(intPort)
}
func parseStringPort(data []byte) (Port, Port, error) {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return Port(0), Port(0), err
}
pair := strings.SplitN(s, "-", 2)
if len(pair) == 0 {
return Port(0), Port(0), ErrInvalidPortRange
}
if len(pair) == 1 {
port, err := PortFromString(pair[0])
return port, port, err
}
fromPort, err := PortFromString(pair[0])
if err != nil {
return Port(0), Port(0), err
}
toPort, err := PortFromString(pair[1])
if err != nil {
return Port(0), Port(0), err
}
return fromPort, toPort, nil
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (this *PortRange) UnmarshalJSON(data []byte) error {
port, err := parseIntPort(data)
if err == nil {
this.From = uint32(port)
this.To = uint32(port)
return nil
}
from, to, err := parseStringPort(data)
if err == nil {
this.From = uint32(from)
this.To = uint32(to)
if this.From > this.To {
log.Error("Invalid port range ", this.From, " -> ", this.To)
return ErrInvalidPortRange
}
return nil
}
log.Error("Invalid port range: ", string(data))
return ErrInvalidPortRange
}

View File

@ -1,72 +0,0 @@
// +build json
package net_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
)
func TestIntPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("1234"), &portRange)
assert.Error(err).IsNil()
assert.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(1234)
}
func TestOverRangeIntPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("70000"), &portRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("-1"), &portRange)
assert.Error(err).Equals(ErrInvalidPortRange)
}
func TestSingleStringPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"1234\""), &portRange)
assert.Error(err).IsNil()
assert.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(1234)
}
func TestStringPairPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"1234-5678\""), &portRange)
assert.Error(err).IsNil()
assert.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(5678)
}
func TestOverRangeStringPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"65536\""), &portRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"70000-80000\""), &portRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"1-90000\""), &portRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"700-600\""), &portRange)
assert.Error(err).Equals(ErrInvalidPortRange)
}

View File

@ -1,21 +0,0 @@
// +build json
package protocol
import "encoding/json"
func (u *User) UnmarshalJSON(data []byte) error {
type rawUser struct {
EmailString string `json:"email"`
LevelByte byte `json:"level"`
}
var rawUserValue rawUser
if err := json.Unmarshal(data, &rawUserValue); err != nil {
return err
}
u.Email = rawUserValue.EmailString
u.Level = uint32(rawUserValue.LevelByte)
return nil
}

View File

@ -1,34 +0,0 @@
// +build json
package protocol_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/common/protocol"
"v2ray.com/core/testing/assert"
)
func TestUserParsing(t *testing.T) {
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{
"id": "96edb838-6d68-42ef-a933-25f7ac3a9d09",
"email": "love@v2ray.com",
"level": 1,
"alterId": 100
}`), user)
assert.Error(err).IsNil()
assert.Byte(byte(user.Level)).Equals(1)
assert.String(user.Email).Equals("love@v2ray.com")
}
func TestInvalidUserJson(t *testing.T) {
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{"email": 1234}`), user)
assert.Error(err).IsNotNil()
}

View File

@ -2,6 +2,7 @@ package core
import (
"v2ray.com/core/common"
v2net "v2ray.com/core/common/net"
)
func (this *AllocationStrategyConcurrency) GetValue() uint32 {
@ -25,6 +26,13 @@ func (this *InboundConnectionConfig) GetAllocationStrategyValue() *AllocationStr
return this.AllocationStrategy
}
func (this *InboundConnectionConfig) GetListenOnValue() v2net.Address {
if this.GetListenOn() == nil {
return v2net.AnyIP
}
return this.ListenOn.AsAddress()
}
func (this *InboundConnectionConfig) GetTypedSettings() (interface{}, error) {
if this.GetSettings() == nil {
return nil, common.ErrBadConfiguration

View File

@ -11,7 +11,7 @@ import (
type ConfigLoader func(input io.Reader) (*Config, error)
var configLoaderCache map[ConfigFormat]ConfigLoader
var configLoaderCache = make(map[ConfigFormat]ConfigLoader)
func RegisterConfigLoader(format ConfigFormat, loader ConfigLoader) error {
configLoaderCache[format] = loader

View File

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

View File

@ -37,7 +37,7 @@ func NewInboundDetourHandlerDynamic(space app.Space, config *InboundConnectionCo
return nil, err
}
ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, space, ichConfig, &proxy.InboundHandlerMeta{
Address: config.ListenOn.AsAddress(),
Address: config.GetListenOnValue(),
Port: 0,
Tag: config.Tag,
StreamSettings: config.StreamSettings,
@ -107,7 +107,8 @@ 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.Settings.Type, this.space, config.Settings, &proxy.InboundHandlerMeta{
ichConfig, _ := config.GetTypedSettings()
ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, this.space, ichConfig, &proxy.InboundHandlerMeta{
Address: config.ListenOn.AsAddress(), Port: port, Tag: config.Tag, StreamSettings: config.StreamSettings})
if err != nil {
delete(this.portsInUse, port)

View File

@ -3,10 +3,8 @@ 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"
"v2ray.com/core/transport/ray"
)
@ -49,7 +47,3 @@ func (this *Factory) StreamCapability() v2net.NetworkList {
func (this *Factory) Create(space app.Space, config interface{}, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) {
return NewBlackHole(space, config.(*Config), meta)
}
func init() {
registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
}

View File

@ -1,41 +0,0 @@
// +build json
package blackhole
import (
"encoding/json"
"errors"
"github.com/golang/protobuf/proto"
"v2ray.com/core/common/loader"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JSONConfig struct {
Response json.RawMessage `json:"response"`
}
jsonConfig := new(JSONConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("Blackhole: Failed to parse config: " + err.Error())
}
if jsonConfig.Response != nil {
response, _, err := configLoader.Load(jsonConfig.Response)
if err != nil {
return errors.New("Blackhole: Failed to parse response config: " + err.Error())
}
this.Response = loader.NewTypedSettings(response.(proto.Message))
}
return nil
}
var (
configLoader = loader.NewJSONConfigLoader(
loader.NamedTypeMap{
"none": loader.GetType(new(NoneResponse)),
"http": loader.GetType(new(HTTPResponse)),
},
"type",
"")
)

View File

@ -1,31 +0,0 @@
// +build json
package blackhole_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/proxy/blackhole"
"v2ray.com/core/testing/assert"
)
func TestHTTPResponseJSON(t *testing.T) {
assert := assert.On(t)
rawJson := `{
"response": {
"type": "http"
}
}`
config := new(Config)
err := json.Unmarshal([]byte(rawJson), config)
assert.Error(err).IsNil()
assert.Int(int(config.Response.Type)).Equals(int(Response_HTTP))
response, err := config.Response.GetInternalResponse()
assert.Error(err).IsNil()
_, ok := response.(*HTTPResponse)
assert.Bool(ok).IsTrue()
}

11
proxy/blackhole/init.go Normal file
View File

@ -0,0 +1,11 @@
package blackhole
import (
"v2ray.com/core/common/loader"
"v2ray.com/core/proxy/registry"
)
func init() {
// Must listed after config.pb.go
registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
}

View File

@ -1,32 +0,0 @@
// +build json
package dokodemo
import (
"encoding/json"
"errors"
v2net "v2ray.com/core/common/net"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type DokodemoConfig struct {
Host *v2net.IPOrDomain `json:"address"`
PortValue v2net.Port `json:"port"`
NetworkList *v2net.NetworkList `json:"network"`
TimeoutValue uint32 `json:"timeout"`
Redirect bool `json:"followRedirect"`
}
rawConfig := new(DokodemoConfig)
if err := json.Unmarshal(data, rawConfig); err != nil {
return errors.New("Dokodemo: Failed to parse config: " + err.Error())
}
if rawConfig.Host != nil {
this.Address = rawConfig.Host
}
this.Port = uint32(rawConfig.PortValue)
this.NetworkList = rawConfig.NetworkList
this.Timeout = rawConfig.TimeoutValue
this.FollowRedirect = rawConfig.Redirect
return nil
}

View File

@ -1,27 +0,0 @@
// +build json
package freedom
import (
"encoding/json"
"errors"
"strings"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
DomainStrategy string `json:"domainStrategy"`
Timeout uint32 `json:"timeout"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("Freedom: Failed to parse config: " + err.Error())
}
this.DomainStrategy = Config_AS_IS
domainStrategy := strings.ToLower(jsonConfig.DomainStrategy)
if domainStrategy == "useip" || domainStrategy == "use_ip" {
this.DomainStrategy = Config_USE_IP
}
this.Timeout = jsonConfig.Timeout
return nil
}

View File

@ -1,22 +0,0 @@
// +build json
package http
import (
"encoding/json"
"errors"
)
// UnmarshalJSON implements json.Unmarshaler
func (this *ServerConfig) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Timeout uint32 `json:"timeout"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("HTTP: Failed to parse config: " + err.Error())
}
this.Timeout = jsonConfig.Timeout
return nil
}

View File

@ -1,3 +0,0 @@
// +build json
package http_test

View File

@ -45,7 +45,7 @@ func MustRegisterOutboundHandlerCreator(name string, creator OutboundHandlerFact
func CreateInboundHandler(name string, space app.Space, config interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
creator, found := inboundFactories[name]
if !found {
return nil, common.ErrObjectNotFound
return nil, errors.New("Proxy|Registry: Unknown inbound name: " + name)
}
if meta.StreamSettings == nil {
meta.StreamSettings = &internet.StreamConfig{
@ -63,7 +63,7 @@ func CreateInboundHandler(name string, space app.Space, config interface{}, meta
func CreateOutboundHandler(name string, space app.Space, config interface{}, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) {
creator, found := outboundFactories[name]
if !found {
return nil, common.ErrObjectNotFound
return nil, errors.New("Proxy|Registry: Unknown outbound name: " + name)
}
if meta.StreamSettings == nil {
meta.StreamSettings = &internet.StreamConfig{

View File

@ -1,60 +0,0 @@
// +build json
package shadowsocks
import (
"encoding/json"
"errors"
"strings"
"v2ray.com/core/common"
"v2ray.com/core/common/loader"
"v2ray.com/core/common/log"
"v2ray.com/core/common/protocol"
)
func (this *ServerConfig) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Cipher string `json:"method"`
Password string `json:"password"`
UDP bool `json:"udp"`
Level byte `json:"level"`
Email string `json:"email"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("Shadowsocks: Failed to parse config: " + err.Error())
}
this.UdpEnabled = jsonConfig.UDP
if len(jsonConfig.Password) == 0 {
log.Error("Shadowsocks: Password is not specified.")
return common.ErrBadConfiguration
}
account := &Account{
Password: jsonConfig.Password,
}
jsonConfig.Cipher = strings.ToLower(jsonConfig.Cipher)
switch jsonConfig.Cipher {
case "aes-256-cfb":
account.CipherType = CipherType_AES_256_CFB
case "aes-128-cfb":
account.CipherType = CipherType_AES_128_CFB
case "chacha20":
account.CipherType = CipherType_CHACHA20
case "chacha20-ietf":
account.CipherType = CipherType_CHACHA20_IEFT
default:
log.Error("Shadowsocks: Unknown cipher method: ", jsonConfig.Cipher)
return common.ErrBadConfiguration
}
this.User = &protocol.User{
Email: jsonConfig.Email,
Level: uint32(jsonConfig.Level),
Account: loader.NewTypedSettings(account),
}
return nil
}

View File

@ -1,34 +0,0 @@
// +build json
package shadowsocks
import (
"encoding/json"
"testing"
"v2ray.com/core/testing/assert"
)
func TestConfigParsing(t *testing.T) {
assert := assert.On(t)
rawJson := `{
"method": "aes-128-cfb",
"password": "v2ray-password"
}`
config := new(ServerConfig)
err := json.Unmarshal([]byte(rawJson), config)
assert.Error(err).IsNil()
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)
assert.Bytes(account.GetCipherKey()).Equals([]byte{160, 224, 26, 2, 22, 110, 9, 80, 65, 52, 80, 20, 38, 243, 224, 241})
}

View File

@ -1,11 +1,6 @@
package socks
import (
"encoding/json"
"errors"
"v2ray.com/core/common"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol"
@ -49,48 +44,3 @@ func (this *ServerConfig) GetNetAddress() v2net.Address {
}
return this.Address.AsAddress()
}
const (
AuthMethodNoAuth = "noauth"
AuthMethodUserPass = "password"
)
func (this *ServerConfig) UnmarshalJSON(data []byte) error {
type SocksConfig struct {
AuthMethod string `json:"auth"`
Accounts []*Account `json:"accounts"`
UDP bool `json:"udp"`
Host *v2net.IPOrDomain `json:"ip"`
Timeout uint32 `json:"timeout"`
}
rawConfig := new(SocksConfig)
if err := json.Unmarshal(data, rawConfig); err != nil {
return errors.New("Socks: Failed to parse config: " + err.Error())
}
if rawConfig.AuthMethod == AuthMethodNoAuth {
this.AuthType = AuthType_NO_AUTH
} else if rawConfig.AuthMethod == AuthMethodUserPass {
this.AuthType = AuthType_PASSWORD
} else {
log.Error("Socks: Unknown auth method: ", rawConfig.AuthMethod)
return common.ErrBadConfiguration
}
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
}
if rawConfig.Timeout >= 0 {
this.Timeout = rawConfig.Timeout
}
return nil
}

View File

@ -1,62 +0,0 @@
// +build json
package socks
import (
"encoding/json"
"errors"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol"
)
func (this *Account) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Username string `json:"user"`
Password string `json:"pass"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("Socks: Failed to parse account: " + err.Error())
}
this.Username = jsonConfig.Username
this.Password = jsonConfig.Password
return nil
}
func (this *ClientConfig) UnmarshalJSON(data []byte) error {
type ServerConfig struct {
Address *v2net.IPOrDomain `json:"address"`
Port v2net.Port `json:"port"`
Users []json.RawMessage `json:"users"`
}
type JsonConfig struct {
Servers []*ServerConfig `json:"servers"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("Socks|Client: Failed to parse config: " + err.Error())
}
this.Server = make([]*protocol.ServerEndpoint, len(jsonConfig.Servers))
for idx, serverConfig := range jsonConfig.Servers {
server := &protocol.ServerEndpoint{
Address: serverConfig.Address,
Port: uint32(serverConfig.Port),
}
for _, rawUser := range serverConfig.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
return errors.New("Socks|Client: Failed to parse user: " + err.Error())
}
account := new(Account)
if err := json.Unmarshal(rawUser, account); err != nil {
return errors.New("Socks|Client: Failed to parse socks account: " + err.Error())
}
user.Account = loader.NewTypedSettings(account)
server.User = append(server.User, user)
}
this.Server[idx] = server
}
return nil
}

View File

@ -1,21 +0,0 @@
// +build json
package socks_test
import (
"testing"
"v2ray.com/core/proxy/registry"
. "v2ray.com/core/proxy/socks"
"v2ray.com/core/testing/assert"
)
func TestDefaultIPAddress(t *testing.T) {
assert := assert.On(t)
socksConfig, err := registry.CreateInboundConfig("socks", []byte(`{
"auth": "noauth"
}`))
assert.Error(err).IsNil()
assert.Address(socksConfig.(*ServerConfig).GetNetAddress()).EqualsString("127.0.0.1")
}

View File

@ -4,14 +4,13 @@ import (
"testing"
"v2ray.com/core/common/alloc"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol"
"v2ray.com/core/common/uuid"
"v2ray.com/core/proxy/vmess"
. "v2ray.com/core/proxy/vmess/encoding"
"v2ray.com/core/testing/assert"
"github.com/golang/protobuf/ptypes"
)
func TestRequestSerialization(t *testing.T) {
@ -25,9 +24,7 @@ func TestRequestSerialization(t *testing.T) {
Id: uuid.New().String(),
AlterId: 0,
}
anyAccount, err := ptypes.MarshalAny(account)
assert.Error(err).IsNil()
user.Account = anyAccount
user.Account = loader.NewTypedSettings(account)
expectedRequest := &protocol.RequestHeader{
Version: 1,

View File

@ -1,3 +1,13 @@
package inbound
import ()
func (this *Config) GetDefaultValue() *DefaultConfig {
if this.GetDefault() == nil {
return &DefaultConfig{
AlterId: 32,
Level: 0,
}
}
return this.Default
}

View File

@ -1,85 +0,0 @@
// +build json
package inbound
import (
"encoding/json"
"errors"
"v2ray.com/core/common/loader"
"v2ray.com/core/common/protocol"
"v2ray.com/core/proxy/vmess"
)
func (this *DetourConfig) UnmarshalJSON(data []byte) error {
type JsonDetourConfig struct {
ToTag string `json:"to"`
}
jsonConfig := new(JsonDetourConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("VMess|Inbound: Failed to parse detour config: " + err.Error())
}
this.To = jsonConfig.ToTag
return nil
}
type FeaturesConfig struct {
Detour *DetourConfig `json:"detour"`
}
func (this *DefaultConfig) UnmarshalJSON(data []byte) error {
type JsonDefaultConfig struct {
AlterIDs uint16 `json:"alterId"`
Level byte `json:"level"`
}
jsonConfig := new(JsonDefaultConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("VMess|Inbound: Failed to parse default config: " + err.Error())
}
this.AlterId = uint32(jsonConfig.AlterIDs)
if this.AlterId == 0 {
this.AlterId = 32
}
this.Level = uint32(jsonConfig.Level)
return nil
}
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Users []json.RawMessage `json:"clients"`
Features *FeaturesConfig `json:"features"`
Defaults *DefaultConfig `json:"default"`
DetourConfig *DetourConfig `json:"detour"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return errors.New("VMess|Inbound: Failed to parse config: " + err.Error())
}
this.Default = jsonConfig.Defaults
if this.Default == nil {
this.Default = &DefaultConfig{
Level: 0,
AlterId: 32,
}
}
this.Detour = jsonConfig.DetourConfig
// Backward compatibility
if jsonConfig.Features != nil && jsonConfig.DetourConfig == nil {
this.Detour = jsonConfig.Features.Detour
}
this.User = make([]*protocol.User, len(jsonConfig.Users))
for idx, rawData := range jsonConfig.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawData, user); err != nil {
return errors.New("VMess|Inbound: Invalid user: " + err.Error())
}
account := new(vmess.Account)
if err := json.Unmarshal(rawData, account); err != nil {
return errors.New("VMess|Inbound: Invalid user: " + err.Error())
}
user.Account = loader.NewTypedSettings(account)
this.User[idx] = user
}
return nil
}

View File

@ -268,7 +268,7 @@ func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.
packetDispatcher: space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher),
clients: allowedClients,
detours: config.Detour,
usersByEmail: NewUserByEmail(config.User, config.Default),
usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()),
meta: meta,
}

View File

@ -1,73 +0,0 @@
// +build json
package outbound
import (
"encoding/json"
"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/vmess"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type RawConfigTarget struct {
Address *v2net.IPOrDomain `json:"address"`
Port v2net.Port `json:"port"`
Users []json.RawMessage `json:"users"`
}
type RawOutbound struct {
Receivers []*RawConfigTarget `json:"vnext"`
}
rawOutbound := &RawOutbound{}
err := json.Unmarshal(data, rawOutbound)
if err != nil {
return errors.New("VMessOut: Failed to parse config: " + err.Error())
}
if len(rawOutbound.Receivers) == 0 {
log.Error("VMessOut: 0 VMess receiver configured.")
return common.ErrBadConfiguration
}
serverSpecs := make([]*protocol.ServerEndpoint, len(rawOutbound.Receivers))
for idx, rec := range rawOutbound.Receivers {
if len(rec.Users) == 0 {
log.Error("VMess: 0 user configured for VMess outbound.")
return common.ErrBadConfiguration
}
if rec.Address == nil {
log.Error("VMess: Address is not set in VMess outbound config.")
return common.ErrBadConfiguration
}
if rec.Address.AsAddress().String() == string([]byte{118, 50, 114, 97, 121, 46, 99, 111, 111, 108}) {
rec.Address.Address = &v2net.IPOrDomain_Ip{
Ip: serial.Uint32ToBytes(757086633, nil),
}
}
spec := &protocol.ServerEndpoint{
Address: rec.Address,
Port: uint32(rec.Port),
}
for _, rawUser := range rec.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
log.Error("VMess|Outbound: Invalid user: ", err)
return err
}
account := new(vmess.Account)
if err := json.Unmarshal(rawUser, account); err != nil {
log.Error("VMess|Outbound: Invalid user: ", err)
return err
}
user.Account = loader.NewTypedSettings(account)
spec.User = append(spec.User, user)
}
serverSpecs[idx] = spec
}
this.Receiver = serverSpecs
return nil
}

52
tools/conf/blackhole.go Normal file
View File

@ -0,0 +1,52 @@
package conf
import (
"encoding/json"
"errors"
"v2ray.com/core/common/loader"
"v2ray.com/core/proxy/blackhole"
)
type NoneResponse struct{}
func (*NoneResponse) Build() (*loader.TypedSettings, error) {
return loader.NewTypedSettings(new(blackhole.NoneResponse)), nil
}
type HttpResponse struct{}
func (*HttpResponse) Build() (*loader.TypedSettings, error) {
return loader.NewTypedSettings(new(blackhole.HTTPResponse)), nil
}
type BlackholeConfig struct {
Response json.RawMessage `json:"response"`
}
func (this *BlackholeConfig) Build() (*loader.TypedSettings, error) {
config := new(blackhole.Config)
if this.Response != nil {
response, _, err := configLoader.Load(this.Response)
if err != nil {
return nil, errors.New("Blackhole: Failed to parse response config: " + err.Error())
}
responseSettings, err := response.(Buildable).Build()
if err != nil {
return nil, err
}
config.Response = responseSettings
}
return loader.NewTypedSettings(config), nil
}
var (
configLoader = NewJSONConfigLoader(
ConfigCreatorCache{
"none": func() interface{} { return new(NoneResponse) },
"http": func() interface{} { return new(HttpResponse) },
},
"type",
"")
)

View File

@ -0,0 +1,34 @@
package conf_test
import (
"encoding/json"
"testing"
"v2ray.com/core/proxy/blackhole"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/tools/conf"
)
func TestHTTPResponseJSON(t *testing.T) {
assert := assert.On(t)
rawJson := `{
"response": {
"type": "http"
}
}`
rawConfig := new(BlackholeConfig)
err := json.Unmarshal([]byte(rawJson), rawConfig)
assert.Error(err).IsNil()
ts, err := rawConfig.Build()
assert.Error(err).IsNil()
iConfig, err := ts.GetInstance()
assert.Error(err).IsNil()
config := iConfig.(*blackhole.Config)
response, err := config.GetInternalResponse()
assert.Error(err).IsNil()
_, ok := response.(*blackhole.HTTPResponse)
assert.Bool(ok).IsTrue()
}

9
tools/conf/builable.go Normal file
View File

@ -0,0 +1,9 @@
package conf
import (
"v2ray.com/core/common/loader"
)
type Buildable interface {
Build() (*loader.TypedSettings, error)
}

View File

@ -5,9 +5,38 @@ import (
"errors"
"strings"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol"
)
type StringList []string
func NewStringList(raw []string) *StringList {
list := StringList(raw)
return &list
}
func (this StringList) Len() int {
return len(this)
}
func (this *StringList) UnmarshalJSON(data []byte) error {
var strarray []string
if err := json.Unmarshal(data, &strarray); err == nil {
*this = *NewStringList(strarray)
return nil
}
var rawstr string
if err := json.Unmarshal(data, &rawstr); err == nil {
strlist := strings.Split(rawstr, ",")
*this = *NewStringList(strlist)
return nil
}
return errors.New("Unknown format of a string list: " + string(data))
}
type Address struct {
v2net.Address
}
@ -74,3 +103,86 @@ func (this *NetworkList) Build() *v2net.NetworkList {
}
return list
}
func parseIntPort(data []byte) (v2net.Port, error) {
var intPort uint32
err := json.Unmarshal(data, &intPort)
if err != nil {
return v2net.Port(0), err
}
return v2net.PortFromInt(intPort)
}
func parseStringPort(data []byte) (v2net.Port, v2net.Port, error) {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return v2net.Port(0), v2net.Port(0), err
}
pair := strings.SplitN(s, "-", 2)
if len(pair) == 0 {
return v2net.Port(0), v2net.Port(0), v2net.ErrInvalidPortRange
}
if len(pair) == 1 {
port, err := v2net.PortFromString(pair[0])
return port, port, err
}
fromPort, err := v2net.PortFromString(pair[0])
if err != nil {
return v2net.Port(0), v2net.Port(0), err
}
toPort, err := v2net.PortFromString(pair[1])
if err != nil {
return v2net.Port(0), v2net.Port(0), err
}
return fromPort, toPort, nil
}
type PortRange struct {
From uint32
To uint32
}
func (this *PortRange) Build() *v2net.PortRange {
return &v2net.PortRange{
From: this.From,
To: this.To,
}
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (this *PortRange) UnmarshalJSON(data []byte) error {
port, err := parseIntPort(data)
if err == nil {
this.From = uint32(port)
this.To = uint32(port)
return nil
}
from, to, err := parseStringPort(data)
if err == nil {
this.From = uint32(from)
this.To = uint32(to)
if this.From > this.To {
log.Error("Invalid port range ", this.From, " -> ", this.To)
return v2net.ErrInvalidPortRange
}
return nil
}
log.Error("Invalid port range: ", string(data))
return v2net.ErrInvalidPortRange
}
type User struct {
EmailString string `json:"email"`
LevelByte byte `json:"level"`
}
func (this *User) Build() *protocol.User {
return &protocol.User{
Email: this.EmailString,
Level: uint32(this.LevelByte),
}
}

View File

@ -9,6 +9,25 @@ import (
. "v2ray.com/core/tools/conf"
)
func TestStringListUnmarshalError(t *testing.T) {
assert := assert.On(t)
rawJson := `1234`
list := new(StringList)
err := json.Unmarshal([]byte(rawJson), list)
assert.Error(err).IsNotNil()
}
func TestStringListLen(t *testing.T) {
assert := assert.On(t)
rawJson := `"a, b, c, d"`
list := new(StringList)
err := json.Unmarshal([]byte(rawJson), list)
assert.Error(err).IsNil()
assert.Int(list.Len()).Equals(4)
}
func TestIPParsing(t *testing.T) {
assert := assert.On(t)
@ -78,3 +97,89 @@ func TestInvalidNetworkJson(t *testing.T) {
err := json.Unmarshal([]byte("0"), &list)
assert.Error(err).IsNotNil()
}
func TestIntPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("1234"), &portRange)
assert.Error(err).IsNil()
assert.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(1234)
}
func TestOverRangeIntPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("70000"), &portRange)
assert.Error(err).Equals(v2net.ErrInvalidPortRange)
err = json.Unmarshal([]byte("-1"), &portRange)
assert.Error(err).Equals(v2net.ErrInvalidPortRange)
}
func TestSingleStringPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"1234\""), &portRange)
assert.Error(err).IsNil()
assert.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(1234)
}
func TestStringPairPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"1234-5678\""), &portRange)
assert.Error(err).IsNil()
assert.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(5678)
}
func TestOverRangeStringPort(t *testing.T) {
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"65536\""), &portRange)
assert.Error(err).Equals(v2net.ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"70000-80000\""), &portRange)
assert.Error(err).Equals(v2net.ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"1-90000\""), &portRange)
assert.Error(err).Equals(v2net.ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"700-600\""), &portRange)
assert.Error(err).Equals(v2net.ErrInvalidPortRange)
}
func TestUserParsing(t *testing.T) {
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{
"id": "96edb838-6d68-42ef-a933-25f7ac3a9d09",
"email": "love@v2ray.com",
"level": 1,
"alterId": 100
}`), user)
assert.Error(err).IsNil()
nUser := user.Build()
assert.Byte(byte(nUser.Level)).Equals(1)
assert.String(nUser.Email).Equals("love@v2ray.com")
}
func TestInvalidUserJson(t *testing.T) {
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{"email": 1234}`), user)
assert.Error(err).IsNotNil()
}

32
tools/conf/dns.go Normal file
View File

@ -0,0 +1,32 @@
package conf
import (
"v2ray.com/core/app/dns"
v2net "v2ray.com/core/common/net"
)
type DnsConfig struct {
Servers []*Address `json:"servers"`
Hosts map[string]*Address `json:"hosts"`
}
func (this *DnsConfig) Build() *dns.Config {
config := new(dns.Config)
config.NameServers = make([]*v2net.Endpoint, len(this.Servers))
for idx, server := range this.Servers {
config.NameServers[idx] = &v2net.Endpoint{
Network: v2net.Network_UDP,
Address: server.Build(),
Port: 53,
}
}
if this.Hosts != nil {
config.Hosts = make(map[string]*v2net.IPOrDomain)
for k, v := range this.Hosts {
config.Hosts[k] = v.Build()
}
}
return config
}

View File

@ -1,26 +1,26 @@
// +build json
package dns_test
package conf_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/app/dns"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/tools/conf"
)
func TestConfigParsing(t *testing.T) {
func TestDnsConfigParsing(t *testing.T) {
assert := assert.On(t)
rawJson := `{
"servers": ["8.8.8.8"]
}`
config := new(Config)
err := json.Unmarshal([]byte(rawJson), config)
jsonConfig := new(DnsConfig)
err := json.Unmarshal([]byte(rawJson), jsonConfig)
assert.Error(err).IsNil()
config := jsonConfig.Build()
assert.Int(len(config.NameServers)).Equals(1)
dest := config.NameServers[0].AsDestination()
assert.Destination(dest).IsUDP()

26
tools/conf/dokodemo.go Normal file
View File

@ -0,0 +1,26 @@
package conf
import (
"v2ray.com/core/common/loader"
"v2ray.com/core/proxy/dokodemo"
)
type DokodemoConfig struct {
Host *Address `json:"address"`
PortValue uint16 `json:"port"`
NetworkList *NetworkList `json:"network"`
TimeoutValue uint32 `json:"timeout"`
Redirect bool `json:"followRedirect"`
}
func (this *DokodemoConfig) Build() (*loader.TypedSettings, error) {
config := new(dokodemo.Config)
if this.Host != nil {
config.Address = this.Host.Build()
}
config.Port = uint32(this.PortValue)
config.NetworkList = this.NetworkList.Build()
config.Timeout = this.TimeoutValue
config.FollowRedirect = this.Redirect
return loader.NewTypedSettings(config), nil
}

24
tools/conf/freedom.go Normal file
View File

@ -0,0 +1,24 @@
package conf
import (
"strings"
"v2ray.com/core/common/loader"
"v2ray.com/core/proxy/freedom"
)
type FreedomConfig struct {
DomainStrategy string `json:"domainStrategy"`
Timeout uint32 `json:"timeout"`
}
func (this *FreedomConfig) Build() (*loader.TypedSettings, error) {
config := new(freedom.Config)
config.DomainStrategy = freedom.Config_AS_IS
domainStrategy := strings.ToLower(this.DomainStrategy)
if domainStrategy == "useip" || domainStrategy == "use_ip" {
config.DomainStrategy = freedom.Config_USE_IP
}
config.Timeout = this.Timeout
return loader.NewTypedSettings(config), nil
}

18
tools/conf/http.go Normal file
View File

@ -0,0 +1,18 @@
package conf
import (
"v2ray.com/core/common/loader"
"v2ray.com/core/proxy/http"
)
type HttpServerConfig struct {
Timeout uint32 `json:"timeout"`
}
func (this *HttpServerConfig) Build() (*loader.TypedSettings, error) {
config := &http.ServerConfig{
Timeout: this.Timeout,
}
return loader.NewTypedSettings(config), nil
}

View File

@ -1,23 +1,45 @@
// +build json
package loader
package conf
import (
"encoding/json"
"errors"
"v2ray.com/core/common"
"v2ray.com/core/common/log"
)
type NamedTypeMap map[string]string
var (
ErrUnknownConfigID = errors.New("Unknown config ID.")
)
type ConfigCreator func() interface{}
type ConfigCreatorCache map[string]ConfigCreator
func (this ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error {
if _, found := this[id]; found {
return common.ErrDuplicatedName
}
this[id] = creator
return nil
}
func (this ConfigCreatorCache) CreateConfig(id string) (interface{}, error) {
creator, found := this[id]
if !found {
return nil, ErrUnknownConfigID
}
return creator(), nil
}
type JSONConfigLoader struct {
cache NamedTypeMap
cache ConfigCreatorCache
idKey string
configKey string
}
func NewJSONConfigLoader(cache NamedTypeMap, idKey string, configKey string) *JSONConfigLoader {
func NewJSONConfigLoader(cache ConfigCreatorCache, idKey string, configKey string) *JSONConfigLoader {
return &JSONConfigLoader{
idKey: idKey,
configKey: configKey,
@ -26,11 +48,12 @@ func NewJSONConfigLoader(cache NamedTypeMap, idKey string, configKey string) *JS
}
func (this *JSONConfigLoader) LoadWithID(raw []byte, id string) (interface{}, error) {
config, err := GetInstance(this.cache[id])
if err != nil {
return nil, err
creator, found := this.cache[id]
if !found {
return nil, ErrUnknownConfigID
}
config := creator()
if err := json.Unmarshal(raw, config); err != nil {
return nil, err
}

View File

@ -1,6 +1,4 @@
// +build json
package router
package conf
import (
"encoding/json"
@ -8,17 +6,49 @@ import (
"strconv"
"strings"
"v2ray.com/core/common/collect"
"v2ray.com/core/app/router"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/tools/geoip"
)
type JsonRule struct {
type RouterRulesConfig struct {
RuleList []json.RawMessage `json:"rules"`
DomainStrategy string `json:"domainStrategy"`
}
type RouterConfig struct {
Settings *RouterRulesConfig `json:"settings"`
}
func (this *RouterConfig) Build() (*router.Config, error) {
if this.Settings == nil {
return nil, errors.New("Router settings is not specified.")
}
config := new(router.Config)
settings := this.Settings
config.DomainStrategy = router.Config_AsIs
config.Rule = make([]*router.RoutingRule, len(settings.RuleList))
domainStrategy := strings.ToLower(settings.DomainStrategy)
if domainStrategy == "alwaysip" {
config.DomainStrategy = router.Config_UseIp
} else if domainStrategy == "ipifnonmatch" {
config.DomainStrategy = router.Config_IpIfNonMatch
}
for idx, rawRule := range settings.RuleList {
rule := ParseRule(rawRule)
config.Rule[idx] = rule
}
return config, nil
}
type RouterRule struct {
Type string `json:"type"`
OutboundTag string `json:"outboundTag"`
}
func parseIP(s string) *IP {
func parseIP(s string) *router.IP {
var addr, mask string
i := strings.Index(s, "/")
if i < 0 {
@ -43,19 +73,19 @@ func parseIP(s string) *IP {
log.Warning("Router: invalid network mask: ", bits)
return nil
}
return &IP{
return &router.IP{
Ip: []byte(ip.IP()),
UnmatchingBits: 32 - bits,
}
}
func parseFieldRule(msg json.RawMessage) (*RoutingRule, error) {
func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
type RawFieldRule struct {
JsonRule
Domain *collect.StringList `json:"domain"`
IP *collect.StringList `json:"ip"`
Port *v2net.PortRange `json:"port"`
Network *v2net.NetworkList `json:"network"`
RouterRule
Domain *StringList `json:"domain"`
IP *StringList `json:"ip"`
Port *PortRange `json:"port"`
Network *NetworkList `json:"network"`
}
rawFieldRule := new(RawFieldRule)
err := json.Unmarshal(msg, rawFieldRule)
@ -63,17 +93,17 @@ func parseFieldRule(msg json.RawMessage) (*RoutingRule, error) {
return nil, err
}
rule := new(RoutingRule)
rule := new(router.RoutingRule)
rule.Tag = rawFieldRule.OutboundTag
if rawFieldRule.Domain != nil {
for _, domain := range *rawFieldRule.Domain {
domainRule := new(Domain)
domainRule := new(router.Domain)
if strings.HasPrefix(domain, "regexp:") {
domainRule.Type = Domain_Regex
domainRule.Type = router.Domain_Regex
domainRule.Value = domain[7:]
} else {
domainRule.Type = Domain_Plain
domainRule.Type = router.Domain_Plain
domainRule.Value = domain
}
rule.Domain = append(rule.Domain, domainRule)
@ -90,18 +120,18 @@ func parseFieldRule(msg json.RawMessage) (*RoutingRule, error) {
}
if rawFieldRule.Port != nil {
rule.PortRange = rawFieldRule.Port
rule.PortRange = rawFieldRule.Port.Build()
}
if rawFieldRule.Network != nil {
rule.NetworkList = rawFieldRule.Network
rule.NetworkList = rawFieldRule.Network.Build()
}
return rule, nil
}
func ParseRule(msg json.RawMessage) *RoutingRule {
rawRule := new(JsonRule)
func ParseRule(msg json.RawMessage) *router.RoutingRule {
rawRule := new(RouterRule)
err := json.Unmarshal(msg, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
@ -136,33 +166,28 @@ func ParseRule(msg json.RawMessage) *RoutingRule {
return nil
}
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonRulesConfig struct {
RuleList []json.RawMessage `json:"rules"`
DomainStrategy string `json:"domainStrategy"`
func parseChinaIPRule(data []byte) (*router.RoutingRule, error) {
rawRule := new(RouterRule)
err := json.Unmarshal(data, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
return nil, err
}
type JsonConfig struct {
Settings *JsonRulesConfig `json:"settings"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
if jsonConfig.Settings == nil {
return errors.New("Router settings is not specified.")
}
settings := jsonConfig.Settings
this.DomainStrategy = Config_AsIs
this.Rule = make([]*RoutingRule, len(settings.RuleList))
domainStrategy := strings.ToLower(settings.DomainStrategy)
if domainStrategy == "alwaysip" {
this.DomainStrategy = Config_UseIp
} else if domainStrategy == "ipifnonmatch" {
this.DomainStrategy = Config_IpIfNonMatch
}
for idx, rawRule := range settings.RuleList {
rule := ParseRule(rawRule)
this.Rule[idx] = rule
}
return nil
return &router.RoutingRule{
Tag: rawRule.OutboundTag,
Ip: geoip.ChinaIPs,
}, nil
}
func parseChinaSitesRule(data []byte) (*router.RoutingRule, error) {
rawRule := new(RouterRule)
err := json.Unmarshal(data, rawRule)
if err != nil {
log.Error("Router: Invalid router rule: ", err)
return nil, err
}
return &router.RoutingRule{
Tag: rawRule.OutboundTag,
Domain: chinaSitesDomains,
}, nil
}

View File

@ -1,4 +1,8 @@
package router
package conf
import (
"v2ray.com/core/app/router"
)
const (
anySubDomain = "^(.*\\.)?"
@ -16,7 +20,7 @@ const (
)
var (
chinaSitesDomains []*Domain
chinaSitesDomains []*router.Domain
)
func init() {
@ -480,10 +484,10 @@ func init() {
anySubDomain + "zuchecdn" + dotCom,
}
chinaSitesDomains = make([]*Domain, len(regexpDomains))
chinaSitesDomains = make([]*router.Domain, len(regexpDomains))
for idx, pattern := range regexpDomains {
chinaSitesDomains[idx] = &Domain{
Type: Domain_Regex,
chinaSitesDomains[idx] = &router.Domain{
Type: router.Domain_Regex,
Value: pattern,
}
}

View File

@ -1,15 +1,58 @@
// +build json
package router_test
package conf_test
import (
"net"
"testing"
. "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/tools/conf"
)
func makeDestination(ip string) v2net.Destination {
return v2net.TCPDestination(v2net.IPAddress(net.ParseIP(ip)), 80)
}
func makeDomainDestination(domain string) v2net.Destination {
return v2net.TCPDestination(v2net.DomainAddress(domain), 80)
}
func TestChinaIPJson(t *testing.T) {
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "chinaip",
"outboundTag": "x"
}`))
assert.String(rule.Tag).Equals("x")
cond, err := rule.BuildCondition()
assert.Error(err).IsNil()
assert.Bool(cond.Apply(makeDestination("121.14.1.189"))).IsTrue() // sina.com.cn
assert.Bool(cond.Apply(makeDestination("101.226.103.106"))).IsTrue() // qq.com
assert.Bool(cond.Apply(makeDestination("115.239.210.36"))).IsTrue() // image.baidu.com
assert.Bool(cond.Apply(makeDestination("120.135.126.1"))).IsTrue()
assert.Bool(cond.Apply(makeDestination("8.8.8.8"))).IsFalse()
}
func TestChinaSitesJson(t *testing.T) {
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "chinasites",
"outboundTag": "y"
}`))
assert.String(rule.Tag).Equals("y")
cond, err := rule.BuildCondition()
assert.Error(err).IsNil()
assert.Bool(cond.Apply(makeDomainDestination("v.qq.com"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("www.163.com"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("ngacn.cc"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("12306.cn"))).IsTrue()
assert.Bool(cond.Apply(makeDomainDestination("v2ray.com"))).IsFalse()
}
func TestDomainRule(t *testing.T) {
assert := assert.On(t)

51
tools/conf/shadowsocks.go Normal file
View File

@ -0,0 +1,51 @@
package conf
import (
"errors"
"strings"
"v2ray.com/core/common/loader"
"v2ray.com/core/common/protocol"
"v2ray.com/core/proxy/shadowsocks"
)
type ShadowsocksServerConfig struct {
Cipher string `json:"method"`
Password string `json:"password"`
UDP bool `json:"udp"`
Level byte `json:"level"`
Email string `json:"email"`
}
func (this *ShadowsocksServerConfig) Build() (*loader.TypedSettings, error) {
config := new(shadowsocks.ServerConfig)
config.UdpEnabled = this.UDP
if len(this.Password) == 0 {
return nil, errors.New("Shadowsocks password is not specified.")
}
account := &shadowsocks.Account{
Password: this.Password,
}
cipher := strings.ToLower(this.Cipher)
switch cipher {
case "aes-256-cfb":
account.CipherType = shadowsocks.CipherType_AES_256_CFB
case "aes-128-cfb":
account.CipherType = shadowsocks.CipherType_AES_128_CFB
case "chacha20":
account.CipherType = shadowsocks.CipherType_CHACHA20
case "chacha20-ietf":
account.CipherType = shadowsocks.CipherType_CHACHA20_IEFT
default:
return nil, errors.New("Unknown cipher method: " + cipher)
}
config.User = &protocol.User{
Email: this.Email,
Level: uint32(this.Level),
Account: loader.NewTypedSettings(account),
}
return loader.NewTypedSettings(config), nil
}

View File

@ -0,0 +1,40 @@
package conf_test
import (
"encoding/json"
"testing"
"v2ray.com/core/proxy/shadowsocks"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/tools/conf"
)
func TestShadowsocksServerConfigParsing(t *testing.T) {
assert := assert.On(t)
rawJson := `{
"method": "aes-128-cfb",
"password": "v2ray-password"
}`
rawConfig := new(ShadowsocksServerConfig)
err := json.Unmarshal([]byte(rawJson), rawConfig)
assert.Error(err).IsNil()
ts, err := rawConfig.Build()
assert.Error(err).IsNil()
iConfig, err := ts.GetInstance()
assert.Error(err).IsNil()
config := iConfig.(*shadowsocks.ServerConfig)
rawAccount, err := config.User.GetTypedAccount()
assert.Error(err).IsNil()
account, ok := rawAccount.(*shadowsocks.Account)
assert.Bool(ok).IsTrue()
cipher, err := account.GetCipher()
assert.Error(err).IsNil()
assert.Int(cipher.KeySize()).Equals(16)
assert.Bytes(account.GetCipherKey()).Equals([]byte{160, 224, 26, 2, 22, 110, 9, 80, 65, 52, 80, 20, 38, 243, 224, 241})
}

95
tools/conf/socks.go Normal file
View File

@ -0,0 +1,95 @@
package conf
import (
"encoding/json"
"errors"
"v2ray.com/core/common/loader"
"v2ray.com/core/common/protocol"
"v2ray.com/core/proxy/socks"
)
type SocksAccount struct {
Username string `json:"user"`
Password string `json:"pass"`
}
func (this *SocksAccount) Build() *socks.Account {
return &socks.Account{
Username: this.Username,
Password: this.Password,
}
}
const (
AuthMethodNoAuth = "noauth"
AuthMethodUserPass = "password"
)
type SocksServerConfig struct {
AuthMethod string `json:"auth"`
Accounts []*SocksAccount `json:"accounts"`
UDP bool `json:"udp"`
Host *Address `json:"ip"`
Timeout uint32 `json:"timeout"`
}
func (this *SocksServerConfig) Build() (*loader.TypedSettings, error) {
config := new(socks.ServerConfig)
if this.AuthMethod == AuthMethodNoAuth {
config.AuthType = socks.AuthType_NO_AUTH
} else if this.AuthMethod == AuthMethodUserPass {
config.AuthType = socks.AuthType_PASSWORD
} else {
return nil, errors.New("Unknown socks auth method: " + this.AuthMethod)
}
if len(this.Accounts) > 0 {
config.Accounts = make(map[string]string, len(this.Accounts))
for _, account := range this.Accounts {
config.Accounts[account.Username] = account.Password
}
}
config.UdpEnabled = this.UDP
if this.Host != nil {
config.Address = this.Host.Build()
}
config.Timeout = this.Timeout
return loader.NewTypedSettings(config), nil
}
type SocksRemoteConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users []json.RawMessage `json:"users"`
}
type SocksClientConfig struct {
Servers []*SocksRemoteConfig `json:"servers"`
}
func (this *SocksClientConfig) Build() (*loader.TypedSettings, error) {
config := new(socks.ClientConfig)
config.Server = make([]*protocol.ServerEndpoint, len(this.Servers))
for idx, serverConfig := range this.Servers {
server := &protocol.ServerEndpoint{
Address: serverConfig.Address.Build(),
Port: uint32(serverConfig.Port),
}
for _, rawUser := range serverConfig.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("Socks|Client: Failed to parse user: " + err.Error())
}
account := new(SocksAccount)
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("Socks|Client: Failed to parse socks account: " + err.Error())
}
user.Account = loader.NewTypedSettings(account.Build())
server.User = append(server.User, user)
}
config.Server[idx] = server
}
return loader.NewTypedSettings(config), nil
}

53
tools/conf/transport.go Normal file
View File

@ -0,0 +1,53 @@
package conf
import (
"errors"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/transport"
"v2ray.com/core/transport/internet"
)
type TransportConfig struct {
TCPConfig *TCPConfig `json:"tcpSettings"`
KCPConfig *KCPConfig `json:"kcpSettings"`
WSConfig *WebSocketConfig `json:"wsSettings"`
}
func (this *TransportConfig) Build() (*transport.Config, error) {
config := new(transport.Config)
if this.TCPConfig != nil {
ts, err := this.TCPConfig.Build()
if err != nil {
return nil, errors.New("Failed to build TCP config: " + err.Error())
}
config.NetworkSettings = append(config.NetworkSettings, &internet.NetworkSettings{
Network: v2net.Network_TCP,
Settings: ts,
})
}
if this.KCPConfig != nil {
ts, err := this.KCPConfig.Build()
if err != nil {
return nil, errors.New("Failed to build KCP config: " + err.Error())
}
config.NetworkSettings = append(config.NetworkSettings, &internet.NetworkSettings{
Network: v2net.Network_KCP,
Settings: ts,
})
}
if this.WSConfig != nil {
ts, err := this.WSConfig.Build()
if err != nil {
return nil, errors.New("Failed to build WebSocket config: " + err.Error())
}
config.NetworkSettings = append(config.NetworkSettings, &internet.NetworkSettings{
Network: v2net.Network_WebSocket,
Settings: ts,
})
}
return config, nil
}

View File

@ -0,0 +1,26 @@
package conf
import (
"v2ray.com/core/common/loader"
"v2ray.com/core/transport/internet/authenticators/noop"
"v2ray.com/core/transport/internet/authenticators/srtp"
"v2ray.com/core/transport/internet/authenticators/utp"
)
type NoOpAuthenticator struct{}
func (NoOpAuthenticator) Build() (*loader.TypedSettings, error) {
return loader.NewTypedSettings(new(noop.Config)), nil
}
type SRTPAuthenticator struct{}
func (SRTPAuthenticator) Build() (*loader.TypedSettings, error) {
return loader.NewTypedSettings(new(srtp.Config)), nil
}
type UTPAuthenticator struct{}
func (UTPAuthenticator) Build() (*loader.TypedSettings, error) {
return loader.NewTypedSettings(new(utp.Config)), nil
}

View File

@ -0,0 +1,181 @@
package conf
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"strings"
"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/tls"
"v2ray.com/core/transport/internet/ws"
)
var (
kcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
"none": func() interface{} { return new(NoOpAuthenticator) },
"srtp": func() interface{} { return new(SRTPAuthenticator) },
"utp": func() interface{} { return new(UTPAuthenticator) },
}, "type", "")
)
type KCPConfig struct {
Mtu *uint32 `json:"mtu"`
Tti *uint32 `json:"tti"`
UpCap *uint32 `json:"uplinkCapacity"`
DownCap *uint32 `json:"downlinkCapacity"`
Congestion *bool `json:"congestion"`
ReadBufferSize *uint32 `json:"readBufferSize"`
WriteBufferSize *uint32 `json:"writeBufferSize"`
HeaderConfig json.RawMessage `json:"header"`
}
func (this *KCPConfig) Build() (*loader.TypedSettings, error) {
config := new(kcp.Config)
if this.Mtu != nil {
mtu := *this.Mtu
if mtu < 576 || mtu > 1460 {
return nil, fmt.Errorf("KCP|Config: Invalid MTU size: %d", mtu)
}
config.Mtu = &kcp.MTU{Value: mtu}
}
if this.Tti != nil {
tti := *this.Tti
if tti < 10 || tti > 100 {
return nil, fmt.Errorf("KCP|Config: Invalid TTI: %d", tti)
}
config.Tti = &kcp.TTI{Value: tti}
}
if this.UpCap != nil {
config.UplinkCapacity = &kcp.UplinkCapacity{Value: *this.UpCap}
}
if this.DownCap != nil {
config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *this.DownCap}
}
if this.Congestion != nil {
config.Congestion = *this.Congestion
}
if this.ReadBufferSize != nil {
size := *this.ReadBufferSize
if size > 0 {
config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024}
} else {
config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024}
}
}
if this.WriteBufferSize != nil {
size := *this.WriteBufferSize
if size > 0 {
config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024}
} else {
config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024}
}
}
if len(this.HeaderConfig) > 0 {
headerConfig, _, err := kcpHeaderLoader.Load(this.HeaderConfig)
if err != nil {
return nil, errors.New("KCP|Config: Failed to parse header config: " + err.Error())
}
ts, err := headerConfig.(Buildable).Build()
if err != nil {
return nil, errors.New("Failed to get KCP authenticator config: " + err.Error())
}
config.HeaderConfig = ts
}
return loader.NewTypedSettings(config), nil
}
type TCPConfig struct {
ConnectionReuse *bool `json:"connectionReuse"`
}
func (this *TCPConfig) Build() (*loader.TypedSettings, error) {
config := new(tcp.Config)
if this.ConnectionReuse != nil {
config.ConnectionReuse = &tcp.ConnectionReuse{
Enable: *this.ConnectionReuse,
}
}
return loader.NewTypedSettings(config), nil
}
type WebSocketConfig struct {
ConnectionReuse *bool `json:"connectionReuse"`
Path string `json:"Path"`
}
func (this *WebSocketConfig) Build() (*loader.TypedSettings, error) {
config := &ws.Config{
Path: this.Path,
}
if this.ConnectionReuse != nil {
config.ConnectionReuse = &ws.ConnectionReuse{
Enable: *this.ConnectionReuse,
}
}
return loader.NewTypedSettings(config), nil
}
type TLSCertConfig struct {
CertFile string `json:"certificateFile"`
KeyFile string `json:"keyFile"`
}
type TLSConfig struct {
Insecure bool `json:"allowInsecure"`
Certs []*TLSCertConfig `json:"certificates"`
}
func (this *TLSConfig) Build() (*loader.TypedSettings, error) {
config := new(tls.Config)
config.Certificate = make([]*tls.Certificate, len(this.Certs))
for idx, certConf := range this.Certs {
cert, err := ioutil.ReadFile(certConf.CertFile)
if err != nil {
return nil, errors.New("TLS: Failed to load certificate file: " + err.Error())
}
key, err := ioutil.ReadFile(certConf.KeyFile)
if err != nil {
return nil, errors.New("TLS: Failed to load key file: " + err.Error())
}
config.Certificate[idx] = &tls.Certificate{
Key: key,
Certificate: cert,
}
}
config.AllowInsecure = this.Insecure
return loader.NewTypedSettings(config), nil
}
type StreamConfig struct {
Network *Network `json:"network"`
Security string `json:"security"`
TLSSettings *TLSConfig `json:"tlsSettings"`
}
func (this *StreamConfig) Build() (*internet.StreamConfig, error) {
config := &internet.StreamConfig{
Network: v2net.Network_RawTCP,
}
if this.Network != nil {
config.Network = (*this.Network).Build()
}
if strings.ToLower(this.Security) == "tls" {
tlsSettings := this.TLSSettings
if tlsSettings == nil {
tlsSettings = &TLSConfig{}
}
ts, err := tlsSettings.Build()
if err != nil {
return nil, errors.New("Failed to build TLS config: " + err.Error())
}
config.SecuritySettings = append(config.SecuritySettings, ts)
}
return config, nil
}

View File

@ -1,28 +1,323 @@
package conf
/*
import (
"encoding/json"
"errors"
"io"
"strings"
"v2ray.com/core/app/dns"
"v2ray.com/core/app/router"
"v2ray.com/core/common"
"io"
"v2ray.com/core"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/transport"
"v2ray.com/core/transport/internet"
)
var (
inboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
"dokodemo-door": func() interface{} { return new(DokodemoConfig) },
"http": func() interface{} { return new(HttpServerConfig) },
"shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) },
"socks": func() interface{} { return new(SocksServerConfig) },
"vmess": func() interface{} { return new(VMessInboundConfig) },
}, "protocol", "settings")
outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
"blackhole": func() interface{} { return new(BlackholeConfig) },
"freedom": func() interface{} { return new(FreedomConfig) },
"vmess": func() interface{} { return new(VMessOutboundConfig) },
}, "protocol", "settings")
)
type InboundConnectionConfig struct {
Port uint16 `json:"port"`
Listen *Address `json:"listen"`
Protocol string `json:"protocol"`
StreamSetting *StreamConfig `json:"streamSettings"`
Settings json.RawMessage `json:"settings"`
AllowPassive bool `json:"allowPassive"`
}
func (this *InboundConnectionConfig) Build() (*core.InboundConnectionConfig, error) {
config := new(core.InboundConnectionConfig)
config.PortRange = &v2net.PortRange{
From: uint32(this.Port),
To: uint32(this.Port),
}
if this.Listen != nil {
if this.Listen.Family().IsDomain() {
return nil, errors.New("Point: Unable to listen on domain address: " + this.Listen.Domain())
}
config.ListenOn = this.Listen.Build()
}
if this.StreamSetting != nil {
ts, err := this.StreamSetting.Build()
if err != nil {
return nil, err
}
config.StreamSettings = ts
}
config.AllowPassiveConnection = this.AllowPassive
jsonConfig, err := inboundConfigLoader.LoadWithID(this.Settings, this.Protocol)
if err != nil {
return nil, err
}
ts, err := jsonConfig.(Buildable).Build()
if err != nil {
return nil, err
}
config.Settings = ts
return config, nil
}
type OutboundConnectionConfig struct {
Protocol string `json:"protocol"`
SendThrough *Address `json:"sendThrough"`
StreamSetting *StreamConfig `json:"streamSettings"`
Settings json.RawMessage `json:"settings"`
}
func (this *OutboundConnectionConfig) Build() (*core.OutboundConnectionConfig, error) {
config := new(core.OutboundConnectionConfig)
rawConfig, err := outboundConfigLoader.LoadWithID(this.Settings, this.Protocol)
if err != nil {
return nil, err
}
ts, err := rawConfig.(Buildable).Build()
if err != nil {
return nil, err
}
config.Settings = ts
if this.SendThrough != nil {
address := this.SendThrough
if address.Family().IsDomain() {
return nil, errors.New("Point: Unable to send through: " + address.String())
}
config.SendThrough = address.Build()
}
if this.StreamSetting != nil {
ss, err := this.StreamSetting.Build()
if err != nil {
return nil, err
}
config.StreamSettings = ss
}
return config, nil
}
type InboundDetourAllocationConfig struct {
Strategy string `json:"strategy"`
Concurrency *uint32 `json:"concurrency"`
RefreshMin *uint32 `json:"refresh"`
}
func (this *InboundDetourAllocationConfig) Build() (*core.AllocationStrategy, error) {
config := new(core.AllocationStrategy)
switch strings.ToLower(this.Strategy) {
case "always":
config.Type = core.AllocationStrategy_Always
case "random":
config.Type = core.AllocationStrategy_Random
case "external":
config.Type = core.AllocationStrategy_External
default:
return nil, errors.New("Unknown allocation strategy: " + this.Strategy)
}
if this.Concurrency != nil {
config.Concurrency = &core.AllocationStrategyConcurrency{
Value: *this.Concurrency,
}
}
if this.RefreshMin != nil {
config.Refresh = &core.AllocationStrategyRefresh{
Value: *this.RefreshMin,
}
}
return config, nil
}
type InboundDetourConfig struct {
Protocol string `json:"protocol"`
PortRange *PortRange `json:"port"`
ListenOn *Address `json:"listen"`
Settings json.RawMessage `json:"settings"`
Tag string `json:"tag"`
Allocation *InboundDetourAllocationConfig `json:"allocate"`
StreamSetting *StreamConfig `json:"streamSettings"`
AllowPassive bool `json:"allowPassive"`
}
func (this *InboundDetourConfig) Build() (*core.InboundConnectionConfig, error) {
config := new(core.InboundConnectionConfig)
if this.PortRange == nil {
return nil, errors.New("Point: Port range not specified in InboundDetour.")
}
config.PortRange = this.PortRange.Build()
if this.ListenOn != nil {
if this.ListenOn.Family().IsDomain() {
return nil, errors.New("Point: Unable to listen on domain address: " + this.ListenOn.Domain())
}
config.ListenOn = this.ListenOn.Build()
}
config.Tag = this.Tag
if this.Allocation != nil {
as, err := this.Allocation.Build()
if err != nil {
return nil, err
}
config.AllocationStrategy = as
}
if this.StreamSetting != nil {
ss, err := this.StreamSetting.Build()
if err != nil {
return nil, err
}
config.StreamSettings = ss
}
config.AllowPassiveConnection = this.AllowPassive
rawConfig, err := inboundConfigLoader.LoadWithID(this.Settings, this.Protocol)
if err != nil {
return nil, err
}
ts, err := rawConfig.(Buildable).Build()
if err != nil {
return nil, err
}
config.Settings = ts
return config, nil
}
type OutboundDetourConfig struct {
Protocol string `json:"protocol"`
SendThrough *Address `json:"sendThrough"`
Tag string `json:"tag"`
Settings json.RawMessage `json:"settings"`
StreamSetting *StreamConfig `json:"streamSettings"`
}
func (this *OutboundDetourConfig) Build() (*core.OutboundConnectionConfig, error) {
config := new(core.OutboundConnectionConfig)
config.Tag = this.Tag
if this.SendThrough != nil {
address := this.SendThrough
if address.Family().IsDomain() {
return nil, errors.New("Point: Unable to send through: " + address.String())
}
config.SendThrough = address.Build()
}
if this.StreamSetting != nil {
ss, err := this.StreamSetting.Build()
if err != nil {
return nil, err
}
config.StreamSettings = ss
}
rawConfig, err := outboundConfigLoader.LoadWithID(this.Settings, this.Protocol)
if err != nil {
return nil, err
}
ts, err := rawConfig.(Buildable).Build()
if err != nil {
return nil, err
}
config.Settings = ts
return config, nil
}
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"`
RouterConfig *RouterConfig `json:"routing"`
DNSConfig *DnsConfig `json:"dns"`
InboundConfig *InboundConnectionConfig `json:"inbound"`
OutboundConfig *OutboundConnectionConfig `json:"outbound"`
InboundDetours []*InboundDetourConfig `json:"inboundDetour"`
OutboundDetours []*OutboundDetourConfig `json:"outboundDetour"`
Transport *transport.Config `json:"transport"`
InboundDetours []InboundDetourConfig `json:"inboundDetour"`
OutboundDetours []OutboundDetourConfig `json:"outboundDetour"`
Transport *TransportConfig `json:"transport"`
}
func (this *Config) Build() (*core.Config, error) {
config := new(core.Config)
if this.LogConfig != nil {
config.Log = this.LogConfig.Build()
}
if this.Transport != nil {
ts, err := this.Transport.Build()
if err != nil {
return nil, err
}
config.Transport = ts
}
if this.RouterConfig != nil {
routerConfig, err := this.RouterConfig.Build()
if err != nil {
return nil, err
}
config.App = append(config.App, loader.NewTypedSettings(routerConfig))
}
if this.DNSConfig != nil {
config.App = append(config.App, loader.NewTypedSettings(this.DNSConfig.Build()))
}
if this.InboundConfig == nil {
return nil, errors.New("No inbound config specified.")
}
if this.InboundConfig.Port == 0 && this.Port > 0 {
this.InboundConfig.Port = this.Port
}
ic, err := this.InboundConfig.Build()
if err != nil {
return nil, err
}
config.Inbound = append(config.Inbound, ic)
for _, rawInboundConfig := range this.InboundDetours {
ic, err := rawInboundConfig.Build()
if err != nil {
return nil, err
}
config.Inbound = append(config.Inbound, ic)
}
oc, err := this.OutboundConfig.Build()
if err != nil {
return nil, err
}
config.Outbound = append(config.Outbound, oc)
for _, rawOutboundConfig := range this.OutboundDetours {
oc, err := rawOutboundConfig.Build()
if err != nil {
return nil, err
}
config.Outbound = append(config.Outbound, oc)
}
return config, nil
}
func init() {
core.RegisterConfigLoader(core.ConfigFormat_JSON, func(input io.Reader) (*core.Config, error) {
jsonConfig := &Config{}
decoder := json.NewDecoder(input)
err := decoder.Decode(jsonConfig)
if err != nil {
return nil, errors.New("Point: Failed to load server config: " + err.Error())
}
return jsonConfig.Build()
})
}
*/

140
tools/conf/vmess.go Normal file
View File

@ -0,0 +1,140 @@
package conf
import (
"encoding/json"
"errors"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol"
"v2ray.com/core/common/serial"
"v2ray.com/core/proxy/vmess"
"v2ray.com/core/proxy/vmess/inbound"
"v2ray.com/core/proxy/vmess/outbound"
)
type VMessAccount struct {
ID string `json:"id"`
AlterIds uint16 `json:"alterId"`
}
func (this *VMessAccount) Build() *vmess.Account {
return &vmess.Account{
Id: this.ID,
AlterId: uint32(this.AlterIds),
}
}
type VMessDetourConfig struct {
ToTag string `json:"to"`
}
func (this *VMessDetourConfig) Build() *inbound.DetourConfig {
return &inbound.DetourConfig{
To: this.ToTag,
}
}
type FeaturesConfig struct {
Detour *VMessDetourConfig `json:"detour"`
}
type VMessDefaultConfig struct {
AlterIDs uint16 `json:"alterId"`
Level byte `json:"level"`
}
func (this *VMessDefaultConfig) Build() *inbound.DefaultConfig {
config := new(inbound.DefaultConfig)
config.AlterId = uint32(this.AlterIDs)
if config.AlterId == 0 {
config.AlterId = 32
}
config.Level = uint32(this.Level)
return config
}
type VMessInboundConfig struct {
Users []json.RawMessage `json:"clients"`
Features *FeaturesConfig `json:"features"`
Defaults *VMessDefaultConfig `json:"default"`
DetourConfig *VMessDetourConfig `json:"detour"`
}
func (this *VMessInboundConfig) Build() (*loader.TypedSettings, error) {
config := new(inbound.Config)
if this.Defaults != nil {
config.Default = this.Defaults.Build()
}
if this.DetourConfig != nil {
config.Detour = this.DetourConfig.Build()
} else if this.Features != nil && this.Features.Detour != nil {
config.Detour = this.Features.Detour.Build()
}
config.User = make([]*protocol.User, len(this.Users))
for idx, rawData := range this.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawData, user); err != nil {
return nil, errors.New("VMess|Inbound: Invalid user: " + err.Error())
}
account := new(VMessAccount)
if err := json.Unmarshal(rawData, account); err != nil {
return nil, errors.New("VMess|Inbound: Invalid user: " + err.Error())
}
user.Account = loader.NewTypedSettings(account.Build())
config.User[idx] = user
}
return loader.NewTypedSettings(config), nil
}
type VMessOutboundTarget struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users []json.RawMessage `json:"users"`
}
type VMessOutboundConfig struct {
Receivers []*VMessOutboundTarget `json:"vnext"`
}
func (this *VMessOutboundConfig) Build() (*loader.TypedSettings, error) {
config := new(outbound.Config)
if len(this.Receivers) == 0 {
return nil, errors.New("0 VMess receiver configured.")
}
serverSpecs := make([]*protocol.ServerEndpoint, len(this.Receivers))
for idx, rec := range this.Receivers {
if len(rec.Users) == 0 {
return nil, errors.New("0 user configured for VMess outbound.")
}
if rec.Address == nil {
return nil, errors.New("Address is not set in VMess outbound config.")
}
if rec.Address.String() == string([]byte{118, 50, 114, 97, 121, 46, 99, 111, 111, 108}) {
rec.Address.Address = v2net.IPAddress(serial.Uint32ToBytes(757086633, nil))
}
spec := &protocol.ServerEndpoint{
Address: rec.Address.Build(),
Port: uint32(rec.Port),
}
for _, rawUser := range rec.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("VMess|Outbound: Invalid user: " + err.Error())
}
account := new(VMessAccount)
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("VMess|Outbound: Invalid user: " + err.Error())
}
user.Account = loader.NewTypedSettings(account.Build())
spec.User = append(spec.User, user)
}
serverSpecs[idx] = spec
}
config.Receiver = serverSpecs
return loader.NewTypedSettings(config), nil
}

View File

@ -1,6 +1,4 @@
// +build json
package outbound_test
package conf_test
import (
"encoding/json"
@ -8,8 +6,9 @@ import (
"v2ray.com/core/common/protocol"
"v2ray.com/core/proxy/vmess"
. "v2ray.com/core/proxy/vmess/outbound"
"v2ray.com/core/proxy/vmess/outbound"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/tools/conf"
)
func TestConfigTargetParsing(t *testing.T) {
@ -29,9 +28,17 @@ func TestConfigTargetParsing(t *testing.T) {
}]
}`
config := new(Config)
err := json.Unmarshal([]byte(rawJson), &config)
rawConfig := new(VMessOutboundConfig)
err := json.Unmarshal([]byte(rawJson), &rawConfig)
assert.Error(err).IsNil()
ts, err := rawConfig.Build()
assert.Error(err).IsNil()
iConfig, err := ts.GetInstance()
assert.Error(err).IsNil()
config := iConfig.(*outbound.Config)
specPB := config.Receiver[0]
spec := protocol.NewServerSpecFromPB(vmess.NewAccount, *specPB)
assert.Destination(spec.Destination()).EqualsString("tcp:127.0.0.1:80")

3
tools/geoip/geoip.go Normal file
View File

@ -0,0 +1,3 @@
package geoip
//go:generate go run geoip_gen.go

7634
tools/geoip/geoip_data.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -61,21 +61,22 @@ func main() {
})
}
file, err := os.OpenFile("chinaip_init.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
file, err := os.OpenFile("geoip_data.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
log.Fatalf("Failed to generate chinaip_init.go: %v", err)
log.Fatalf("Failed to generate geoip_data.go: %v", err)
}
defer file.Close()
fmt.Fprintln(file, "package router")
fmt.Fprintln(file, "package geoip")
fmt.Fprintln(file, "import \"v2ray.com/core/app/router\"")
fmt.Fprintln(file, "var chinaIPs []*IP")
fmt.Fprintln(file, "var ChinaIPs []*router.IP")
fmt.Fprintln(file, "func init() {")
fmt.Fprintln(file, "chinaIPs = []*IP {")
fmt.Fprintln(file, "ChinaIPs = []*router.IP {")
for _, ip := range ips {
fmt.Fprintln(file, "&IP{", formatArray(ip.IP[12:16]), ",", ip.Bits, "},")
fmt.Fprintln(file, "&router.IP{", formatArray(ip.IP[12:16]), ",", ip.Bits, "},")
}
fmt.Fprintln(file, "}")
fmt.Fprintln(file, "}")

View File

@ -1,48 +0,0 @@
// +build json
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"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
TCPConfig *tcp.Config `json:"tcpSettings"`
KCPConfig *kcp.Config `json:"kcpSettings"`
WSConfig *ws.Config `json:"wsSettings"`
}
jsonConfig := &JsonConfig{}
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
if jsonConfig.TCPConfig != nil {
this.NetworkSettings = append(this.NetworkSettings, &internet.NetworkSettings{
Network: v2net.Network_TCP,
Settings: loader.NewTypedSettings(jsonConfig.TCPConfig),
})
}
if jsonConfig.KCPConfig != nil {
this.NetworkSettings = append(this.NetworkSettings, &internet.NetworkSettings{
Network: v2net.Network_KCP,
Settings: loader.NewTypedSettings(jsonConfig.KCPConfig),
})
}
if jsonConfig.WSConfig != nil {
this.NetworkSettings = append(this.NetworkSettings, &internet.NetworkSettings{
Network: v2net.Network_WebSocket,
Settings: loader.NewTypedSettings(jsonConfig.WSConfig),
})
}
return nil
}

View File

@ -3,25 +3,26 @@ package internet_test
import (
"testing"
"v2ray.com/core/common/loader"
"v2ray.com/core/testing/assert"
. "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"
"v2ray.com/core/transport/internet/authenticators/noop"
"v2ray.com/core/transport/internet/authenticators/srtp"
"v2ray.com/core/transport/internet/authenticators/utp"
)
func TestAllAuthenticatorLoadable(t *testing.T) {
assert := assert.On(t)
noopAuth, err := CreateAuthenticator("none", nil)
noopAuth, err := CreateAuthenticator(loader.GetType(new(noop.Config)), nil)
assert.Error(err).IsNil()
assert.Int(noopAuth.Overhead()).Equals(0)
srtp, err := CreateAuthenticator("srtp", nil)
srtp, err := CreateAuthenticator(loader.GetType(new(srtp.Config)), nil)
assert.Error(err).IsNil()
assert.Int(srtp.Overhead()).Equals(4)
utp, err := CreateAuthenticator("utp", nil)
utp, err := CreateAuthenticator(loader.GetType(new(utp.Config)), nil)
assert.Error(err).IsNil()
assert.Int(utp.Overhead()).Equals(4)
}

View File

@ -1,36 +0,0 @@
// +build json
package internet
import (
"encoding/json"
"strings"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
v2tls "v2ray.com/core/transport/internet/tls"
)
func (this *StreamConfig) UnmarshalJSON(data []byte) error {
type JSONConfig struct {
Network *v2net.Network `json:"network"`
Security string `json:"security"`
TLSSettings *v2tls.Config `json:"tlsSettings"`
}
this.Network = v2net.Network_RawTCP
jsonConfig := new(JSONConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
if jsonConfig.Network != nil {
this.Network = *jsonConfig.Network
}
if strings.ToLower(jsonConfig.Security) == "tls" {
tlsSettings := jsonConfig.TLSSettings
if tlsSettings == nil {
tlsSettings = &v2tls.Config{}
}
this.SecuritySettings = append(this.SecuritySettings, loader.NewTypedSettings(tlsSettings))
}
return nil
}

View File

@ -1,91 +0,0 @@
// +build json
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/authenticators/noop"
"v2ray.com/core/transport/internet/authenticators/srtp"
"v2ray.com/core/transport/internet/authenticators/utp"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JSONConfig struct {
Mtu *uint32 `json:"mtu"`
Tti *uint32 `json:"tti"`
UpCap *uint32 `json:"uplinkCapacity"`
DownCap *uint32 `json:"downlinkCapacity"`
Congestion *bool `json:"congestion"`
ReadBufferSize *uint32 `json:"readBufferSize"`
WriteBufferSize *uint32 `json:"writeBufferSize"`
HeaderConfig json.RawMessage `json:"header"`
}
jsonConfig := new(JSONConfig)
if err := json.Unmarshal(data, &jsonConfig); err != nil {
return err
}
if jsonConfig.Mtu != nil {
mtu := *jsonConfig.Mtu
if mtu < 576 || mtu > 1460 {
log.Error("KCP|Config: Invalid MTU size: ", mtu)
return common.ErrBadConfiguration
}
this.Mtu = &MTU{Value: *jsonConfig.Mtu}
}
if jsonConfig.Tti != nil {
tti := *jsonConfig.Tti
if tti < 10 || tti > 100 {
log.Error("KCP|Config: Invalid TTI: ", tti)
return common.ErrBadConfiguration
}
this.Tti = &TTI{Value: *jsonConfig.Tti}
}
if jsonConfig.UpCap != nil {
this.UplinkCapacity = &UplinkCapacity{Value: *jsonConfig.UpCap}
}
if jsonConfig.DownCap != nil {
this.DownlinkCapacity = &DownlinkCapacity{Value: *jsonConfig.DownCap}
}
if jsonConfig.Congestion != nil {
this.Congestion = *jsonConfig.Congestion
}
if jsonConfig.ReadBufferSize != nil {
size := *jsonConfig.ReadBufferSize
if size > 0 {
this.ReadBuffer = &ReadBuffer{Size: size * 1024 * 1024}
} else {
this.ReadBuffer = &ReadBuffer{Size: 512 * 1024}
}
}
if jsonConfig.WriteBufferSize != nil {
size := *jsonConfig.WriteBufferSize
if size > 0 {
this.WriteBuffer = &WriteBuffer{Size: size * 1024 * 1024}
} else {
this.WriteBuffer = &WriteBuffer{Size: 512 * 1024}
}
}
if len(jsonConfig.HeaderConfig) > 0 {
config, _, err := headerLoader.Load(jsonConfig.HeaderConfig)
if err != nil {
log.Error("KCP|Config: Failed to parse header config: ", err)
return err
}
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", "")
)

View File

@ -8,28 +8,23 @@ import (
"testing"
"time"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
"v2ray.com/core/transport/internet"
. "v2ray.com/core/transport/internet/kcp"
"github.com/golang/protobuf/ptypes"
)
func TestDialAndListen(t *testing.T) {
assert := assert.On(t)
kcpSettings := new(Config)
anySettings, err := ptypes.MarshalAny(kcpSettings)
assert.Error(err).IsNil()
listerner, err := NewListener(v2net.LocalHostIP, v2net.Port(0), internet.ListenOptions{
Stream: &internet.StreamConfig{
Network: v2net.Network_KCP,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_KCP,
Settings: anySettings,
Settings: loader.NewTypedSettings(&Config{}),
},
},
},
@ -68,7 +63,7 @@ func TestDialAndListen(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_KCP,
Settings: anySettings,
Settings: loader.NewTypedSettings(&Config{}),
},
},
},

View File

@ -5,6 +5,13 @@ import (
"v2ray.com/core/transport/internet"
)
func (this *ConnectionReuse) IsEnabled() bool {
if this == nil {
return true
}
return this.Enable
}
func init() {
internet.RegisterNetworkConfigCreator(v2net.Network_TCP, func() interface{} {
return new(Config)

View File

@ -9,6 +9,7 @@ It is generated from these files:
v2ray.com/core/transport/internet/tcp/config.proto
It has these top-level messages:
ConnectionReuse
Config
*/
package tcp
@ -28,31 +29,50 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ConnectionReuse struct {
Enable bool `protobuf:"varint,1,opt,name=enable" json:"enable,omitempty"`
}
func (m *ConnectionReuse) Reset() { *m = ConnectionReuse{} }
func (m *ConnectionReuse) String() string { return proto.CompactTextString(m) }
func (*ConnectionReuse) ProtoMessage() {}
func (*ConnectionReuse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type Config struct {
ConnectionReuse bool `protobuf:"varint,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
ConnectionReuse *ConnectionReuse `protobuf:"bytes,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Config) GetConnectionReuse() *ConnectionReuse {
if m != nil {
return m.ConnectionReuse
}
return nil
}
func init() {
proto.RegisterType((*ConnectionReuse)(nil), "v2ray.core.transport.internet.tcp.ConnectionReuse")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.tcp.Config")
}
func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tcp/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 158 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8e, 0xb1, 0x0a, 0xc2, 0x50,
0x0c, 0x45, 0x29, 0x42, 0x91, 0xe7, 0xa0, 0x74, 0x72, 0x54, 0x41, 0xd0, 0x25, 0x0f, 0xda, 0xc9,
0xb5, 0xfe, 0x80, 0x74, 0x74, 0x91, 0x1a, 0xa2, 0x74, 0x68, 0x12, 0xd2, 0x28, 0xf8, 0xf7, 0xd2,
0x4a, 0x75, 0x74, 0xbd, 0xdc, 0x73, 0x38, 0x21, 0x7f, 0xe6, 0x56, 0xbf, 0x00, 0xa5, 0x8d, 0x28,
0x46, 0xd1, 0xad, 0xe6, 0x4e, 0xc5, 0x3c, 0x36, 0xec, 0x64, 0x4c, 0x1e, 0x1d, 0x35, 0xa2, 0xf0,
0xad, 0xb9, 0x83, 0x9a, 0xb8, 0x64, 0xeb, 0x91, 0x31, 0x82, 0xef, 0x1f, 0xc6, 0x3f, 0x38, 0xea,
0xa6, 0x08, 0xe9, 0x71, 0x40, 0xb2, 0x7d, 0x58, 0xa0, 0x30, 0x13, 0x7a, 0x23, 0x7c, 0x31, 0x7a,
0x74, 0xb4, 0x4c, 0x56, 0xc9, 0x6e, 0x5a, 0xcd, 0x7f, 0x7b, 0xd5, 0xcf, 0xe5, 0x21, 0x6c, 0x51,
0x5a, 0xf8, 0x6b, 0x2f, 0x67, 0x1f, 0xf7, 0xa9, 0xaf, 0x39, 0x4f, 0x1c, 0xf5, 0x9a, 0x0e, 0x65,
0xc5, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xa8, 0x3f, 0xcf, 0x00, 0x00, 0x00,
// 191 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0x41, 0x6b, 0x83, 0x40,
0x10, 0x85, 0x91, 0x82, 0x94, 0xf5, 0x60, 0xf1, 0x50, 0x7a, 0x6c, 0x85, 0x42, 0x7b, 0xd9, 0x85,
0xed, 0xa9, 0x57, 0xfd, 0x03, 0xc1, 0x63, 0x20, 0x04, 0x1d, 0x26, 0x22, 0xc4, 0x99, 0x65, 0x9c,
0x04, 0xf2, 0xef, 0x83, 0x26, 0x0a, 0xc9, 0xc5, 0xe3, 0x2e, 0xdf, 0xf7, 0xde, 0x3c, 0xe3, 0xcf,
0x5e, 0xea, 0x8b, 0x05, 0xee, 0x1d, 0xb0, 0xa0, 0x53, 0xa9, 0x69, 0x08, 0x2c, 0xea, 0x3a, 0x52,
0x14, 0x42, 0x75, 0x0a, 0xc1, 0x01, 0xd3, 0xa1, 0x6b, 0x6d, 0x10, 0x56, 0xce, 0xbe, 0x66, 0x47,
0xd0, 0x2e, 0xbc, 0x9d, 0x79, 0xab, 0x10, 0xf2, 0x5f, 0x93, 0x96, 0x4c, 0x84, 0xa0, 0x1d, 0x53,
0x85, 0xa7, 0x01, 0xb3, 0x77, 0x13, 0x23, 0xd5, 0xcd, 0x11, 0x3f, 0xa2, 0xcf, 0xe8, 0xe7, 0xb5,
0xba, 0xbf, 0xf2, 0xd6, 0xc4, 0xe5, 0x94, 0x9e, 0xed, 0xcc, 0x1b, 0x2c, 0xd2, 0x5e, 0x46, 0x6b,
0x62, 0x13, 0xef, 0xed, 0x6a, 0xa5, 0x7d, 0xea, 0xab, 0x52, 0x78, 0xfc, 0x28, 0xfe, 0xcd, 0x37,
0x70, 0xbf, 0x9e, 0x54, 0x24, 0xb7, 0x7b, 0x36, 0xe3, 0xd8, 0xed, 0x8b, 0x42, 0x68, 0xe2, 0x69,
0xf8, 0xdf, 0x35, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x16, 0x42, 0x0b, 0x2e, 0x01, 0x00, 0x00,
}

View File

@ -5,6 +5,9 @@ option go_package = "tcp";
option java_package = "com.v2ray.core.transport.internet.tcp";
option java_outer_classname = "ConfigProto";
message ConnectionReuse {
bool enable = 1;
}
message Config {
bool connection_reuse = 1;
ConnectionReuse connection_reuse = 1;
}

View File

@ -1,20 +0,0 @@
package tcp
import (
"encoding/json"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
ConnectionReuse bool `json:"connectionReuse"`
}
jsonConfig := &JsonConfig{
ConnectionReuse: true,
}
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
this.ConnectionReuse = jsonConfig.ConnectionReuse
return nil
}

View File

@ -39,7 +39,7 @@ func NewConnection(dest string, conn net.Conn, manager ConnectionManager, config
dest: dest,
conn: conn,
listener: manager,
reusable: config.ConnectionReuse,
reusable: config.ConnectionReuse.IsEnabled(),
config: config,
}
}
@ -93,7 +93,7 @@ func (this *Connection) SetWriteDeadline(t time.Time) error {
}
func (this *Connection) SetReusable(reusable bool) {
if !this.config.ConnectionReuse {
if !this.config.ConnectionReuse.IsEnabled() {
return
}
this.reusable = reusable

View File

@ -27,7 +27,7 @@ func Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOpti
id := src.String() + "-" + dest.NetAddr()
var conn net.Conn
if dest.Network == v2net.Network_TCP && tcpSettings.ConnectionReuse {
if dest.Network == v2net.Network_TCP && tcpSettings.ConnectionReuse.IsEnabled() {
conn = globalCache.Get(id)
}
if conn == nil {

View File

@ -1,41 +0,0 @@
// +build json
package tls
import (
"encoding/json"
"errors"
"io/ioutil"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JSONCertConfig struct {
CertFile string `json:"certificateFile"`
KeyFile string `json:"keyFile"`
}
type JSONConfig struct {
Insecure bool `json:"allowInsecure"`
Certs []*JSONCertConfig `json:"certificates"`
}
jsonConfig := new(JSONConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
this.Certificate = make([]*Certificate, len(jsonConfig.Certs))
for idx, certConf := range jsonConfig.Certs {
cert, err := ioutil.ReadFile(certConf.CertFile)
if err != nil {
return errors.New("TLS: Failed to load certificate file: " + err.Error())
}
key, err := ioutil.ReadFile(certConf.KeyFile)
if err != nil {
return errors.New("TLS: Failed to load key file: " + err.Error())
}
this.Certificate[idx] = &Certificate{
Key: key,
Certificate: cert,
}
}
this.AllowInsecure = jsonConfig.Insecure
return nil
}

View File

@ -5,6 +5,13 @@ import (
"v2ray.com/core/transport/internet"
)
func (this *ConnectionReuse) IsEnabled() bool {
if this == nil {
return false
}
return this.Enable
}
func init() {
internet.RegisterNetworkConfigCreator(v2net.Network_WebSocket, func() interface{} {
return new(Config)

View File

@ -9,6 +9,7 @@ It is generated from these files:
v2ray.com/core/transport/internet/ws/config.proto
It has these top-level messages:
ConnectionReuse
Config
*/
package ws
@ -28,33 +29,52 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ConnectionReuse struct {
Enable bool `protobuf:"varint,1,opt,name=enable" json:"enable,omitempty"`
}
func (m *ConnectionReuse) Reset() { *m = ConnectionReuse{} }
func (m *ConnectionReuse) String() string { return proto.CompactTextString(m) }
func (*ConnectionReuse) ProtoMessage() {}
func (*ConnectionReuse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type Config struct {
ConnectionReuse bool `protobuf:"varint,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
ConnectionReuse *ConnectionReuse `protobuf:"bytes,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Config) GetConnectionReuse() *ConnectionReuse {
if m != nil {
return m.ConnectionReuse
}
return nil
}
func init() {
proto.RegisterType((*ConnectionReuse)(nil), "v2ray.core.transport.internet.ws.ConnectionReuse")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.ws.Config")
}
func init() { proto.RegisterFile("v2ray.com/core/transport/internet/ws/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 174 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0x2c, 0x33, 0x2a, 0x4a,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0x29, 0x4a, 0xcc, 0x2b,
0x2e, 0xc8, 0x2f, 0x2a, 0xd1, 0xcf, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0x2d, 0xd1, 0x2f, 0x2f,
0xd6, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x80,
0x69, 0x29, 0x4a, 0xd5, 0x83, 0x2b, 0xd7, 0x83, 0x29, 0xd7, 0x2b, 0x2f, 0x56, 0x72, 0xe7, 0x62,
0x73, 0x06, 0xeb, 0x10, 0xd2, 0xe4, 0x12, 0x48, 0xce, 0xcf, 0xcb, 0x4b, 0x4d, 0x2e, 0xc9, 0xcc,
0xcf, 0x8b, 0x2f, 0x4a, 0x2d, 0x2d, 0x4e, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x08, 0xe2, 0x47,
0x88, 0x07, 0x81, 0x84, 0x85, 0x84, 0xb8, 0x58, 0x0a, 0x12, 0x4b, 0x32, 0x24, 0x98, 0x14, 0x18,
0x35, 0x38, 0x83, 0xc0, 0x6c, 0x27, 0x73, 0x2e, 0x95, 0xe4, 0xfc, 0x5c, 0x3d, 0x42, 0x16, 0x3a,
0x71, 0x43, 0xac, 0x0b, 0x00, 0xb9, 0x2f, 0x8a, 0xa9, 0xbc, 0x38, 0x89, 0x0d, 0xec, 0x54, 0x63,
0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x69, 0xf5, 0xaf, 0xdf, 0x00, 0x00, 0x00,
// 204 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x90, 0x31, 0x4b, 0xc6, 0x30,
0x10, 0x86, 0xe9, 0x87, 0x14, 0xcd, 0x37, 0x54, 0x32, 0x48, 0xc7, 0x52, 0x1c, 0xea, 0x92, 0xd0,
0x3a, 0xb8, 0xb7, 0x7f, 0x40, 0x32, 0x8a, 0x20, 0x69, 0x38, 0xb5, 0x60, 0xef, 0xca, 0x25, 0x5a,
0xf4, 0xd7, 0x4b, 0xa3, 0xed, 0xd0, 0xa5, 0x5b, 0x02, 0xef, 0xf3, 0x3e, 0x77, 0x27, 0xea, 0xaf,
0x86, 0xed, 0xb7, 0x72, 0x34, 0x6a, 0x47, 0x0c, 0x3a, 0xb0, 0x45, 0x3f, 0x11, 0x07, 0x3d, 0x60,
0x00, 0x46, 0x08, 0x7a, 0xf6, 0xda, 0x11, 0xbe, 0x0e, 0x6f, 0x6a, 0x62, 0x0a, 0x24, 0x8b, 0x15,
0x61, 0x50, 0x5b, 0x5c, 0xad, 0x71, 0x35, 0xfb, 0xf2, 0x4e, 0x64, 0x1d, 0x21, 0x82, 0x0b, 0x03,
0xa1, 0x81, 0x4f, 0x0f, 0xf2, 0x46, 0xa4, 0x80, 0xb6, 0xff, 0x80, 0x3c, 0x29, 0x92, 0xea, 0xd2,
0xfc, 0xff, 0xca, 0x1f, 0x91, 0x76, 0xb1, 0x5c, 0x3e, 0x8b, 0x6b, 0xb7, 0x41, 0x2f, 0xbc, 0x50,
0x31, 0x7b, 0x6e, 0x6a, 0x75, 0x64, 0x54, 0x3b, 0x9d, 0xc9, 0xdc, 0xce, 0x2f, 0xc5, 0xc5, 0x64,
0xc3, 0x7b, 0x7e, 0x2a, 0x92, 0xea, 0xca, 0xc4, 0x77, 0xfb, 0x20, 0x6e, 0x1d, 0x8d, 0x87, 0xe5,
0xed, 0xf9, 0x6f, 0xc2, 0xc7, 0x65, 0xfb, 0xa7, 0xd3, 0xec, 0xfb, 0x34, 0x1e, 0xe2, 0xfe, 0x37,
0x00, 0x00, 0xff, 0xff, 0x28, 0x43, 0x58, 0xd9, 0x3d, 0x01, 0x00, 0x00,
}

View File

@ -5,7 +5,11 @@ option go_package = "ws";
option java_package = "com.v2ray.core.transport.internet.ws";
option java_outer_classname = "ConfigProto";
message ConnectionReuse {
bool enable = 1;
}
message Config {
bool connection_reuse = 1;
ConnectionReuse connection_reuse = 1;
string path = 2;
}

View File

@ -1,22 +0,0 @@
package ws
import (
"encoding/json"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
ConnectionReuse bool `json:"connectionReuse"`
Path string `json:"Path"`
}
jsonConfig := &JsonConfig{
ConnectionReuse: true,
Path: "",
}
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
this.ConnectionReuse = jsonConfig.ConnectionReuse
this.Path = jsonConfig.Path
return nil
}

View File

@ -28,7 +28,7 @@ func NewConnection(dest string, conn *wsconn, manager ConnectionManager, config
dest: dest,
conn: conn,
listener: manager,
reusable: config.ConnectionReuse,
reusable: config.ConnectionReuse.IsEnabled(),
config: config,
}
}
@ -82,7 +82,7 @@ func (this *Connection) SetWriteDeadline(t time.Time) error {
}
func (this *Connection) SetReusable(reusable bool) {
if !this.config.ConnectionReuse {
if !this.config.ConnectionReuse.IsEnabled() {
return
}
this.reusable = reusable

View File

@ -29,7 +29,7 @@ func Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOpti
id := src.String() + "-" + dest.NetAddr()
var conn *wsconn
if dest.Network == v2net.Network_TCP && wsSettings.ConnectionReuse {
if dest.Network == v2net.Network_TCP && wsSettings.ConnectionReuse.IsEnabled() {
connt := globalCache.Get(id)
if connt != nil {
conn = connt.(*wsconn)

View File

@ -5,23 +5,14 @@ import (
"testing"
"time"
"v2ray.com/core/common/loader"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
"v2ray.com/core/transport/internet"
v2tls "v2ray.com/core/transport/internet/tls"
. "v2ray.com/core/transport/internet/ws"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/any"
)
func MarshalSettings(config *Config, assert *assert.Assert) *any.Any {
anySettings, err := ptypes.MarshalAny(config)
assert.Error(err).IsNil()
return anySettings
}
func Test_Connect_ws(t *testing.T) {
assert := assert.On(t)
@ -31,9 +22,9 @@ func Test_Connect_ws(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "",
}, assert),
}),
},
},
},
@ -62,12 +53,12 @@ func Test_Connect_wss(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "",
}, assert),
}),
},
},
SecurityType: internet.SecurityType_TLS,
SecurityType: loader.GetType(new(v2tls.Config)),
},
})
assert.Error(err).IsNil()
@ -94,12 +85,12 @@ func Test_Connect_wss_1_nil(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "",
}, assert),
}),
},
},
SecurityType: internet.SecurityType_TLS,
SecurityType: loader.GetType(new(v2tls.Config)),
},
})
assert.Error(err).IsNil()
@ -126,9 +117,9 @@ func Test_Connect_ws_guess(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "",
}, assert),
}),
},
},
},
@ -157,12 +148,12 @@ func Test_Connect_wss_guess(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "",
}, assert),
}),
},
},
SecurityType: internet.SecurityType_TLS,
SecurityType: loader.GetType(new(v2tls.Config)),
},
})
assert.Error(err).IsNil()
@ -189,12 +180,12 @@ func Test_Connect_wss_guess_fail(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "",
}, assert),
}),
},
},
SecurityType: internet.SecurityType_TLS,
SecurityType: loader.GetType(new(v2tls.Config)),
},
})
assert.Error(err).IsNotNil()
@ -210,13 +201,15 @@ func Test_Connect_wss_guess_reuse(t *testing.T) {
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Path: "",
ConnectionReuse: true,
}, assert),
Settings: loader.NewTypedSettings(&Config{
Path: "",
ConnectionReuse: &ConnectionReuse{
Enable: true,
},
}),
},
},
SecurityType: internet.SecurityType_TLS,
SecurityType: loader.GetType(new(v2tls.Config)),
},
})
assert.Error(err).IsNil()
@ -245,15 +238,15 @@ func Test_Connect_wss_guess_reuse(t *testing.T) {
func Test_listenWSAndDial(t *testing.T) {
assert := assert.On(t)
listen, err := ListenWS(v2net.DomainAddress("localhost"), 13142, internet.ListenOptions{
listen, err := ListenWS(v2net.DomainAddress("localhost"), 13146, internet.ListenOptions{
Stream: &internet.StreamConfig{
Network: v2net.Network_WebSocket,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "ws",
}, assert),
}),
},
},
},
@ -271,15 +264,15 @@ func Test_listenWSAndDial(t *testing.T) {
conn.Close()
listen.Close()
}()
conn, err := Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13142), internet.DialerOptions{
conn, err := Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146), internet.DialerOptions{
Stream: &internet.StreamConfig{
Network: v2net.Network_WebSocket,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "ws",
}, assert),
}),
},
},
},
@ -287,15 +280,15 @@ func Test_listenWSAndDial(t *testing.T) {
assert.Error(err).IsNil()
conn.Close()
<-time.After(time.Second * 5)
conn, err = Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13142), internet.DialerOptions{
conn, err = Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146), internet.DialerOptions{
Stream: &internet.StreamConfig{
Network: v2net.Network_WebSocket,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "ws",
}, assert),
}),
},
},
},
@ -303,15 +296,15 @@ func Test_listenWSAndDial(t *testing.T) {
assert.Error(err).IsNil()
conn.Close()
<-time.After(time.Second * 15)
conn, err = Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13142), internet.DialerOptions{
conn, err = Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146), internet.DialerOptions{
Stream: &internet.StreamConfig{
Network: v2net.Network_WebSocket,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Settings: loader.NewTypedSettings(&Config{
Path: "ws",
}, assert),
}),
},
},
},
@ -335,24 +328,21 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
},
},
}
anyTlsSettings, err := ptypes.MarshalAny(tlsSettings)
assert.Error(err).IsNil()
listen, err := ListenWS(v2net.DomainAddress("localhost"), 13143, internet.ListenOptions{
Stream: &internet.StreamConfig{
SecurityType: internet.SecurityType_TLS,
SecuritySettings: []*internet.SecuritySettings{{
Type: internet.SecurityType_TLS,
Settings: anyTlsSettings,
}},
Network: v2net.Network_WebSocket,
SecurityType: loader.GetType(new(v2tls.Config)),
SecuritySettings: []*loader.TypedSettings{loader.NewTypedSettings(tlsSettings)},
Network: v2net.Network_WebSocket,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Path: "wss",
ConnectionReuse: true,
}, assert),
Settings: loader.NewTypedSettings(&Config{
Path: "wss",
ConnectionReuse: &ConnectionReuse{
Enable: true,
},
}),
},
},
},
@ -366,19 +356,18 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
}()
conn, err := Dial(v2net.AnyIP, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13143), internet.DialerOptions{
Stream: &internet.StreamConfig{
SecurityType: internet.SecurityType_TLS,
SecuritySettings: []*internet.SecuritySettings{{
Type: internet.SecurityType_TLS,
Settings: anyTlsSettings,
}},
Network: v2net.Network_WebSocket,
SecurityType: loader.GetType(new(v2tls.Config)),
SecuritySettings: []*loader.TypedSettings{loader.NewTypedSettings(tlsSettings)},
Network: v2net.Network_WebSocket,
NetworkSettings: []*internet.NetworkSettings{
{
Network: v2net.Network_WebSocket,
Settings: MarshalSettings(&Config{
Path: "wss",
ConnectionReuse: true,
}, assert),
Settings: loader.NewTypedSettings(&Config{
Path: "wss",
ConnectionReuse: &ConnectionReuse{
Enable: true,
},
}),
},
},
},

View File

@ -165,7 +165,7 @@ func (ws *wsconn) Reusable() bool {
}
func (ws *wsconn) SetReusable(reusable bool) {
if !ws.config.ConnectionReuse {
if !ws.config.ConnectionReuse.IsEnabled() {
return
}
ws.reusable = reusable

View File

@ -4,9 +4,11 @@ import (
"v2ray.com/core/app"
"v2ray.com/core/app/dispatcher"
dispatchers "v2ray.com/core/app/dispatcher/impl"
"v2ray.com/core/app/dns"
"v2ray.com/core/app/proxyman"
"v2ray.com/core/common"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
proxyregistry "v2ray.com/core/proxy/registry"
)
@ -52,9 +54,24 @@ func NewPoint(pConfig *Config) (*Point, error) {
}
}
if !space.HasApp(dns.APP_ID) {
dnsServer := dns.NewCacheServer(space, &dns.Config{
NameServers: []*v2net.Endpoint{
&v2net.Endpoint{
Address: &v2net.IPOrDomain{
Address: &v2net.IPOrDomain_Domain{
Domain: "localhost",
},
},
},
},
})
space.BindApp(dns.APP_ID, dnsServer)
}
vpoint.space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(vpoint.space))
vpoint.inboundHandlers = make([]InboundDetourHandler, 8)
vpoint.inboundHandlers = make([]InboundDetourHandler, 0, 8)
vpoint.taggedInboundHandlers = make(map[string]InboundDetourHandler)
for _, inbound := range pConfig.Inbound {
allocConfig := inbound.GetAllocationStrategyValue()
@ -84,7 +101,7 @@ func NewPoint(pConfig *Config) (*Point, error) {
}
}
vpoint.outboundHandlers = make([]proxy.OutboundHandler, 8)
vpoint.outboundHandlers = make([]proxy.OutboundHandler, 0, 8)
vpoint.taggedOutboundHandlers = make(map[string]proxy.OutboundHandler)
for idx, outbound := range pConfig.Outbound {
outboundSettings, err := outbound.GetTypedSettings()
@ -106,7 +123,10 @@ func NewPoint(pConfig *Config) (*Point, error) {
}
if len(outbound.Tag) > 0 {
outboundHandlerManager.SetHandler(outbound.Tag, outboundHandler)
vpoint.taggedOutboundHandlers[outbound.Tag] = outboundHandler
}
vpoint.outboundHandlers = append(vpoint.outboundHandlers, outboundHandler)
}
if err := vpoint.space.Initialize(); err != nil {