v2ray 9 gadi atpakaļ
vecāks
revīzija
7dfa852677

+ 10 - 0
common/protocol/account.go

@@ -5,6 +5,7 @@ import (
 )
 
 type Account interface {
+	Equals(Account) bool
 }
 
 type VMessAccount struct {
@@ -18,3 +19,12 @@ func (this *VMessAccount) AnyValidID() *ID {
 	}
 	return this.AlterIDs[dice.Roll(len(this.AlterIDs))]
 }
+
+func (this *VMessAccount) Equals(account Account) bool {
+	vmessAccount, ok := account.(*VMessAccount)
+	if !ok {
+		return false
+	}
+	// TODO: handle AlterIds difference
+	return this.ID.Equals(vmessAccount.ID)
+}

+ 90 - 0
common/protocol/server_picker.go

@@ -0,0 +1,90 @@
+package protocol
+
+import (
+	"sync"
+)
+
+type ServerList struct {
+	sync.RWMutex
+	servers []*ServerSpec
+}
+
+func NewServerList() *ServerList {
+	return &ServerList{}
+}
+
+func (this *ServerList) AddServer(server *ServerSpec) {
+	this.Lock()
+	defer this.Unlock()
+
+	this.servers = append(this.servers, server)
+}
+
+func (this *ServerList) Size() uint32 {
+	this.RLock()
+	defer this.RUnlock()
+
+	return uint32(len(this.servers))
+}
+
+func (this *ServerList) GetServer(idx uint32) *ServerSpec {
+	this.RLock()
+	defer this.RUnlock()
+
+	for {
+		if idx >= uint32(len(this.servers)) {
+			return nil
+		}
+
+		server := this.servers[idx]
+		if !server.IsValid() {
+			this.RemoveServer(idx)
+			continue
+		}
+
+		return server
+	}
+}
+
+// @Private
+func (this *ServerList) RemoveServer(idx uint32) {
+	n := len(this.servers)
+	this.servers[idx] = this.servers[n-1]
+	this.servers = this.servers[:n-1]
+}
+
+type ServerPicker interface {
+	PickServer() *ServerSpec
+}
+
+type RoundRobinServerPicker struct {
+	sync.Mutex
+	serverlist *ServerList
+	nextIndex  uint32
+}
+
+func NewRoundRobinServerPicker(serverlist *ServerList) *RoundRobinServerPicker {
+	return &RoundRobinServerPicker{
+		serverlist: serverlist,
+		nextIndex:  0,
+	}
+}
+
+func (this *RoundRobinServerPicker) PickServer() *ServerSpec {
+	this.Lock()
+	defer this.Unlock()
+
+	next := this.nextIndex
+	server := this.serverlist.GetServer(next)
+	if server == nil {
+		next = 0
+		server = this.serverlist.GetServer(0)
+	}
+	next++
+	if next >= this.serverlist.Size() {
+		next = 0
+	}
+	this.nextIndex = next
+
+	return server
+}

+ 81 - 0
common/protocol/server_spec.go

@@ -0,0 +1,81 @@
+package protocol
+
+import (
+	"sync"
+	"time"
+
+	"github.com/v2ray/v2ray-core/common/dice"
+	v2net "github.com/v2ray/v2ray-core/common/net"
+)
+
+type ServerSpec struct {
+	sync.RWMutex
+	Destination v2net.Destination
+
+	users []*User
+}
+
+func NewServerSpec(dest v2net.Destination, users ...*User) *ServerSpec {
+	return &ServerSpec{
+		Destination: dest,
+		users:       users,
+	}
+}
+
+func (this *ServerSpec) HasUser(user *User) bool {
+	this.RLock()
+	defer this.RUnlock()
+
+	account := user.Account
+	for _, u := range this.users {
+		if u.Account.Equals(account) {
+			return true
+		}
+	}
+	return false
+}
+
+func (this *ServerSpec) AddUser(user *User) {
+	if this.HasUser(user) {
+		return
+	}
+
+	this.Lock()
+	defer this.Unlock()
+
+	this.users = append(this.users, user)
+}
+
+func (this *ServerSpec) PickUser() *User {
+	userCount := len(this.users)
+	return this.users[dice.Roll(userCount)]
+}
+
+func (this *ServerSpec) IsValid() bool {
+	return true
+}
+
+func (this *ServerSpec) SetValid(b bool) {
+}
+
+type TimeoutServerSpec struct {
+	*ServerSpec
+	until time.Time
+}
+
+func NewTimeoutServerSpec(spec *ServerSpec, until time.Time) *TimeoutServerSpec {
+	return &TimeoutServerSpec{
+		ServerSpec: spec,
+		until:      until,
+	}
+}
+
+func (this *TimeoutServerSpec) IsValid() bool {
+	return this.until.Before(time.Now())
+}
+
+func (this *TimeoutServerSpec) SetValid(b bool) {
+	if !b {
+		this.until = time.Time{}
+	}
+}