1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-21 17:46:58 -05:00

Refactor vmess config

This commit is contained in:
Claire Raymond 2015-10-16 10:03:22 +00:00
parent f10f08c87d
commit 771d0225c7
18 changed files with 263 additions and 184 deletions

View File

@ -8,7 +8,7 @@ import (
"github.com/v2ray/v2ray-core/config/json" "github.com/v2ray/v2ray-core/config/json"
_ "github.com/v2ray/v2ray-core/proxy/freedom/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/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" "github.com/v2ray/v2ray-core/testing/unit"
) )

View File

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

View File

@ -1,4 +1,4 @@
package user package config
import ( import (
"crypto/md5" "crypto/md5"
@ -23,11 +23,11 @@ type ID struct {
cmdKey [IDBytesLen]byte cmdKey [IDBytesLen]byte
} }
func NewID(id string) (ID, error) { func NewID(id string) (*ID, error) {
idBytes, err := UUIDToID(id) idBytes, err := UUIDToID(id)
if err != nil { if err != nil {
log.Error("Failed to parse id %s", id) log.Error("Failed to parse id %s", id)
return ID{}, InvalidID return &ID{}, InvalidID
} }
md5hash := md5.New() md5hash := md5.New()
@ -35,7 +35,7 @@ func NewID(id string) (ID, error) {
md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21")) md5hash.Write([]byte("c48619fe-8f02-49e0-b9e9-edf763e17e21"))
cmdKey := md5.Sum(nil) cmdKey := md5.Sum(nil)
return ID{ return &ID{
String: id, String: id,
Bytes: idBytes, Bytes: idBytes,
cmdKey: cmdKey, cmdKey: cmdKey,

View File

@ -1,4 +1,4 @@
package user package config
import ( import (
"testing" "testing"

View File

@ -0,0 +1,6 @@
package config
type Inbound interface {
AllowedUsers() []User
UDPEnabled() bool
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
package config
type User interface {
ID() *ID
}

View File

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

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/v2ray/v2ray-core/common/collect" "github.com/v2ray/v2ray-core/common/collect"
"github.com/v2ray/v2ray-core/proxy/vmess/config"
) )
const ( const (
@ -13,12 +14,12 @@ const (
) )
type UserSet interface { type UserSet interface {
AddUser(user User) error AddUser(user config.User) error
GetUser(timeHash []byte) (*ID, int64, bool) GetUser(timeHash []byte) (*config.ID, int64, bool)
} }
type TimedUserSet struct { type TimedUserSet struct {
validUserIds []ID validUserIds []*config.ID
userHash map[string]indexTimePair userHash map[string]indexTimePair
userHashDeleteQueue *collect.TimedQueue userHashDeleteQueue *collect.TimedQueue
access sync.RWMutex access sync.RWMutex
@ -31,7 +32,7 @@ type indexTimePair struct {
func NewTimedUserSet() UserSet { func NewTimedUserSet() UserSet {
tus := &TimedUserSet{ tus := &TimedUserSet{
validUserIds: make([]ID, 0, 16), validUserIds: make([]*config.ID, 0, 16),
userHash: make(map[string]indexTimePair, 512), userHash: make(map[string]indexTimePair, 512),
userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec), userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec),
access: sync.RWMutex{}, 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{}) idHash := NewTimeHash(HMACHash{})
for lastSec < nowSec { for lastSec < nowSec {
idHash := idHash.Hash(id.Bytes[:], lastSec) 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 { func (us *TimedUserSet) AddUser(user config.User) error {
id := user.Id id := user.ID()
idx := len(us.validUserIds) idx := len(us.validUserIds)
us.validUserIds = append(us.validUserIds, id) us.validUserIds = append(us.validUserIds, id)
@ -85,12 +86,12 @@ func (us *TimedUserSet) AddUser(user User) error {
return nil 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() defer us.access.RUnlock()
us.access.RLock() us.access.RLock()
pair, found := us.userHash[string(userHash)] pair, found := us.userHash[string(userHash)]
if found { if found {
return &us.validUserIds[pair.index], pair.timeSec, true return us.validUserIds[pair.index], pair.timeSec, true
} }
return nil, 0, false return nil, 0, false
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/v2ray/v2ray-core/common/log" "github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net" v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/proxy" "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/proxy/vmess/protocol/user"
"github.com/v2ray/v2ray-core/transport" "github.com/v2ray/v2ray-core/transport"
) )
@ -35,7 +36,7 @@ const (
// streaming. // streaming.
type VMessRequest struct { type VMessRequest struct {
Version byte Version byte
UserId user.ID UserId config.ID
RequestIV []byte RequestIV []byte
RequestKey []byte RequestKey []byte
ResponseHeader []byte ResponseHeader []byte
@ -68,7 +69,7 @@ func NewVMessRequestReader(vUserSet user.UserSet) *VMessRequestReader {
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
buffer := make([]byte, 256) buffer := make([]byte, 256)
nBytes, err := reader.Read(buffer[:user.IDBytesLen]) nBytes, err := reader.Read(buffer[:config.IDBytesLen])
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -6,25 +6,34 @@ import (
"testing" "testing"
v2net "github.com/v2ray/v2ray-core/common/net" 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/proxy/vmess/protocol/user"
"github.com/v2ray/v2ray-core/testing/mocks" "github.com/v2ray/v2ray-core/testing/mocks"
"github.com/v2ray/v2ray-core/testing/unit" "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) { func TestVMessSerialization(t *testing.T) {
assert := unit.Assert(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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
userSet := mocks.MockUserSet{[]user.ID{}, make(map[string]int), make(map[string]int64)} userSet := mocks.MockUserSet{[]*config.ID{}, make(map[string]int), make(map[string]int64)}
userSet.AddUser(user.User{userId}) userSet.AddUser(&TestUser{userId})
request := new(VMessRequest) request := new(VMessRequest)
request.Version = byte(0x01) request.Version = byte(0x01)
request.UserId = userId request.UserId = *userId
randBytes := make([]byte, 36) randBytes := make([]byte, 36)
_, err = rand.Read(randBytes) _, err = rand.Read(randBytes)
@ -61,13 +70,13 @@ func TestVMessSerialization(t *testing.T) {
} }
func BenchmarkVMessRequestWriting(b *testing.B) { func BenchmarkVMessRequestWriting(b *testing.B) {
userId, _ := user.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") userId, _ := config.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51")
userSet := mocks.MockUserSet{[]user.ID{}, make(map[string]int), make(map[string]int64)} userSet := mocks.MockUserSet{[]*config.ID{}, make(map[string]int), make(map[string]int64)}
userSet.AddUser(user.User{userId}) userSet.AddUser(&TestUser{userId})
request := new(VMessRequest) request := new(VMessRequest)
request.Version = byte(0x01) request.Version = byte(0x01)
request.UserId = userId request.UserId = *userId
randBytes := make([]byte, 36) randBytes := make([]byte, 36)
rand.Read(randBytes) rand.Read(randBytes)

View File

@ -8,6 +8,8 @@ import (
"github.com/v2ray/v2ray-core/common/alloc" "github.com/v2ray/v2ray-core/common/alloc"
v2net "github.com/v2ray/v2ray-core/common/net" v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/proxy" "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/mocks"
"github.com/v2ray/v2ray-core/testing/unit" "github.com/v2ray/v2ray-core/testing/unit"
) )
@ -16,6 +18,8 @@ func TestVMessInAndOut(t *testing.T) {
assert := unit.Assert(t) assert := unit.Assert(t)
data2Send := "The data to be send to outbound server." 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) portA := uint16(17392)
ich := &mocks.InboundConnectionHandler{ ich := &mocks.InboundConnectionHandler{
@ -33,14 +37,13 @@ func TestVMessInAndOut(t *testing.T) {
}, },
OutboundConfigValue: &mocks.ConnectionConfig{ OutboundConfigValue: &mocks.ConnectionConfig{
ProtocolValue: "vmess", ProtocolValue: "vmess",
SettingsValue: &VMessOutboundConfig{ SettingsValue: &json.Outbound{
[]VNextConfig{ []*json.ConfigTarget{
VNextConfig{ &json.ConfigTarget{
Address: "127.0.0.1", Address: v2net.IPAddress([]byte{127, 0, 0, 1}, 13829),
Port: 13829, TCPEnabled: true,
Network: "tcp", Users: []*json.ConfigUser{
Users: []VMessUser{ &json.ConfigUser{Id: testAccount},
VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"},
}, },
}, },
}, },
@ -67,9 +70,9 @@ func TestVMessInAndOut(t *testing.T) {
PortValue: portB, PortValue: portB,
InboundConfigValue: &mocks.ConnectionConfig{ InboundConfigValue: &mocks.ConnectionConfig{
ProtocolValue: "vmess", ProtocolValue: "vmess",
SettingsValue: &VMessInboundConfig{ SettingsValue: &json.Inbound{
AllowedClients: []VMessUser{ AllowedClients: []*json.ConfigUser{
VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}, &json.ConfigUser{Id: testAccount},
}, },
}, },
}, },
@ -95,6 +98,8 @@ func TestVMessInAndOutUDP(t *testing.T) {
assert := unit.Assert(t) assert := unit.Assert(t)
data2Send := "The data to be send to outbound server." 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) portA := uint16(17394)
ich := &mocks.InboundConnectionHandler{ ich := &mocks.InboundConnectionHandler{
@ -112,14 +117,13 @@ func TestVMessInAndOutUDP(t *testing.T) {
}, },
OutboundConfigValue: &mocks.ConnectionConfig{ OutboundConfigValue: &mocks.ConnectionConfig{
ProtocolValue: "vmess", ProtocolValue: "vmess",
SettingsValue: &VMessOutboundConfig{ SettingsValue: &json.Outbound{
[]VNextConfig{ []*json.ConfigTarget{
VNextConfig{ &json.ConfigTarget{
Address: "127.0.0.1", Address: v2net.IPAddress([]byte{127, 0, 0, 1}, 13841),
Port: 13841, UDPEnabled: true,
Network: "udp", Users: []*json.ConfigUser{
Users: []VMessUser{ &json.ConfigUser{Id: testAccount},
VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"},
}, },
}, },
}, },
@ -146,11 +150,11 @@ func TestVMessInAndOutUDP(t *testing.T) {
PortValue: portB, PortValue: portB,
InboundConfigValue: &mocks.ConnectionConfig{ InboundConfigValue: &mocks.ConnectionConfig{
ProtocolValue: "vmess", ProtocolValue: "vmess",
SettingsValue: &VMessInboundConfig{ SettingsValue: &json.Inbound{
AllowedClients: []VMessUser{ AllowedClients: []*json.ConfigUser{
VMessUser{Id: "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}, &json.ConfigUser{Id: testAccount},
}, },
UDPEnabled: true, UDP: true,
}, },
}, },
OutboundConfigValue: &mocks.ConnectionConfig{ OutboundConfigValue: &mocks.ConnectionConfig{

View File

@ -13,6 +13,7 @@ import (
v2net "github.com/v2ray/v2ray-core/common/net" v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/retry" "github.com/v2ray/v2ray-core/common/retry"
"github.com/v2ray/v2ray-core/proxy" "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"
"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" "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) { func (factory *VMessInboundHandlerFactory) Create(dispatcher app.PacketDispatcher, rawConfig interface{}) (proxy.InboundConnectionHandler, error) {
config := rawConfig.(*VMessInboundConfig) config := rawConfig.(config.Inbound)
allowedClients := user.NewTimedUserSet() allowedClients := user.NewTimedUserSet()
for _, client := range config.AllowedClients { for _, user := range config.AllowedUsers() {
user, err := client.ToUser()
if err != nil {
log.Error("VMessIn: Failed to parse user id %s: %v", client.Id, err)
return nil, err
}
allowedClients.AddUser(user) allowedClients.AddUser(user)
} }
return NewVMessInboundHandler(dispatcher, allowedClients, config.UDPEnabled), nil return NewVMessInboundHandler(dispatcher, allowedClients, config.UDPEnabled()), nil
} }
func init() { func init() {

View File

@ -13,6 +13,7 @@ import (
"github.com/v2ray/v2ray-core/common/log" "github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net" v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/proxy" "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"
"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user"
"github.com/v2ray/v2ray-core/transport/ray" "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." 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 { type VMessOutboundHandler struct {
vNextList []*VNextServer vNextList []*config.OutboundTarget
vNextListUDP []*VNextServer vNextListUDP []*config.OutboundTarget
} }
func NewVMessOutboundHandler(vNextList, vNextListUDP []*VNextServer) *VMessOutboundHandler { func NewVMessOutboundHandler(vNextList, vNextListUDP []*config.OutboundTarget) *VMessOutboundHandler {
return &VMessOutboundHandler{ return &VMessOutboundHandler{
vNextList: vNextList, vNextList: vNextList,
vNextListUDP: vNextListUDP, vNextListUDP: vNextListUDP,
} }
} }
func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) { func pickVNext(serverList []*config.OutboundTarget) (v2net.Destination, config.User) {
vNextLen := len(serverList) vNextLen := len(serverList)
if vNextLen == 0 { if vNextLen == 0 {
panic("VMessOut: Zero vNext is configured.") panic("VMessOut: Zero vNext is configured.")
@ -51,7 +46,7 @@ func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) {
} }
vNext := serverList[vNextIndex] vNext := serverList[vNextIndex]
vNextUserLen := len(vNext.Users) vNextUserLen := len(vNext.Accounts)
if vNextUserLen == 0 { if vNextUserLen == 0 {
panic("VMessOut: Zero User account.") panic("VMessOut: Zero User account.")
} }
@ -59,7 +54,7 @@ func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) {
if vNextUserLen > 1 { if vNextUserLen > 1 {
vNextUserIndex = mrand.Intn(vNextUserLen) vNextUserIndex = mrand.Intn(vNextUserLen)
} }
vNextUser := vNext.Users[vNextUserIndex] vNextUser := vNext.Accounts[vNextUserIndex]
return vNext.Destination, vNextUser return vNext.Destination, vNextUser
} }
@ -76,7 +71,7 @@ func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.
} }
request := &protocol.VMessRequest{ request := &protocol.VMessRequest{
Version: protocol.Version, Version: protocol.Version,
UserId: vNextUser.Id, UserId: *vNextUser.ID(),
Command: command, Command: command,
Address: firstPacket.Destination().Address(), Address: firstPacket.Destination().Address(),
} }
@ -199,26 +194,15 @@ type VMessOutboundHandlerFactory struct {
} }
func (factory *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (proxy.OutboundConnectionHandler, error) { func (factory *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (proxy.OutboundConnectionHandler, error) {
config := rawConfig.(*VMessOutboundConfig) vOutConfig := rawConfig.(config.Outbound)
servers := make([]*VNextServer, 0, len(config.VNextList)) servers := make([]*config.OutboundTarget, 0, 16)
udpServers := make([]*VNextServer, 0, len(config.VNextList)) udpServers := make([]*config.OutboundTarget, 0, 16)
for _, server := range config.VNextList { for _, target := range vOutConfig.Targets() {
if server.HasNetwork("tcp") { if target.Destination.IsTCP() {
aServer, err := server.ToVNextServer("tcp") servers = append(servers, target)
if err == nil {
servers = append(servers, aServer)
} else {
log.Warning("Discarding the server.")
}
} }
if server.HasNetwork("udp") { if target.Destination.IsUDP() {
aServer, err := server.ToVNextServer("udp") udpServers = append(udpServers, target)
if err == nil {
udpServers = append(udpServers, aServer)
} else {
log.Warning("Discarding the server.")
}
} }
} }
return NewVMessOutboundHandler(servers, udpServers), nil return NewVMessOutboundHandler(servers, udpServers), nil

View File

@ -1,24 +1,24 @@
package mocks package mocks
import ( import (
"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user" "github.com/v2ray/v2ray-core/proxy/vmess/config"
) )
type MockUserSet struct { type MockUserSet struct {
UserIds []user.ID UserIds []*config.ID
UserHashes map[string]int UserHashes map[string]int
Timestamps map[string]int64 Timestamps map[string]int64
} }
func (us *MockUserSet) AddUser(user user.User) error { func (us *MockUserSet) AddUser(user config.User) error {
us.UserIds = append(us.UserIds, user.Id) us.UserIds = append(us.UserIds, user.ID())
return nil 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)] idx, found := us.UserHashes[string(userhash)]
if found { if found {
return &us.UserIds[idx], us.Timestamps[string(userhash)], true return us.UserIds[idx], us.Timestamps[string(userhash)], true
} }
return nil, 0, false return nil, 0, false
} }