| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | package protocolimport (	"sync"	"time"	"v2ray.com/core/common/dice"	"v2ray.com/core/common/net")type ValidationStrategy interface {	IsValid() bool	Invalidate()}type alwaysValidStrategy struct{}func AlwaysValid() ValidationStrategy {	return alwaysValidStrategy{}}func (alwaysValidStrategy) IsValid() bool {	return true}func (alwaysValidStrategy) Invalidate() {}type timeoutValidStrategy struct {	until time.Time}func BeforeTime(t time.Time) ValidationStrategy {	return &timeoutValidStrategy{		until: t,	}}func (v *timeoutValidStrategy) IsValid() bool {	return v.until.After(time.Now())}func (v *timeoutValidStrategy) Invalidate() {	v.until = time.Time{}}type ServerSpec struct {	sync.RWMutex	dest  net.Destination	users []*User	valid ValidationStrategy}func NewServerSpec(dest net.Destination, valid ValidationStrategy, users ...*User) *ServerSpec {	return &ServerSpec{		dest:  dest,		users: users,		valid: valid,	}}func NewServerSpecFromPB(spec ServerEndpoint) *ServerSpec {	dest := net.TCPDestination(spec.Address.AsAddress(), net.Port(spec.Port))	return NewServerSpec(dest, AlwaysValid(), spec.User...)}func (v *ServerSpec) Destination() net.Destination {	return v.dest}func (v *ServerSpec) HasUser(user *User) bool {	v.RLock()	defer v.RUnlock()	accountA, err := user.GetTypedAccount()	if err != nil {		return false	}	for _, u := range v.users {		accountB, err := u.GetTypedAccount()		if err == nil && accountA.Equals(accountB) {			return true		}	}	return false}func (v *ServerSpec) AddUser(user *User) {	if v.HasUser(user) {		return	}	v.Lock()	defer v.Unlock()	v.users = append(v.users, user)}func (v *ServerSpec) PickUser() *User {	userCount := len(v.users)	switch userCount {	case 0:		return nil	case 1:		return v.users[0]	default:		return v.users[dice.Roll(userCount)]	}}func (v *ServerSpec) IsValid() bool {	return v.valid.IsValid()}func (v *ServerSpec) Invalidate() {	v.valid.Invalidate()}
 |