From 771d0225c762de8e20d8f832afe89a67752eeb10 Mon Sep 17 00:00:00 2001 From: Claire Raymond Date: Fri, 16 Oct 2015 10:03:22 +0000 Subject: [PATCH] Refactor vmess config --- config/json/json_test.go | 2 +- proxy/vmess/config.go | 84 ------------------- proxy/vmess/{protocol/user => config}/id.go | 8 +- .../{protocol/user => config}/id_test.go | 2 +- proxy/vmess/config/inbound.go | 6 ++ proxy/vmess/config/json/inbound.go | 30 +++++++ proxy/vmess/config/json/outbound.go | 84 +++++++++++++++++++ proxy/vmess/config/json/user.go | 35 ++++++++ proxy/vmess/config/outbound.go | 14 ++++ proxy/vmess/config/user.go | 5 ++ proxy/vmess/protocol/user/user.go | 6 -- proxy/vmess/protocol/user/userset.go | 19 +++-- proxy/vmess/protocol/vmess.go | 5 +- proxy/vmess/protocol/vmess_test.go | 25 ++++-- proxy/vmess/vmess_test.go | 50 ++++++----- proxy/vmess/vmessin.go | 12 +-- proxy/vmess/vmessout.go | 48 ++++------- testing/mocks/mockuserset.go | 12 +-- 18 files changed, 263 insertions(+), 184 deletions(-) delete mode 100644 proxy/vmess/config.go rename proxy/vmess/{protocol/user => config}/id.go (92%) rename proxy/vmess/{protocol/user => config}/id_test.go (96%) create mode 100644 proxy/vmess/config/inbound.go create mode 100644 proxy/vmess/config/json/inbound.go create mode 100644 proxy/vmess/config/json/outbound.go create mode 100644 proxy/vmess/config/json/user.go create mode 100644 proxy/vmess/config/outbound.go create mode 100644 proxy/vmess/config/user.go delete mode 100644 proxy/vmess/protocol/user/user.go diff --git a/config/json/json_test.go b/config/json/json_test.go index df4dc0663..1fe2762c1 100644 --- a/config/json/json_test.go +++ b/config/json/json_test.go @@ -8,7 +8,7 @@ import ( "github.com/v2ray/v2ray-core/config/json" _ "github.com/v2ray/v2ray-core/proxy/freedom/config/json" _ "github.com/v2ray/v2ray-core/proxy/socks/config/json" - _ "github.com/v2ray/v2ray-core/proxy/vmess" + _ "github.com/v2ray/v2ray-core/proxy/vmess/config/json" "github.com/v2ray/v2ray-core/testing/unit" ) diff --git a/proxy/vmess/config.go b/proxy/vmess/config.go deleted file mode 100644 index 1bcab8a25..000000000 --- a/proxy/vmess/config.go +++ /dev/null @@ -1,84 +0,0 @@ -package vmess - -import ( - "net" - "strings" - - "github.com/v2ray/v2ray-core/common/log" - v2net "github.com/v2ray/v2ray-core/common/net" - "github.com/v2ray/v2ray-core/config" - "github.com/v2ray/v2ray-core/config/json" - "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" -) - -// VMessUser is an authenticated user account in VMess configuration. -type VMessUser struct { - Id string `json:"id"` - Email string `json:"email"` -} - -func (u *VMessUser) ToUser() (user.User, error) { - id, err := user.NewID(u.Id) - return user.User{ - Id: id, - }, err -} - -// VMessInboundConfig is -type VMessInboundConfig struct { - AllowedClients []VMessUser `json:"clients"` - UDPEnabled bool `json:"udp"` -} - -type VNextConfig struct { - Address string `json:"address"` - Port uint16 `json:"port"` - Users []VMessUser `json:"users"` - Network string `json:"network"` -} - -func (config VNextConfig) HasNetwork(network string) bool { - return strings.Contains(config.Network, network) -} - -func (c VNextConfig) ToVNextServer(network string) (*VNextServer, error) { - users := make([]user.User, 0, len(c.Users)) - for _, user := range c.Users { - vuser, err := user.ToUser() - if err != nil { - log.Error("Failed to convert %v to User.", user) - return nil, config.BadConfiguration - } - users = append(users, vuser) - } - ip := net.ParseIP(c.Address) - if ip == nil { - log.Error("Unable to parse VNext IP: %s", c.Address) - return nil, config.BadConfiguration - } - address := v2net.IPAddress(ip, c.Port) - var dest v2net.Destination - if network == "tcp" { - dest = v2net.NewTCPDestination(address) - } else { - dest = v2net.NewUDPDestination(address) - } - return &VNextServer{ - Destination: dest, - Users: users, - }, nil -} - -type VMessOutboundConfig struct { - VNextList []VNextConfig `json:"vnext"` -} - -func init() { - json.RegisterConfigType("vmess", config.TypeInbound, func() interface{} { - return new(VMessInboundConfig) - }) - - json.RegisterConfigType("vmess", config.TypeOutbound, func() interface{} { - return new(VMessOutboundConfig) - }) -} diff --git a/proxy/vmess/protocol/user/id.go b/proxy/vmess/config/id.go similarity index 92% rename from proxy/vmess/protocol/user/id.go rename to proxy/vmess/config/id.go index 9d382a067..6f891310f 100644 --- a/proxy/vmess/protocol/user/id.go +++ b/proxy/vmess/config/id.go @@ -1,4 +1,4 @@ -package user +package config import ( "crypto/md5" @@ -23,11 +23,11 @@ type ID struct { cmdKey [IDBytesLen]byte } -func NewID(id string) (ID, error) { +func NewID(id string) (*ID, error) { idBytes, err := UUIDToID(id) if err != nil { log.Error("Failed to parse id %s", id) - return ID{}, InvalidID + return &ID{}, InvalidID } md5hash := md5.New() @@ -35,7 +35,7 @@ func NewID(id string) (ID, error) { md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21")) cmdKey := md5.Sum(nil) - return ID{ + return &ID{ String: id, Bytes: idBytes, cmdKey: cmdKey, diff --git a/proxy/vmess/protocol/user/id_test.go b/proxy/vmess/config/id_test.go similarity index 96% rename from proxy/vmess/protocol/user/id_test.go rename to proxy/vmess/config/id_test.go index b5d57800d..9f547d7bd 100644 --- a/proxy/vmess/protocol/user/id_test.go +++ b/proxy/vmess/config/id_test.go @@ -1,4 +1,4 @@ -package user +package config import ( "testing" diff --git a/proxy/vmess/config/inbound.go b/proxy/vmess/config/inbound.go new file mode 100644 index 000000000..09646704e --- /dev/null +++ b/proxy/vmess/config/inbound.go @@ -0,0 +1,6 @@ +package config + +type Inbound interface { + AllowedUsers() []User + UDPEnabled() bool +} diff --git a/proxy/vmess/config/json/inbound.go b/proxy/vmess/config/json/inbound.go new file mode 100644 index 000000000..15b48e756 --- /dev/null +++ b/proxy/vmess/config/json/inbound.go @@ -0,0 +1,30 @@ +package json + +import ( + "github.com/v2ray/v2ray-core/config" + "github.com/v2ray/v2ray-core/config/json" + vmessconfig "github.com/v2ray/v2ray-core/proxy/vmess/config" +) + +type Inbound struct { + AllowedClients []*ConfigUser `json:"clients"` + UDP bool `json:"udp"` +} + +func (c *Inbound) AllowedUsers() []vmessconfig.User { + users := make([]vmessconfig.User, 0, len(c.AllowedClients)) + for _, rawUser := range c.AllowedClients { + users = append(users, rawUser) + } + return users +} + +func (c *Inbound) UDPEnabled() bool { + return c.UDP +} + +func init() { + json.RegisterConfigType("vmess", config.TypeInbound, func() interface{} { + return new(Inbound) + }) +} diff --git a/proxy/vmess/config/json/outbound.go b/proxy/vmess/config/json/outbound.go new file mode 100644 index 000000000..79599fb2d --- /dev/null +++ b/proxy/vmess/config/json/outbound.go @@ -0,0 +1,84 @@ +package json + +import ( + "encoding/json" + "net" + "strings" + + "github.com/v2ray/v2ray-core/common/log" + v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/config" + jsonconfig "github.com/v2ray/v2ray-core/config/json" + vmessconfig "github.com/v2ray/v2ray-core/proxy/vmess/config" +) + +type RawConfigTarget struct { + Address string `json:"address"` + Port uint16 `json:"port"` + Users []*ConfigUser `json:"users"` + Network string `json:"network"` +} + +func (config RawConfigTarget) HasNetwork(network string) bool { + return strings.Contains(config.Network, network) +} + +type ConfigTarget struct { + Address v2net.Address + Users []*ConfigUser + TCPEnabled bool + UDPEnabled bool +} + +func (t *ConfigTarget) UnmarshalJSON(data []byte) error { + var rawConfig RawConfigTarget + if err := json.Unmarshal(data, &rawConfig); err != nil { + return err + } + ip := net.ParseIP(rawConfig.Address) + if ip == nil { + log.Error("Unable to parse IP: %s", rawConfig.Address) + return config.BadConfiguration + } + t.Address = v2net.IPAddress(ip, rawConfig.Port) + if rawConfig.HasNetwork("tcp") { + t.TCPEnabled = true + } + if rawConfig.HasNetwork("udp") { + t.UDPEnabled = true + } + return nil +} + +type Outbound struct { + TargetList []*ConfigTarget `json:"vnext"` +} + +func (o *Outbound) Targets() []*vmessconfig.OutboundTarget { + targets := make([]*vmessconfig.OutboundTarget, 0, 2*len(o.TargetList)) + for _, rawTarget := range o.TargetList { + users := make([]vmessconfig.User, 0, len(rawTarget.Users)) + for _, rawUser := range rawTarget.Users { + users = append(users, rawUser) + } + if rawTarget.TCPEnabled { + targets = append(targets, &vmessconfig.OutboundTarget{ + Destination: v2net.NewTCPDestination(rawTarget.Address), + Accounts: users, + }) + } + if rawTarget.UDPEnabled { + targets = append(targets, &vmessconfig.OutboundTarget{ + Destination: v2net.NewUDPDestination(rawTarget.Address), + Accounts: users, + }) + } + } + return targets +} + +func init() { + jsonconfig.RegisterConfigType("vmess", config.TypeOutbound, func() interface{} { + return new(Outbound) + }) +} diff --git a/proxy/vmess/config/json/user.go b/proxy/vmess/config/json/user.go new file mode 100644 index 000000000..251cc622e --- /dev/null +++ b/proxy/vmess/config/json/user.go @@ -0,0 +1,35 @@ +package json + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/proxy/vmess/config" +) + +// ConfigUser is an user account in VMess configuration. +type ConfigUser struct { + Id *config.ID + Email string +} + +func (u *ConfigUser) UnmarshalJSON(data []byte) error { + type rawUser struct { + IdString string `json:"id"` + EmailString string `json:"email"` + } + var rawUserValue rawUser + if err := json.Unmarshal(data, &rawUserValue); err != nil { + return err + } + id, err := config.NewID(rawUserValue.IdString) + if err != nil { + return err + } + u.Id = id + u.Email = rawUserValue.EmailString + return nil +} + +func (u *ConfigUser) ID() *config.ID { + return u.Id +} diff --git a/proxy/vmess/config/outbound.go b/proxy/vmess/config/outbound.go new file mode 100644 index 000000000..b050ebd37 --- /dev/null +++ b/proxy/vmess/config/outbound.go @@ -0,0 +1,14 @@ +package config + +import ( + v2net "github.com/v2ray/v2ray-core/common/net" +) + +type OutboundTarget struct { + Destination v2net.Destination + Accounts []User +} + +type Outbound interface { + Targets() []*OutboundTarget +} diff --git a/proxy/vmess/config/user.go b/proxy/vmess/config/user.go new file mode 100644 index 000000000..baf52e93b --- /dev/null +++ b/proxy/vmess/config/user.go @@ -0,0 +1,5 @@ +package config + +type User interface { + ID() *ID +} diff --git a/proxy/vmess/protocol/user/user.go b/proxy/vmess/protocol/user/user.go deleted file mode 100644 index 4ef10733e..000000000 --- a/proxy/vmess/protocol/user/user.go +++ /dev/null @@ -1,6 +0,0 @@ -package user - -// User is the user account that is used for connection to a Point -type User struct { - Id ID `json:"id"` // The ID of this User. -} diff --git a/proxy/vmess/protocol/user/userset.go b/proxy/vmess/protocol/user/userset.go index 5968914db..81f186e7e 100644 --- a/proxy/vmess/protocol/user/userset.go +++ b/proxy/vmess/protocol/user/userset.go @@ -5,6 +5,7 @@ import ( "time" "github.com/v2ray/v2ray-core/common/collect" + "github.com/v2ray/v2ray-core/proxy/vmess/config" ) const ( @@ -13,12 +14,12 @@ const ( ) type UserSet interface { - AddUser(user User) error - GetUser(timeHash []byte) (*ID, int64, bool) + AddUser(user config.User) error + GetUser(timeHash []byte) (*config.ID, int64, bool) } type TimedUserSet struct { - validUserIds []ID + validUserIds []*config.ID userHash map[string]indexTimePair userHashDeleteQueue *collect.TimedQueue access sync.RWMutex @@ -31,7 +32,7 @@ type indexTimePair struct { func NewTimedUserSet() UserSet { tus := &TimedUserSet{ - validUserIds: make([]ID, 0, 16), + validUserIds: make([]*config.ID, 0, 16), userHash: make(map[string]indexTimePair, 512), userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec), access: sync.RWMutex{}, @@ -49,7 +50,7 @@ func (us *TimedUserSet) removeEntries(entries <-chan interface{}) { } } -func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id ID) { +func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id *config.ID) { idHash := NewTimeHash(HMACHash{}) for lastSec < nowSec { idHash := idHash.Hash(id.Bytes[:], lastSec) @@ -73,8 +74,8 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) { } } -func (us *TimedUserSet) AddUser(user User) error { - id := user.Id +func (us *TimedUserSet) AddUser(user config.User) error { + id := user.ID() idx := len(us.validUserIds) us.validUserIds = append(us.validUserIds, id) @@ -85,12 +86,12 @@ func (us *TimedUserSet) AddUser(user User) error { return nil } -func (us TimedUserSet) GetUser(userHash []byte) (*ID, int64, bool) { +func (us TimedUserSet) GetUser(userHash []byte) (*config.ID, int64, bool) { defer us.access.RUnlock() us.access.RLock() pair, found := us.userHash[string(userHash)] if found { - return &us.validUserIds[pair.index], pair.timeSec, true + return us.validUserIds[pair.index], pair.timeSec, true } return nil, 0, false } diff --git a/proxy/vmess/protocol/vmess.go b/proxy/vmess/protocol/vmess.go index 4d2d11e76..99747f9a7 100644 --- a/proxy/vmess/protocol/vmess.go +++ b/proxy/vmess/protocol/vmess.go @@ -13,6 +13,7 @@ import ( "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/proxy" + "github.com/v2ray/v2ray-core/proxy/vmess/config" "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" "github.com/v2ray/v2ray-core/transport" ) @@ -35,7 +36,7 @@ const ( // streaming. type VMessRequest struct { Version byte - UserId user.ID + UserId config.ID RequestIV []byte RequestKey []byte ResponseHeader []byte @@ -68,7 +69,7 @@ func NewVMessRequestReader(vUserSet user.UserSet) *VMessRequestReader { func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { buffer := make([]byte, 256) - nBytes, err := reader.Read(buffer[:user.IDBytesLen]) + nBytes, err := reader.Read(buffer[:config.IDBytesLen]) if err != nil { return nil, err } diff --git a/proxy/vmess/protocol/vmess_test.go b/proxy/vmess/protocol/vmess_test.go index c27d48836..8d38eee34 100644 --- a/proxy/vmess/protocol/vmess_test.go +++ b/proxy/vmess/protocol/vmess_test.go @@ -6,25 +6,34 @@ import ( "testing" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy/vmess/config" "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" "github.com/v2ray/v2ray-core/testing/mocks" "github.com/v2ray/v2ray-core/testing/unit" ) +type TestUser struct { + id *config.ID +} + +func (u *TestUser) ID() *config.ID { + return u.id +} + func TestVMessSerialization(t *testing.T) { assert := unit.Assert(t) - userId, err := user.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") + userId, err := config.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") if err != nil { t.Fatal(err) } - userSet := mocks.MockUserSet{[]user.ID{}, make(map[string]int), make(map[string]int64)} - userSet.AddUser(user.User{userId}) + userSet := mocks.MockUserSet{[]*config.ID{}, make(map[string]int), make(map[string]int64)} + userSet.AddUser(&TestUser{userId}) request := new(VMessRequest) request.Version = byte(0x01) - request.UserId = userId + request.UserId = *userId randBytes := make([]byte, 36) _, err = rand.Read(randBytes) @@ -61,13 +70,13 @@ func TestVMessSerialization(t *testing.T) { } func BenchmarkVMessRequestWriting(b *testing.B) { - userId, _ := user.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") - userSet := mocks.MockUserSet{[]user.ID{}, make(map[string]int), make(map[string]int64)} - userSet.AddUser(user.User{userId}) + userId, _ := config.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") + userSet := mocks.MockUserSet{[]*config.ID{}, make(map[string]int), make(map[string]int64)} + userSet.AddUser(&TestUser{userId}) request := new(VMessRequest) request.Version = byte(0x01) - request.UserId = userId + request.UserId = *userId randBytes := make([]byte, 36) rand.Read(randBytes) diff --git a/proxy/vmess/vmess_test.go b/proxy/vmess/vmess_test.go index de1704313..5bb5dc916 100644 --- a/proxy/vmess/vmess_test.go +++ b/proxy/vmess/vmess_test.go @@ -8,6 +8,8 @@ import ( "github.com/v2ray/v2ray-core/common/alloc" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/proxy" + "github.com/v2ray/v2ray-core/proxy/vmess/config" + "github.com/v2ray/v2ray-core/proxy/vmess/config/json" "github.com/v2ray/v2ray-core/testing/mocks" "github.com/v2ray/v2ray-core/testing/unit" ) @@ -16,6 +18,8 @@ func TestVMessInAndOut(t *testing.T) { assert := unit.Assert(t) data2Send := "The data to be send to outbound server." + testAccount, err := config.NewID("ad937d9d-6e23-4a5a-ba23-bce5092a7c51") + assert.Error(err).IsNil() portA := uint16(17392) ich := &mocks.InboundConnectionHandler{ @@ -33,14 +37,13 @@ func TestVMessInAndOut(t *testing.T) { }, OutboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "vmess", - SettingsValue: &VMessOutboundConfig{ - []VNextConfig{ - VNextConfig{ - Address: "127.0.0.1", - Port: 13829, - Network: "tcp", - Users: []VMessUser{ - VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}, + SettingsValue: &json.Outbound{ + []*json.ConfigTarget{ + &json.ConfigTarget{ + Address: v2net.IPAddress([]byte{127, 0, 0, 1}, 13829), + TCPEnabled: true, + Users: []*json.ConfigUser{ + &json.ConfigUser{Id: testAccount}, }, }, }, @@ -67,9 +70,9 @@ func TestVMessInAndOut(t *testing.T) { PortValue: portB, InboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "vmess", - SettingsValue: &VMessInboundConfig{ - AllowedClients: []VMessUser{ - VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}, + SettingsValue: &json.Inbound{ + AllowedClients: []*json.ConfigUser{ + &json.ConfigUser{Id: testAccount}, }, }, }, @@ -95,6 +98,8 @@ func TestVMessInAndOutUDP(t *testing.T) { assert := unit.Assert(t) data2Send := "The data to be send to outbound server." + testAccount, err := config.NewID("ad937d9d-6e23-4a5a-ba23-bce5092a7c51") + assert.Error(err).IsNil() portA := uint16(17394) ich := &mocks.InboundConnectionHandler{ @@ -112,14 +117,13 @@ func TestVMessInAndOutUDP(t *testing.T) { }, OutboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "vmess", - SettingsValue: &VMessOutboundConfig{ - []VNextConfig{ - VNextConfig{ - Address: "127.0.0.1", - Port: 13841, - Network: "udp", - Users: []VMessUser{ - VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}, + SettingsValue: &json.Outbound{ + []*json.ConfigTarget{ + &json.ConfigTarget{ + Address: v2net.IPAddress([]byte{127, 0, 0, 1}, 13841), + UDPEnabled: true, + Users: []*json.ConfigUser{ + &json.ConfigUser{Id: testAccount}, }, }, }, @@ -146,11 +150,11 @@ func TestVMessInAndOutUDP(t *testing.T) { PortValue: portB, InboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "vmess", - SettingsValue: &VMessInboundConfig{ - AllowedClients: []VMessUser{ - VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}, + SettingsValue: &json.Inbound{ + AllowedClients: []*json.ConfigUser{ + &json.ConfigUser{Id: testAccount}, }, - UDPEnabled: true, + UDP: true, }, }, OutboundConfigValue: &mocks.ConnectionConfig{ diff --git a/proxy/vmess/vmessin.go b/proxy/vmess/vmessin.go index 485dd8694..14adf5d5f 100644 --- a/proxy/vmess/vmessin.go +++ b/proxy/vmess/vmessin.go @@ -13,6 +13,7 @@ import ( v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/common/retry" "github.com/v2ray/v2ray-core/proxy" + "github.com/v2ray/v2ray-core/proxy/vmess/config" "github.com/v2ray/v2ray-core/proxy/vmess/protocol" "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" ) @@ -142,19 +143,14 @@ type VMessInboundHandlerFactory struct { } func (factory *VMessInboundHandlerFactory) Create(dispatcher app.PacketDispatcher, rawConfig interface{}) (proxy.InboundConnectionHandler, error) { - config := rawConfig.(*VMessInboundConfig) + config := rawConfig.(config.Inbound) allowedClients := user.NewTimedUserSet() - for _, client := range config.AllowedClients { - user, err := client.ToUser() - if err != nil { - log.Error("VMessIn: Failed to parse user id %s: %v", client.Id, err) - return nil, err - } + for _, user := range config.AllowedUsers() { allowedClients.AddUser(user) } - return NewVMessInboundHandler(dispatcher, allowedClients, config.UDPEnabled), nil + return NewVMessInboundHandler(dispatcher, allowedClients, config.UDPEnabled()), nil } func init() { diff --git a/proxy/vmess/vmessout.go b/proxy/vmess/vmessout.go index 10bd72a7b..f45c9b204 100644 --- a/proxy/vmess/vmessout.go +++ b/proxy/vmess/vmessout.go @@ -13,6 +13,7 @@ import ( "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/proxy" + "github.com/v2ray/v2ray-core/proxy/vmess/config" "github.com/v2ray/v2ray-core/proxy/vmess/protocol" "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" "github.com/v2ray/v2ray-core/transport/ray" @@ -22,25 +23,19 @@ const ( InfoTimeNotSync = "Please check the User ID in your vmess configuration, and make sure the time on your local and remote server are in sync." ) -// VNext is the next Point server in the connection chain. -type VNextServer struct { - Destination v2net.Destination // Address of VNext server - Users []user.User // User accounts for accessing VNext. -} - type VMessOutboundHandler struct { - vNextList []*VNextServer - vNextListUDP []*VNextServer + vNextList []*config.OutboundTarget + vNextListUDP []*config.OutboundTarget } -func NewVMessOutboundHandler(vNextList, vNextListUDP []*VNextServer) *VMessOutboundHandler { +func NewVMessOutboundHandler(vNextList, vNextListUDP []*config.OutboundTarget) *VMessOutboundHandler { return &VMessOutboundHandler{ vNextList: vNextList, vNextListUDP: vNextListUDP, } } -func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) { +func pickVNext(serverList []*config.OutboundTarget) (v2net.Destination, config.User) { vNextLen := len(serverList) if vNextLen == 0 { panic("VMessOut: Zero vNext is configured.") @@ -51,7 +46,7 @@ func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) { } vNext := serverList[vNextIndex] - vNextUserLen := len(vNext.Users) + vNextUserLen := len(vNext.Accounts) if vNextUserLen == 0 { panic("VMessOut: Zero User account.") } @@ -59,7 +54,7 @@ func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) { if vNextUserLen > 1 { vNextUserIndex = mrand.Intn(vNextUserLen) } - vNextUser := vNext.Users[vNextUserIndex] + vNextUser := vNext.Accounts[vNextUserIndex] return vNext.Destination, vNextUser } @@ -76,7 +71,7 @@ func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray. } request := &protocol.VMessRequest{ Version: protocol.Version, - UserId: vNextUser.Id, + UserId: *vNextUser.ID(), Command: command, Address: firstPacket.Destination().Address(), } @@ -199,26 +194,15 @@ type VMessOutboundHandlerFactory struct { } func (factory *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (proxy.OutboundConnectionHandler, error) { - config := rawConfig.(*VMessOutboundConfig) - servers := make([]*VNextServer, 0, len(config.VNextList)) - udpServers := make([]*VNextServer, 0, len(config.VNextList)) - for _, server := range config.VNextList { - if server.HasNetwork("tcp") { - aServer, err := server.ToVNextServer("tcp") - if err == nil { - servers = append(servers, aServer) - } else { - log.Warning("Discarding the server.") - } + vOutConfig := rawConfig.(config.Outbound) + servers := make([]*config.OutboundTarget, 0, 16) + udpServers := make([]*config.OutboundTarget, 0, 16) + for _, target := range vOutConfig.Targets() { + if target.Destination.IsTCP() { + servers = append(servers, target) } - if server.HasNetwork("udp") { - aServer, err := server.ToVNextServer("udp") - if err == nil { - udpServers = append(udpServers, aServer) - } else { - log.Warning("Discarding the server.") - } - + if target.Destination.IsUDP() { + udpServers = append(udpServers, target) } } return NewVMessOutboundHandler(servers, udpServers), nil diff --git a/testing/mocks/mockuserset.go b/testing/mocks/mockuserset.go index 5b12b76ac..236628468 100644 --- a/testing/mocks/mockuserset.go +++ b/testing/mocks/mockuserset.go @@ -1,24 +1,24 @@ package mocks import ( - "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" + "github.com/v2ray/v2ray-core/proxy/vmess/config" ) type MockUserSet struct { - UserIds []user.ID + UserIds []*config.ID UserHashes map[string]int Timestamps map[string]int64 } -func (us *MockUserSet) AddUser(user user.User) error { - us.UserIds = append(us.UserIds, user.Id) +func (us *MockUserSet) AddUser(user config.User) error { + us.UserIds = append(us.UserIds, user.ID()) return nil } -func (us *MockUserSet) GetUser(userhash []byte) (*user.ID, int64, bool) { +func (us *MockUserSet) GetUser(userhash []byte) (*config.ID, int64, bool) { idx, found := us.UserHashes[string(userhash)] if found { - return &us.UserIds[idx], us.Timestamps[string(userhash)], true + return us.UserIds[idx], us.Timestamps[string(userhash)], true } return nil, 0, false }