diff --git a/proxy/blackhole/config.go b/proxy/blackhole/config.go index a4f116005..e16ce9b4d 100644 --- a/proxy/blackhole/config.go +++ b/proxy/blackhole/config.go @@ -1,4 +1,4 @@ package blackhole -type Config interface { +type Config struct { } diff --git a/proxy/blackhole/config_json.go b/proxy/blackhole/config_json.go new file mode 100644 index 000000000..92d3bc827 --- /dev/null +++ b/proxy/blackhole/config_json.go @@ -0,0 +1,14 @@ +// +build json + +package blackhole + +import ( + "github.com/v2ray/v2ray-core/proxy/internal/config" +) + +func init() { + config.RegisterOutboundConnectionConfig("blackhole", + func(data []byte) (interface{}, error) { + return new(Config), nil + }) +} diff --git a/proxy/blackhole/json/json.go b/proxy/blackhole/json/json.go deleted file mode 100644 index 4d42e29db..000000000 --- a/proxy/blackhole/json/json.go +++ /dev/null @@ -1,15 +0,0 @@ -package json - -import ( - "github.com/v2ray/v2ray-core/proxy/internal/config" - "github.com/v2ray/v2ray-core/proxy/internal/config/json" -) - -type BlackHoleConfig struct { -} - -func init() { - config.RegisterOutboundConnectionConfig("blackhole", json.JsonConfigLoader(func() interface{} { - return new(BlackHoleConfig) - })) -} diff --git a/proxy/dokodemo/config.go b/proxy/dokodemo/config.go index f9ea64c4b..4416d71b1 100644 --- a/proxy/dokodemo/config.go +++ b/proxy/dokodemo/config.go @@ -4,9 +4,9 @@ import ( v2net "github.com/v2ray/v2ray-core/common/net" ) -type Config interface { - Address() v2net.Address - Port() v2net.Port - Network() v2net.NetworkList - Timeout() int +type Config struct { + Address v2net.Address + Port v2net.Port + Network v2net.NetworkList + Timeout int } diff --git a/proxy/dokodemo/config_json.go b/proxy/dokodemo/config_json.go new file mode 100644 index 000000000..9c2d868d4 --- /dev/null +++ b/proxy/dokodemo/config_json.go @@ -0,0 +1,33 @@ +// +build json + +package dokodemo + +import ( + "encoding/json" + + v2net "github.com/v2ray/v2ray-core/common/net" + v2netjson "github.com/v2ray/v2ray-core/common/net/json" + "github.com/v2ray/v2ray-core/proxy/internal/config" +) + +func init() { + config.RegisterInboundConnectionConfig("dokodemo-door", + func(data []byte) (interface{}, error) { + type DokodemoConfig struct { + Host *v2netjson.Host `json:"address"` + PortValue v2net.Port `json:"port"` + NetworkList *v2netjson.NetworkList `json:"network"` + TimeoutValue int `json:"timeout"` + } + rawConfig := new(DokodemoConfig) + if err := json.Unmarshal(data, rawConfig); err != nil { + return nil, err + } + return &Config{ + Address: rawConfig.Host.Address(), + Port: rawConfig.PortValue, + Network: rawConfig.NetworkList, + Timeout: rawConfig.TimeoutValue, + }, nil + }) +} diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index d61781381..e7a2cf57c 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -15,7 +15,7 @@ import ( type DokodemoDoor struct { tcpMutex sync.RWMutex udpMutex sync.RWMutex - config Config + config *Config accepting bool address v2net.Address port v2net.Port @@ -24,12 +24,12 @@ type DokodemoDoor struct { udpConn *net.UDPConn } -func NewDokodemoDoor(space app.Space, config Config) *DokodemoDoor { +func NewDokodemoDoor(space app.Space, config *Config) *DokodemoDoor { return &DokodemoDoor{ config: config, space: space, - address: config.Address(), - port: config.Port(), + address: config.Address, + port: config.Port, } } @@ -52,13 +52,13 @@ func (this *DokodemoDoor) Close() { func (this *DokodemoDoor) Listen(port v2net.Port) error { this.accepting = true - if this.config.Network().HasNetwork(v2net.TCPNetwork) { + if this.config.Network.HasNetwork(v2net.TCPNetwork) { err := this.ListenTCP(port) if err != nil { return err } } - if this.config.Network().HasNetwork(v2net.UDPNetwork) { + if this.config.Network.HasNetwork(v2net.UDPNetwork) { err := this.ListenUDP(port) if err != nil { return err @@ -163,7 +163,7 @@ func (this *DokodemoDoor) HandleTCPConnection(conn *net.TCPConn) { inputFinish.Lock() outputFinish.Lock() - reader := v2net.NewTimeOutReader(this.config.Timeout(), conn) + reader := v2net.NewTimeOutReader(this.config.Timeout, conn) go dumpInput(reader, ray.InboundInput(), &inputFinish) go dumpOutput(conn, ray.InboundOutput(), &outputFinish) diff --git a/proxy/dokodemo/dokodemo_factory.go b/proxy/dokodemo/dokodemo_factory.go index da9572f68..19ac79544 100644 --- a/proxy/dokodemo/dokodemo_factory.go +++ b/proxy/dokodemo/dokodemo_factory.go @@ -9,7 +9,7 @@ import ( func init() { internal.MustRegisterInboundConnectionHandlerCreator("dokodemo-door", func(space app.Space, rawConfig interface{}) (proxy.InboundConnectionHandler, error) { - config := rawConfig.(Config) + config := rawConfig.(*Config) return NewDokodemoDoor(space, config), nil }) } diff --git a/proxy/dokodemo/dokodemo_test.go b/proxy/dokodemo/dokodemo_test.go index ad17bde00..c286bf4b6 100644 --- a/proxy/dokodemo/dokodemo_test.go +++ b/proxy/dokodemo/dokodemo_test.go @@ -1,11 +1,10 @@ -package dokodemo +package dokodemo_test import ( "net" "testing" v2nettesting "github.com/v2ray/v2ray-core/common/net/testing" - _ "github.com/v2ray/v2ray-core/proxy/dokodemo/json" _ "github.com/v2ray/v2ray-core/proxy/freedom" "github.com/v2ray/v2ray-core/shell/point" "github.com/v2ray/v2ray-core/shell/point/testing/mocks" diff --git a/proxy/dokodemo/json/json.go b/proxy/dokodemo/json/json.go deleted file mode 100644 index 928a19343..000000000 --- a/proxy/dokodemo/json/json.go +++ /dev/null @@ -1,37 +0,0 @@ -package json - -import ( - v2net "github.com/v2ray/v2ray-core/common/net" - v2netjson "github.com/v2ray/v2ray-core/common/net/json" - "github.com/v2ray/v2ray-core/proxy/internal/config" - "github.com/v2ray/v2ray-core/proxy/internal/config/json" -) - -type DokodemoConfig struct { - Host *v2netjson.Host `json:"address"` - PortValue v2net.Port `json:"port"` - NetworkList *v2netjson.NetworkList `json:"network"` - TimeoutValue int `json:"timeout"` -} - -func (this *DokodemoConfig) Address() v2net.Address { - return this.Host.Address() -} - -func (this *DokodemoConfig) Port() v2net.Port { - return this.PortValue -} - -func (this *DokodemoConfig) Network() v2net.NetworkList { - return this.NetworkList -} - -func (this *DokodemoConfig) Timeout() int { - return this.TimeoutValue -} - -func init() { - config.RegisterInboundConnectionConfig("dokodemo-door", json.JsonConfigLoader(func() interface{} { - return new(DokodemoConfig) - })) -} diff --git a/proxy/freedom/config.go b/proxy/freedom/config.go index 82d859bad..a61f352fd 100644 --- a/proxy/freedom/config.go +++ b/proxy/freedom/config.go @@ -1,4 +1,4 @@ package freedom -type Config interface { +type Config struct { } diff --git a/proxy/freedom/config_json.go b/proxy/freedom/config_json.go new file mode 100644 index 000000000..c36367afe --- /dev/null +++ b/proxy/freedom/config_json.go @@ -0,0 +1,14 @@ +// +build json + +package freedom + +import ( + "github.com/v2ray/v2ray-core/proxy/internal/config" +) + +func init() { + config.RegisterOutboundConnectionConfig("freedom", + func(data []byte) (interface{}, error) { + return new(Config), nil + }) +} diff --git a/proxy/freedom/freedom_test.go b/proxy/freedom/freedom_test.go index 918f41d2d..4119fae3c 100644 --- a/proxy/freedom/freedom_test.go +++ b/proxy/freedom/freedom_test.go @@ -14,7 +14,6 @@ import ( v2nettesting "github.com/v2ray/v2ray-core/common/net/testing" v2proxy "github.com/v2ray/v2ray-core/proxy" _ "github.com/v2ray/v2ray-core/proxy/socks" - _ "github.com/v2ray/v2ray-core/proxy/socks/json" proxytesting "github.com/v2ray/v2ray-core/proxy/testing" proxymocks "github.com/v2ray/v2ray-core/proxy/testing/mocks" "github.com/v2ray/v2ray-core/shell/point" diff --git a/proxy/freedom/json/json.go b/proxy/freedom/json/json.go deleted file mode 100644 index 241fff40d..000000000 --- a/proxy/freedom/json/json.go +++ /dev/null @@ -1,15 +0,0 @@ -package json - -import ( - "github.com/v2ray/v2ray-core/proxy/internal/config" - "github.com/v2ray/v2ray-core/proxy/internal/config/json" -) - -type FreedomConfiguration struct { -} - -func init() { - config.RegisterOutboundConnectionConfig("freedom", json.JsonConfigLoader(func() interface{} { - return &FreedomConfiguration{} - })) -} diff --git a/proxy/http/config.go b/proxy/http/config.go index 1a20700f5..7132bb21f 100644 --- a/proxy/http/config.go +++ b/proxy/http/config.go @@ -1,4 +1,4 @@ package http -type Config interface { +type Config struct { } diff --git a/proxy/http/config_json.go b/proxy/http/config_json.go new file mode 100644 index 000000000..b8b6301bc --- /dev/null +++ b/proxy/http/config_json.go @@ -0,0 +1,14 @@ +// +build json + +package http + +import ( + "github.com/v2ray/v2ray-core/proxy/internal/config" +) + +func init() { + config.RegisterInboundConnectionConfig("http", + func(data []byte) (interface{}, error) { + return new(Config), nil + }) +} diff --git a/proxy/http/json/json.go b/proxy/http/json/json.go deleted file mode 100644 index 69de8fe65..000000000 --- a/proxy/http/json/json.go +++ /dev/null @@ -1,15 +0,0 @@ -package json - -import ( - "github.com/v2ray/v2ray-core/proxy/internal/config" - "github.com/v2ray/v2ray-core/proxy/internal/config/json" -) - -type HttpProxyConfig struct { -} - -func init() { - config.RegisterInboundConnectionConfig("http", json.JsonConfigLoader(func() interface{} { - return new(HttpProxyConfig) - })) -} diff --git a/proxy/internal/config/json/json.go b/proxy/internal/config/json/json.go deleted file mode 100644 index 3bccc2957..000000000 --- a/proxy/internal/config/json/json.go +++ /dev/null @@ -1,16 +0,0 @@ -package json - -import ( - "encoding/json" - - "github.com/v2ray/v2ray-core/common/log" -) - -func JsonConfigLoader(newConfig func() interface{}) func(data []byte) (interface{}, error) { - return func(data []byte) (interface{}, error) { - obj := newConfig() - log.Debug("Unmarshalling JSON: %s", string(data)) - err := json.Unmarshal(data, obj) - return obj, err - } -} diff --git a/proxy/socks/config.go b/proxy/socks/config.go index ef87d6c7b..d86149dad 100644 --- a/proxy/socks/config.go +++ b/proxy/socks/config.go @@ -1,13 +1,28 @@ package socks import ( - "net" + v2net "github.com/v2ray/v2ray-core/common/net" ) -type Config interface { - IsNoAuth() bool - IsPassword() bool - HasAccount(username, password string) bool - IP() net.IP - UDPEnabled() bool +const ( + AuthTypeNoAuth = byte(0) + AuthTypePassword = byte(1) +) + +type Config struct { + AuthType byte + Accounts map[string]string + Address v2net.Address + UDPEnabled bool +} + +func (this *Config) HasAccount(username, password string) bool { + if this.Accounts == nil { + return false + } + storedPassed, found := this.Accounts[username] + if !found { + return false + } + return storedPassed == password } diff --git a/proxy/socks/config_json.go b/proxy/socks/config_json.go new file mode 100644 index 000000000..be23b5c97 --- /dev/null +++ b/proxy/socks/config_json.go @@ -0,0 +1,64 @@ +// +build json + +package socks + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/common/log" + v2net "github.com/v2ray/v2ray-core/common/net" + v2netjson "github.com/v2ray/v2ray-core/common/net/json" + "github.com/v2ray/v2ray-core/proxy/internal" + "github.com/v2ray/v2ray-core/proxy/internal/config" +) + +const ( + AuthMethodNoAuth = "noauth" + AuthMethodUserPass = "password" +) + +func init() { + config.RegisterInboundConnectionConfig("socks", + func(data []byte) (interface{}, error) { + type SocksAccount struct { + Username string `json:"user"` + Password string `json:"pass"` + } + + type SocksConfig struct { + AuthMethod string `json:"auth"` + Accounts []*SocksAccount `json:"accounts"` + UDP bool `json:"udp"` + Host *v2netjson.Host `json:"ip"` + } + + rawConfig := new(SocksConfig) + if err := json.Unmarshal(data, rawConfig); err != nil { + return nil, err + } + socksConfig := new(Config) + if rawConfig.AuthMethod == AuthMethodNoAuth { + socksConfig.AuthType = AuthTypeNoAuth + } else if rawConfig.AuthMethod == AuthMethodUserPass { + socksConfig.AuthType = AuthTypePassword + } else { + log.Error("Socks: Unknown auth method: %s", rawConfig.AuthMethod) + return nil, internal.ErrorBadConfiguration + } + + if len(rawConfig.Accounts) > 0 { + socksConfig.Accounts = make(map[string]string, len(rawConfig.Accounts)) + for _, account := range rawConfig.Accounts { + socksConfig.Accounts[account.Username] = account.Password + } + } + + socksConfig.UDPEnabled = rawConfig.UDP + if rawConfig.Host != nil { + socksConfig.Address = rawConfig.Host.Address() + } else { + socksConfig.Address = v2net.IPAddress([]byte{127, 0, 0, 1}) + } + return socksConfig, nil + }) +} diff --git a/proxy/socks/config_json_test.go b/proxy/socks/config_json_test.go new file mode 100644 index 000000000..4897acba5 --- /dev/null +++ b/proxy/socks/config_json_test.go @@ -0,0 +1,22 @@ +// +build json + +package socks_test + +import ( + "testing" + + "github.com/v2ray/v2ray-core/proxy/internal/config" + "github.com/v2ray/v2ray-core/proxy/socks" + v2testing "github.com/v2ray/v2ray-core/testing" + "github.com/v2ray/v2ray-core/testing/assert" +) + +func TestDefaultIPAddress(t *testing.T) { + v2testing.Current(t) + + socksConfig, err := config.CreateInboundConnectionConfig("socks", []byte(`{ + "auth": "noauth" + }`)) + assert.Error(err).IsNil() + assert.String(socksConfig.(*socks.Config).Address).Equals("127.0.0.1") +} diff --git a/proxy/socks/json/config.go b/proxy/socks/json/config.go deleted file mode 100644 index 8fbf048db..000000000 --- a/proxy/socks/json/config.go +++ /dev/null @@ -1,93 +0,0 @@ -package json - -import ( - "encoding/json" - "errors" - "net" - - "github.com/v2ray/v2ray-core/proxy/internal/config" - jsonconfig "github.com/v2ray/v2ray-core/proxy/internal/config/json" -) - -const ( - AuthMethodNoAuth = "noauth" - AuthMethodUserPass = "password" -) - -type SocksAccount struct { - Username string `json:"user"` - Password string `json:"pass"` -} - -type SocksAccountMap map[string]string - -func (this *SocksAccountMap) UnmarshalJSON(data []byte) error { - var accounts []SocksAccount - err := json.Unmarshal(data, &accounts) - if err != nil { - return err - } - *this = make(map[string]string) - for _, account := range accounts { - (*this)[account.Username] = account.Password - } - return nil -} - -func (this *SocksAccountMap) HasAccount(user, pass string) bool { - if actualPass, found := (*this)[user]; found { - return actualPass == pass - } - return false -} - -type IPAddress net.IP - -func (this *IPAddress) UnmarshalJSON(data []byte) error { - var ipStr string - err := json.Unmarshal(data, &ipStr) - if err != nil { - return err - } - ip := net.ParseIP(ipStr) - if ip == nil { - return errors.New("Unknown IP format: " + ipStr) - } - *this = IPAddress(ip) - return nil -} - -type SocksConfig struct { - AuthMethod string `json:"auth"` - Accounts SocksAccountMap `json:"accounts"` - UDP bool `json:"udp"` - HostIP IPAddress `json:"ip"` -} - -func (sc *SocksConfig) IsNoAuth() bool { - return sc.AuthMethod == AuthMethodNoAuth -} - -func (sc *SocksConfig) IsPassword() bool { - return sc.AuthMethod == AuthMethodUserPass -} - -func (sc *SocksConfig) HasAccount(user, pass string) bool { - return sc.Accounts.HasAccount(user, pass) -} - -func (sc *SocksConfig) IP() net.IP { - return net.IP(sc.HostIP) -} - -func (this *SocksConfig) UDPEnabled() bool { - return this.UDP -} - -func init() { - config.RegisterInboundConnectionConfig("socks", jsonconfig.JsonConfigLoader(func() interface{} { - return &SocksConfig{ - HostIP: IPAddress(net.IPv4(127, 0, 0, 1)), - } - })) -} diff --git a/proxy/socks/json/config_test.go b/proxy/socks/json/config_test.go deleted file mode 100644 index 030d30f4e..000000000 --- a/proxy/socks/json/config_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package json - -import ( - "encoding/json" - "net" - "testing" - - "github.com/v2ray/v2ray-core/proxy/internal/config" - v2testing "github.com/v2ray/v2ray-core/testing" - "github.com/v2ray/v2ray-core/testing/assert" -) - -func TestAccountMapParsing(t *testing.T) { - v2testing.Current(t) - - var accountMap SocksAccountMap - err := json.Unmarshal([]byte("[{\"user\": \"a\", \"pass\":\"b\"}, {\"user\": \"c\", \"pass\":\"d\"}]"), &accountMap) - assert.Error(err).IsNil() - - assert.Bool(accountMap.HasAccount("a", "b")).IsTrue() - assert.Bool(accountMap.HasAccount("a", "c")).IsFalse() - assert.Bool(accountMap.HasAccount("c", "d")).IsTrue() - assert.Bool(accountMap.HasAccount("e", "d")).IsFalse() -} - -func TestDefaultIPAddress(t *testing.T) { - v2testing.Current(t) - - socksConfig, err := config.CreateInboundConnectionConfig("socks", []byte(`{}`)) - assert.Error(err).IsNil() - assert.String(socksConfig.(*SocksConfig).IP()).Equals("127.0.0.1") -} - -func TestIPAddressParsing(t *testing.T) { - v2testing.Current(t) - - var ipAddress IPAddress - err := json.Unmarshal([]byte("\"1.2.3.4\""), &ipAddress) - assert.Error(err).IsNil() - assert.String(net.IP(ipAddress)).Equals("1.2.3.4") -} - -func TestNoAuthConfig(t *testing.T) { - v2testing.Current(t) - - var config SocksConfig - err := json.Unmarshal([]byte("{\"auth\":\"noauth\", \"ip\":\"8.8.8.8\"}"), &config) - assert.Error(err).IsNil() - assert.Bool(config.IsNoAuth()).IsTrue() - assert.Bool(config.IsPassword()).IsFalse() - assert.String(config.IP()).Equals("8.8.8.8") - assert.Bool(config.UDPEnabled()).IsFalse() -} - -func TestUserPassConfig(t *testing.T) { - v2testing.Current(t) - - var config SocksConfig - err := json.Unmarshal([]byte("{\"auth\":\"password\", \"accounts\":[{\"user\":\"x\", \"pass\":\"y\"}], \"udp\":true}"), &config) - assert.Error(err).IsNil() - assert.Bool(config.IsNoAuth()).IsFalse() - assert.Bool(config.IsPassword()).IsTrue() - assert.Bool(config.HasAccount("x", "y")).IsTrue() - assert.Bool(config.UDPEnabled()).IsTrue() -} diff --git a/proxy/socks/socks.go b/proxy/socks/socks.go index 7ad810c35..6c0672754 100644 --- a/proxy/socks/socks.go +++ b/proxy/socks/socks.go @@ -27,13 +27,13 @@ type SocksServer struct { udpMutex sync.RWMutex accepting bool space app.Space - config Config + config *Config tcpListener *net.TCPListener udpConn *net.UDPConn udpAddress v2net.Destination } -func NewSocksServer(space app.Space, config Config) *SocksServer { +func NewSocksServer(space app.Space, config *Config) *SocksServer { return &SocksServer{ space: space, config: config, @@ -71,7 +71,7 @@ func (this *SocksServer) Listen(port v2net.Port) error { this.tcpListener = listener this.tcpMutex.Unlock() go this.AcceptConnections() - if this.config.UDPEnabled() { + if this.config.UDPEnabled { this.ListenUDP(port) } return nil @@ -116,7 +116,7 @@ func (this *SocksServer) HandleConnection(connection *net.TCPConn) error { func (this *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.Writer, auth protocol.Socks5AuthenticationRequest) error { expectedAuthMethod := protocol.AuthNotRequired - if this.config.IsPassword() { + if this.config.AuthType == AuthTypePassword { expectedAuthMethod = protocol.AuthUserPass } @@ -137,7 +137,7 @@ func (this *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.Wri log.Error("Socks failed to write authentication: %v", err) return err } - if this.config.IsPassword() { + if this.config.AuthType == AuthTypePassword { upRequest, err := protocol.ReadUserPassRequest(reader) if err != nil { log.Error("Socks failed to read username and password: %v", err) @@ -165,7 +165,7 @@ func (this *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.Wri return err } - if request.Command == protocol.CmdUdpAssociate && this.config.UDPEnabled() { + if request.Command == protocol.CmdUdpAssociate && this.config.UDPEnabled { return this.handleUDP(reader, writer) } diff --git a/proxy/socks/socks_test.go b/proxy/socks/socks_test.go index 4de9bd0c6..f28761e35 100644 --- a/proxy/socks/socks_test.go +++ b/proxy/socks/socks_test.go @@ -1,4 +1,4 @@ -package socks +package socks_test import ( "bytes" @@ -12,7 +12,6 @@ import ( "github.com/v2ray/v2ray-core/app" v2nettesting "github.com/v2ray/v2ray-core/common/net/testing" v2proxy "github.com/v2ray/v2ray-core/proxy" - _ "github.com/v2ray/v2ray-core/proxy/socks/json" proxytesting "github.com/v2ray/v2ray-core/proxy/testing" proxymocks "github.com/v2ray/v2ray-core/proxy/testing/mocks" "github.com/v2ray/v2ray-core/shell/point" diff --git a/proxy/socks/socksfactory.go b/proxy/socks/socksfactory.go index 9f9a8ad97..848787eb0 100644 --- a/proxy/socks/socksfactory.go +++ b/proxy/socks/socksfactory.go @@ -9,6 +9,6 @@ import ( func init() { internal.MustRegisterInboundConnectionHandlerCreator("socks", func(space app.Space, rawConfig interface{}) (proxy.InboundConnectionHandler, error) { - return NewSocksServer(space, rawConfig.(Config)), nil + return NewSocksServer(space, rawConfig.(*Config)), nil }) } diff --git a/proxy/socks/udp.go b/proxy/socks/udp.go index 8ef802346..fde340530 100644 --- a/proxy/socks/udp.go +++ b/proxy/socks/udp.go @@ -21,7 +21,7 @@ func (this *SocksServer) ListenUDP(port v2net.Port) error { return err } this.udpMutex.Lock() - this.udpAddress = v2net.UDPDestination(v2net.IPAddress(this.config.IP()), port) + this.udpAddress = v2net.UDPDestination(this.config.Address, port) this.udpConn = conn this.udpMutex.Unlock() diff --git a/proxy/vmess/inbound/config.go b/proxy/vmess/inbound/config.go index 415ad92ae..1d085f956 100644 --- a/proxy/vmess/inbound/config.go +++ b/proxy/vmess/inbound/config.go @@ -4,6 +4,6 @@ import ( "github.com/v2ray/v2ray-core/proxy/vmess" ) -type Config interface { - AllowedUsers() []vmess.User +type Config struct { + AllowedUsers []*vmess.User } diff --git a/proxy/vmess/inbound/config_json.go b/proxy/vmess/inbound/config_json.go new file mode 100644 index 000000000..e62ab1a50 --- /dev/null +++ b/proxy/vmess/inbound/config_json.go @@ -0,0 +1,26 @@ +// +build json + +package inbound + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/proxy/internal/config" + "github.com/v2ray/v2ray-core/proxy/vmess" +) + +func init() { + config.RegisterInboundConnectionConfig("vmess", + func(data []byte) (interface{}, error) { + type JsonConfig struct { + Users []*vmess.User `json:"clients"` + } + jsonConfig := new(JsonConfig) + if err := json.Unmarshal(data, jsonConfig); err != nil { + return nil, err + } + return &Config{ + AllowedUsers: jsonConfig.Users, + }, nil + }) +} diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 73d520fc9..18c004404 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -109,7 +109,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error readFinish.Lock() writeFinish.Lock() - userSettings := vmess.GetUserSettings(request.User.Level()) + userSettings := vmess.GetUserSettings(request.User.Level) connReader.SetTimeOut(userSettings.PayloadReadTimeout) go handleInput(request, connReader, input, &readFinish) @@ -167,10 +167,10 @@ func handleOutput(request *protocol.VMessRequest, writer io.Writer, output <-cha func init() { internal.MustRegisterInboundConnectionHandlerCreator("vmess", func(space app.Space, rawConfig interface{}) (proxy.InboundConnectionHandler, error) { - config := rawConfig.(Config) + config := rawConfig.(*Config) allowedClients := protocol.NewTimedUserSet() - for _, user := range config.AllowedUsers() { + for _, user := range config.AllowedUsers { allowedClients.AddUser(user) } diff --git a/proxy/vmess/inbound/json/inbound.go b/proxy/vmess/inbound/json/inbound.go deleted file mode 100644 index feb633634..000000000 --- a/proxy/vmess/inbound/json/inbound.go +++ /dev/null @@ -1,26 +0,0 @@ -package json - -import ( - "github.com/v2ray/v2ray-core/proxy/internal/config" - "github.com/v2ray/v2ray-core/proxy/internal/config/json" - "github.com/v2ray/v2ray-core/proxy/vmess" - vmessjson "github.com/v2ray/v2ray-core/proxy/vmess/json" -) - -type Inbound struct { - AllowedClients []*vmessjson.ConfigUser `json:"clients"` -} - -func (c *Inbound) AllowedUsers() []vmess.User { - users := make([]vmess.User, 0, len(c.AllowedClients)) - for _, rawUser := range c.AllowedClients { - users = append(users, rawUser) - } - return users -} - -func init() { - config.RegisterInboundConnectionConfig("vmess", json.JsonConfigLoader(func() interface{} { - return new(Inbound) - })) -} diff --git a/proxy/vmess/json/user.go b/proxy/vmess/json/user.go deleted file mode 100644 index e4903bc8a..000000000 --- a/proxy/vmess/json/user.go +++ /dev/null @@ -1,73 +0,0 @@ -package json - -import ( - "encoding/json" - "math/rand" - - "github.com/v2ray/v2ray-core/common/uuid" - "github.com/v2ray/v2ray-core/proxy/vmess" -) - -// ConfigUser is an user account in VMess configuration. -type ConfigUser struct { - Id *vmess.ID - Email string - LevelValue vmess.UserLevel - AlterIds []*vmess.ID -} - -func (u *ConfigUser) UnmarshalJSON(data []byte) error { - type rawUser struct { - IdString string `json:"id"` - EmailString string `json:"email"` - LevelInt int `json:"level"` - AlterIdCount int `json:"alterId"` - } - var rawUserValue rawUser - if err := json.Unmarshal(data, &rawUserValue); err != nil { - return err - } - id, err := uuid.ParseString(rawUserValue.IdString) - if err != nil { - return err - } - u.Id = vmess.NewID(id) - u.Email = rawUserValue.EmailString - u.LevelValue = vmess.UserLevel(rawUserValue.LevelInt) - - if rawUserValue.AlterIdCount > 0 { - prevId := u.Id.UUID() - // TODO: check duplicate - u.AlterIds = make([]*vmess.ID, rawUserValue.AlterIdCount) - for idx, _ := range u.AlterIds { - newid := prevId.Next() - u.AlterIds[idx] = vmess.NewID(newid) - prevId = newid - } - } - - return nil -} - -func (u *ConfigUser) ID() *vmess.ID { - return u.Id -} - -func (this *ConfigUser) Level() vmess.UserLevel { - return this.LevelValue -} - -func (this *ConfigUser) AlterIDs() []*vmess.ID { - return this.AlterIds -} - -func (this *ConfigUser) AnyValidID() *vmess.ID { - if len(this.AlterIds) == 0 { - return this.ID() - } - if len(this.AlterIds) == 1 { - return this.AlterIds[0] - } - idIdx := rand.Intn(len(this.AlterIds)) - return this.AlterIds[idIdx] -} diff --git a/proxy/vmess/outbound/config.go b/proxy/vmess/outbound/config.go index f1dc245cd..a149d6e7b 100644 --- a/proxy/vmess/outbound/config.go +++ b/proxy/vmess/outbound/config.go @@ -1,5 +1,5 @@ package outbound -type Config interface { - Receivers() []*Receiver +type Config struct { + Receivers []*Receiver } diff --git a/proxy/vmess/outbound/config_json.go b/proxy/vmess/outbound/config_json.go new file mode 100644 index 000000000..83b76634b --- /dev/null +++ b/proxy/vmess/outbound/config_json.go @@ -0,0 +1,39 @@ +// +build json + +package outbound + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/common/log" + "github.com/v2ray/v2ray-core/proxy/internal" + proxyconfig "github.com/v2ray/v2ray-core/proxy/internal/config" +) + +func (this *Config) UnmarshalJSON(data []byte) error { + type RawOutbound struct { + Receivers []*Receiver `json:"vnext"` + } + rawOutbound := &RawOutbound{} + err := json.Unmarshal(data, rawOutbound) + if err != nil { + return err + } + if len(rawOutbound.Receivers) == 0 { + log.Error("VMess: 0 VMess receiver configured.") + return internal.ErrorBadConfiguration + } + this.Receivers = rawOutbound.Receivers + return nil +} + +func init() { + proxyconfig.RegisterOutboundConnectionConfig("vmess", + func(data []byte) (interface{}, error) { + rawConfig := new(Config) + if err := json.Unmarshal(data, rawConfig); err != nil { + return nil, err + } + return rawConfig, nil + }) +} diff --git a/proxy/vmess/outbound/json/outbound.go b/proxy/vmess/outbound/json/outbound.go deleted file mode 100644 index 78381c805..000000000 --- a/proxy/vmess/outbound/json/outbound.go +++ /dev/null @@ -1,85 +0,0 @@ -package json - -import ( - "encoding/json" - - "github.com/v2ray/v2ray-core/common/log" - v2net "github.com/v2ray/v2ray-core/common/net" - v2netjson "github.com/v2ray/v2ray-core/common/net/json" - "github.com/v2ray/v2ray-core/proxy/internal" - proxyconfig "github.com/v2ray/v2ray-core/proxy/internal/config" - jsonconfig "github.com/v2ray/v2ray-core/proxy/internal/config/json" - "github.com/v2ray/v2ray-core/proxy/vmess" - vmessjson "github.com/v2ray/v2ray-core/proxy/vmess/json" - "github.com/v2ray/v2ray-core/proxy/vmess/outbound" -) - -type ConfigTarget struct { - Destination v2net.Destination - Users []*vmessjson.ConfigUser -} - -func (t *ConfigTarget) UnmarshalJSON(data []byte) error { - type RawConfigTarget struct { - Address *v2netjson.Host `json:"address"` - Port v2net.Port `json:"port"` - Users []*vmessjson.ConfigUser `json:"users"` - } - var rawConfig RawConfigTarget - if err := json.Unmarshal(data, &rawConfig); err != nil { - return err - } - if len(rawConfig.Users) == 0 { - log.Error("0 user configured for VMess outbound.") - return internal.ErrorBadConfiguration - } - t.Users = rawConfig.Users - if rawConfig.Address == nil { - log.Error("Address is not set in VMess outbound config.") - return internal.ErrorBadConfiguration - } - t.Destination = v2net.TCPDestination(rawConfig.Address.Address(), rawConfig.Port) - return nil -} - -type Outbound struct { - TargetList []*ConfigTarget `json:"vnext"` -} - -func (this *Outbound) UnmarshalJSON(data []byte) error { - type RawOutbound struct { - TargetList []*ConfigTarget `json:"vnext"` - } - rawOutbound := &RawOutbound{} - err := json.Unmarshal(data, rawOutbound) - if err != nil { - return err - } - if len(rawOutbound.TargetList) == 0 { - log.Error("0 VMess receiver configured.") - return internal.ErrorBadConfiguration - } - this.TargetList = rawOutbound.TargetList - return nil -} - -func (o *Outbound) Receivers() []*outbound.Receiver { - targets := make([]*outbound.Receiver, 0, 2*len(o.TargetList)) - for _, rawTarget := range o.TargetList { - users := make([]vmess.User, 0, len(rawTarget.Users)) - for _, rawUser := range rawTarget.Users { - users = append(users, rawUser) - } - targets = append(targets, &outbound.Receiver{ - Destination: rawTarget.Destination, - Accounts: users, - }) - } - return targets -} - -func init() { - proxyconfig.RegisterOutboundConnectionConfig("vmess", jsonconfig.JsonConfigLoader(func() interface{} { - return new(Outbound) - })) -} diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 720cd36a9..815b39b64 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -195,10 +195,10 @@ func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<- func init() { internal.MustRegisterOutboundConnectionHandlerCreator("vmess", func(space app.Space, rawConfig interface{}) (proxy.OutboundConnectionHandler, error) { - vOutConfig := rawConfig.(Config) + vOutConfig := rawConfig.(*Config) return &VMessOutboundHandler{ space: space, - receiverManager: NewReceiverManager(vOutConfig.Receivers()), + receiverManager: NewReceiverManager(vOutConfig.Receivers), }, nil }) } diff --git a/proxy/vmess/outbound/receiver.go b/proxy/vmess/outbound/receiver.go index a504b48c4..d784f0148 100644 --- a/proxy/vmess/outbound/receiver.go +++ b/proxy/vmess/outbound/receiver.go @@ -9,7 +9,7 @@ import ( type Receiver struct { Destination v2net.Destination - Accounts []vmess.User + Accounts []*vmess.User } type ReceiverManager struct { @@ -22,7 +22,7 @@ func NewReceiverManager(receivers []*Receiver) *ReceiverManager { } } -func (this *ReceiverManager) PickReceiver() (v2net.Destination, vmess.User) { +func (this *ReceiverManager) PickReceiver() (v2net.Destination, *vmess.User) { receiverLen := len(this.receivers) receiverIdx := 0 if receiverLen > 1 { diff --git a/proxy/vmess/outbound/receiver_json.go b/proxy/vmess/outbound/receiver_json.go new file mode 100644 index 000000000..3a9ed58b2 --- /dev/null +++ b/proxy/vmess/outbound/receiver_json.go @@ -0,0 +1,36 @@ +// +build json + +package outbound + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/common/log" + v2net "github.com/v2ray/v2ray-core/common/net" + v2netjson "github.com/v2ray/v2ray-core/common/net/json" + "github.com/v2ray/v2ray-core/proxy/internal" + "github.com/v2ray/v2ray-core/proxy/vmess" +) + +func (this *Receiver) UnmarshalJSON(data []byte) error { + type RawConfigTarget struct { + Address *v2netjson.Host `json:"address"` + Port v2net.Port `json:"port"` + Users []*vmess.User `json:"users"` + } + var rawConfig RawConfigTarget + if err := json.Unmarshal(data, &rawConfig); err != nil { + return err + } + if len(rawConfig.Users) == 0 { + log.Error("VMess: 0 user configured for VMess outbound.") + return internal.ErrorBadConfiguration + } + this.Accounts = rawConfig.Users + if rawConfig.Address == nil { + log.Error("VMess: Address is not set in VMess outbound config.") + return internal.ErrorBadConfiguration + } + this.Destination = v2net.TCPDestination(rawConfig.Address.Address(), rawConfig.Port) + return nil +} diff --git a/proxy/vmess/outbound/json/outbound_test.go b/proxy/vmess/outbound/receiver_json_test.go similarity index 54% rename from proxy/vmess/outbound/json/outbound_test.go rename to proxy/vmess/outbound/receiver_json_test.go index d782d6ec1..b00774d21 100644 --- a/proxy/vmess/outbound/json/outbound_test.go +++ b/proxy/vmess/outbound/receiver_json_test.go @@ -1,10 +1,12 @@ -package json_test +// +build json + +package outbound_test import ( "encoding/json" "testing" - jsonconfig "github.com/v2ray/v2ray-core/proxy/vmess/outbound/json" + . "github.com/v2ray/v2ray-core/proxy/vmess/outbound" v2testing "github.com/v2ray/v2ray-core/testing" "github.com/v2ray/v2ray-core/testing/assert" ) @@ -24,10 +26,10 @@ func TestConfigTargetParsing(t *testing.T) { ] }` - var target *jsonconfig.ConfigTarget - err := json.Unmarshal([]byte(rawJson), &target) + receiver := new(Receiver) + err := json.Unmarshal([]byte(rawJson), &receiver) assert.Error(err).IsNil() - assert.String(target.Destination).Equals("tcp:127.0.0.1:80") - assert.Int(len(target.Users)).Equals(1) - assert.String(target.Users[0].ID()).Equals("e641f5ad-9397-41e3-bf1a-e8740dfed019") + assert.String(receiver.Destination).Equals("tcp:127.0.0.1:80") + assert.Int(len(receiver.Accounts)).Equals(1) + assert.String(receiver.Accounts[0].ID).Equals("e641f5ad-9397-41e3-bf1a-e8740dfed019") } diff --git a/proxy/vmess/protocol/rand_test.go b/proxy/vmess/protocol/rand_test.go index 14c2ec64b..2e502cde9 100644 --- a/proxy/vmess/protocol/rand_test.go +++ b/proxy/vmess/protocol/rand_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - . "github.com/v2ray/v2ray-core/proxy/vmess/protocol" + . "github.com/v2ray/v2ray-core/proxy/vmess/protocol" v2testing "github.com/v2ray/v2ray-core/testing" "github.com/v2ray/v2ray-core/testing/assert" ) diff --git a/proxy/vmess/protocol/testing/mockuserset.go b/proxy/vmess/protocol/testing/mockuserset.go index b59457b80..ed2952d3c 100644 --- a/proxy/vmess/protocol/testing/mockuserset.go +++ b/proxy/vmess/protocol/testing/mockuserset.go @@ -6,17 +6,17 @@ import ( ) type MockUserSet struct { - Users []vmess.User + Users []*vmess.User UserHashes map[string]int Timestamps map[string]protocol.Timestamp } -func (us *MockUserSet) AddUser(user vmess.User) error { +func (us *MockUserSet) AddUser(user *vmess.User) error { us.Users = append(us.Users, user) return nil } -func (us *MockUserSet) GetUser(userhash []byte) (vmess.User, protocol.Timestamp, bool) { +func (us *MockUserSet) GetUser(userhash []byte) (*vmess.User, protocol.Timestamp, bool) { idx, found := us.UserHashes[string(userhash)] if found { return us.Users[idx], us.Timestamps[string(userhash)], true diff --git a/proxy/vmess/protocol/testing/static_userset.go b/proxy/vmess/protocol/testing/static_userset.go index d63bb3ab9..47f293814 100644 --- a/proxy/vmess/protocol/testing/static_userset.go +++ b/proxy/vmess/protocol/testing/static_userset.go @@ -6,34 +6,16 @@ import ( "github.com/v2ray/v2ray-core/proxy/vmess/protocol" ) -type StaticUser struct { - id *vmess.ID -} - -func (this *StaticUser) ID() *vmess.ID { - return this.id -} - -func (this *StaticUser) Level() vmess.UserLevel { - return vmess.UserLevelUntrusted -} - -func (this *StaticUser) AlterIDs() []*vmess.ID { - return nil -} - -func (this *StaticUser) AnyValidID() *vmess.ID { - return this.id -} - type StaticUserSet struct { } -func (us *StaticUserSet) AddUser(user vmess.User) error { +func (us *StaticUserSet) AddUser(user *vmess.User) error { return nil } -func (us *StaticUserSet) GetUser(userhash []byte) (vmess.User, protocol.Timestamp, bool) { +func (us *StaticUserSet) GetUser(userhash []byte) (*vmess.User, protocol.Timestamp, bool) { id, _ := uuid.ParseString("703e9102-eb57-499c-8b59-faf4f371bb21") - return &StaticUser{id: vmess.NewID(id)}, 0, true + return &vmess.User{ + ID: vmess.NewID(id), + }, 0, true } diff --git a/proxy/vmess/protocol/userset.go b/proxy/vmess/protocol/userset.go index b6b971271..b36df0a5a 100644 --- a/proxy/vmess/protocol/userset.go +++ b/proxy/vmess/protocol/userset.go @@ -38,12 +38,12 @@ type idEntry struct { } type UserSet interface { - AddUser(user vmess.User) error - GetUser(timeHash []byte) (vmess.User, Timestamp, bool) + AddUser(user *vmess.User) error + GetUser(timeHash []byte) (*vmess.User, Timestamp, bool) } type TimedUserSet struct { - validUsers []vmess.User + validUsers []*vmess.User userHash map[[16]byte]indexTimePair ids []*idEntry access sync.RWMutex @@ -56,7 +56,7 @@ type indexTimePair struct { func NewTimedUserSet() UserSet { tus := &TimedUserSet{ - validUsers: make([]vmess.User, 0, 16), + validUsers: make([]*vmess.User, 0, 16), userHash: make(map[[16]byte]indexTimePair, 512), access: sync.RWMutex{}, ids: make([]*idEntry, 0, 512), @@ -94,21 +94,21 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) { } } -func (us *TimedUserSet) AddUser(user vmess.User) error { +func (us *TimedUserSet) AddUser(user *vmess.User) error { idx := len(us.validUsers) us.validUsers = append(us.validUsers, user) nowSec := time.Now().Unix() entry := &idEntry{ - id: user.ID(), + id: user.ID, userIdx: idx, lastSec: Timestamp(nowSec - cacheDurationSec), hashes: collect.NewSizedQueue(2*cacheDurationSec + 1), } us.generateNewHashes(Timestamp(nowSec+cacheDurationSec), idx, entry) us.ids = append(us.ids, entry) - for _, alterid := range user.AlterIDs() { + for _, alterid := range user.AlterIDs { entry := &idEntry{ id: alterid, userIdx: idx, @@ -122,7 +122,7 @@ func (us *TimedUserSet) AddUser(user vmess.User) error { return nil } -func (us *TimedUserSet) GetUser(userHash []byte) (vmess.User, Timestamp, bool) { +func (us *TimedUserSet) GetUser(userHash []byte) (*vmess.User, Timestamp, bool) { defer us.access.RUnlock() us.access.RLock() var fixedSizeHash [16]byte diff --git a/proxy/vmess/protocol/vmess.go b/proxy/vmess/protocol/vmess.go index f02a730b9..994af6220 100644 --- a/proxy/vmess/protocol/vmess.go +++ b/proxy/vmess/protocol/vmess.go @@ -34,7 +34,7 @@ const ( // streaming. type VMessRequest struct { Version byte - User vmess.User + User *vmess.User RequestIV []byte RequestKey []byte ResponseHeader []byte @@ -83,7 +83,7 @@ func (this *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { timestampHash := TimestampHash() timestampHash.Write(timeSec.HashBytes()) iv := timestampHash.Sum(nil) - aesStream, err := v2crypto.NewAesDecryptionStream(userObj.ID().CmdKey(), iv) + aesStream, err := v2crypto.NewAesDecryptionStream(userObj.ID.CmdKey(), iv) if err != nil { log.Debug("VMess: Failed to create AES stream: %v", err) return nil, err @@ -217,7 +217,7 @@ func (this *VMessRequest) ToBytes(timestampGenerator RandomTimestampGenerator, b timestampHash := md5.New() timestampHash.Write(timestamp.HashBytes()) iv := timestampHash.Sum(nil) - aesStream, err := v2crypto.NewAesEncryptionStream(this.User.ID().CmdKey(), iv) + aesStream, err := v2crypto.NewAesEncryptionStream(this.User.ID.CmdKey(), iv) if err != nil { return nil, err } diff --git a/proxy/vmess/protocol/vmess_test.go b/proxy/vmess/protocol/vmess_test.go index fe96cc797..7426bd25e 100644 --- a/proxy/vmess/protocol/vmess_test.go +++ b/proxy/vmess/protocol/vmess_test.go @@ -24,27 +24,6 @@ func (this *FakeTimestampGenerator) Next() Timestamp { return this.timestamp } -type TestUser struct { - id *vmess.ID - level vmess.UserLevel -} - -func (u *TestUser) ID() *vmess.ID { - return u.id -} - -func (this *TestUser) Level() vmess.UserLevel { - return this.level -} - -func (this *TestUser) AlterIDs() []*vmess.ID { - return nil -} - -func (this *TestUser) AnyValidID() *vmess.ID { - return this.id -} - func TestVMessSerialization(t *testing.T) { v2testing.Current(t) @@ -53,11 +32,11 @@ func TestVMessSerialization(t *testing.T) { userId := vmess.NewID(id) - testUser := &TestUser{ - id: userId, + testUser := &vmess.User{ + ID: userId, } - userSet := protocoltesting.MockUserSet{[]vmess.User{}, make(map[string]int), make(map[string]Timestamp)} + userSet := protocoltesting.MockUserSet{[]*vmess.User{}, make(map[string]int), make(map[string]Timestamp)} userSet.AddUser(testUser) request := new(VMessRequest) @@ -92,7 +71,7 @@ func TestVMessSerialization(t *testing.T) { } assert.Byte(actualRequest.Version).Named("Version").Equals(byte(0x01)) - assert.String(actualRequest.User.ID()).Named("UserId").Equals(request.User.ID().String()) + assert.String(actualRequest.User.ID).Named("UserId").Equals(request.User.ID.String()) assert.Bytes(actualRequest.RequestIV).Named("RequestIV").Equals(request.RequestIV[:]) assert.Bytes(actualRequest.RequestKey).Named("RequestKey").Equals(request.RequestKey[:]) assert.Bytes(actualRequest.ResponseHeader).Named("ResponseHeader").Equals(request.ResponseHeader[:]) @@ -113,10 +92,10 @@ func BenchmarkVMessRequestWriting(b *testing.B) { assert.Error(err).IsNil() userId := vmess.NewID(id) - userSet := protocoltesting.MockUserSet{[]vmess.User{}, make(map[string]int), make(map[string]Timestamp)} + userSet := protocoltesting.MockUserSet{[]*vmess.User{}, make(map[string]int), make(map[string]Timestamp)} - testUser := &TestUser{ - id: userId, + testUser := &vmess.User{ + ID: userId, } userSet.AddUser(testUser) diff --git a/proxy/vmess/user.go b/proxy/vmess/user.go index 06a8857c1..51b0551fb 100644 --- a/proxy/vmess/user.go +++ b/proxy/vmess/user.go @@ -1,5 +1,9 @@ package vmess +import ( + "math/rand" +) + type UserLevel int const ( @@ -7,11 +11,21 @@ const ( UserLevelUntrusted = UserLevel(0) ) -type User interface { - ID() *ID - AlterIDs() []*ID - Level() UserLevel - AnyValidID() *ID +type User struct { + ID *ID + AlterIDs []*ID + Level UserLevel +} + +func (this *User) AnyValidID() *ID { + if len(this.AlterIDs) == 0 { + return this.ID + } + if len(this.AlterIDs) == 1 { + return this.AlterIDs[0] + } + idx := rand.Intn(len(this.AlterIDs)) + return this.AlterIDs[idx] } type UserSettings struct { diff --git a/proxy/vmess/user_json.go b/proxy/vmess/user_json.go new file mode 100644 index 000000000..3d5382255 --- /dev/null +++ b/proxy/vmess/user_json.go @@ -0,0 +1,42 @@ +// +build json + +package vmess + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/common/uuid" +) + +func (u *User) UnmarshalJSON(data []byte) error { + type rawUser struct { + IdString string `json:"id"` + EmailString string `json:"email"` + LevelInt int `json:"level"` + AlterIdCount int `json:"alterId"` + } + var rawUserValue rawUser + if err := json.Unmarshal(data, &rawUserValue); err != nil { + return err + } + id, err := uuid.ParseString(rawUserValue.IdString) + if err != nil { + return err + } + u.ID = NewID(id) + //u.Email = rawUserValue.EmailString + u.Level = UserLevel(rawUserValue.LevelInt) + + if rawUserValue.AlterIdCount > 0 { + prevId := u.ID.UUID() + // TODO: check duplicate + u.AlterIDs = make([]*ID, rawUserValue.AlterIdCount) + for idx, _ := range u.AlterIDs { + newid := prevId.Next() + u.AlterIDs[idx] = NewID(newid) + prevId = newid + } + } + + return nil +} diff --git a/proxy/vmess/vmess_test.go b/proxy/vmess/vmess_test.go index 296588a55..8e32e9538 100644 --- a/proxy/vmess/vmess_test.go +++ b/proxy/vmess/vmess_test.go @@ -13,9 +13,7 @@ import ( proxymocks "github.com/v2ray/v2ray-core/proxy/testing/mocks" vmess "github.com/v2ray/v2ray-core/proxy/vmess" _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound" - _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound/json" _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound" - _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound/json" "github.com/v2ray/v2ray-core/shell/point" "github.com/v2ray/v2ray-core/shell/point/testing/mocks" v2testing "github.com/v2ray/v2ray-core/testing" diff --git a/release/server/main.go b/release/server/main.go index f837ff79f..3646b7e41 100644 --- a/release/server/main.go +++ b/release/server/main.go @@ -16,19 +16,12 @@ import ( // The following are neccesary as they register handlers in their init functions. _ "github.com/v2ray/v2ray-core/proxy/blackhole" - _ "github.com/v2ray/v2ray-core/proxy/blackhole/json" _ "github.com/v2ray/v2ray-core/proxy/dokodemo" - _ "github.com/v2ray/v2ray-core/proxy/dokodemo/json" _ "github.com/v2ray/v2ray-core/proxy/freedom" - _ "github.com/v2ray/v2ray-core/proxy/freedom/json" _ "github.com/v2ray/v2ray-core/proxy/http" - _ "github.com/v2ray/v2ray-core/proxy/http/json" _ "github.com/v2ray/v2ray-core/proxy/socks" - _ "github.com/v2ray/v2ray-core/proxy/socks/json" _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound" - _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound/json" _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound" - _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound/json" ) var ( diff --git a/shell/point/json/json_test.go b/shell/point/json/json_test.go index bf196ab86..341b4d976 100644 --- a/shell/point/json/json_test.go +++ b/shell/point/json/json_test.go @@ -5,11 +5,11 @@ import ( "testing" netassert "github.com/v2ray/v2ray-core/common/net/testing/assert" - _ "github.com/v2ray/v2ray-core/proxy/dokodemo/json" - _ "github.com/v2ray/v2ray-core/proxy/freedom/json" - _ "github.com/v2ray/v2ray-core/proxy/socks/json" - _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound/json" - _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound/json" + _ "github.com/v2ray/v2ray-core/proxy/dokodemo" + _ "github.com/v2ray/v2ray-core/proxy/freedom" + _ "github.com/v2ray/v2ray-core/proxy/socks" + _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound" + _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound" "github.com/v2ray/v2ray-core/shell/point/json" v2testing "github.com/v2ray/v2ray-core/testing" diff --git a/testing/scenarios/server_env.go b/testing/scenarios/server_env.go index e6db94f03..a8c0263f2 100644 --- a/testing/scenarios/server_env.go +++ b/testing/scenarios/server_env.go @@ -13,17 +13,11 @@ import ( // The following are neccesary as they register handlers in their init functions. _ "github.com/v2ray/v2ray-core/proxy/blackhole" - _ "github.com/v2ray/v2ray-core/proxy/blackhole/json" _ "github.com/v2ray/v2ray-core/proxy/dokodemo" - _ "github.com/v2ray/v2ray-core/proxy/dokodemo/json" _ "github.com/v2ray/v2ray-core/proxy/freedom" - _ "github.com/v2ray/v2ray-core/proxy/freedom/json" _ "github.com/v2ray/v2ray-core/proxy/socks" - _ "github.com/v2ray/v2ray-core/proxy/socks/json" _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound" - _ "github.com/v2ray/v2ray-core/proxy/vmess/inbound/json" _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound" - _ "github.com/v2ray/v2ray-core/proxy/vmess/outbound/json" ) var ( diff --git a/tools/build/go.go b/tools/build/go.go index c9f1c1e85..187a507f5 100644 --- a/tools/build/go.go +++ b/tools/build/go.go @@ -14,7 +14,7 @@ func buildV2Ray(targetFile string, version string, goOS GoOS, goArch GoArch) err today := fmt.Sprintf("%04d%02d%02d", year, int(month), day) ldFlags = ldFlags + " -X github.com/v2ray/v2ray-core.version=" + version + " -X github.com/v2ray/v2ray-core.build=" + today } - cmd := exec.Command("go", "build", "-o", targetFile, "-compiler", "gc", "-ldflags", ldFlags, "github.com/v2ray/v2ray-core/release/server") + cmd := exec.Command("go", "build", "-tags", "json", "-o", targetFile, "-compiler", "gc", "-ldflags", ldFlags, "github.com/v2ray/v2ray-core/release/server") cmd.Env = append(cmd.Env, "GOOS="+string(goOS), "GOARCH="+string(goArch)) cmd.Env = append(cmd.Env, os.Environ()...) output, err := cmd.CombinedOutput()