1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-23 10:37:09 -05:00
v2fly/proxy/vmess/outbound/receiver.go

137 lines
2.8 KiB
Go
Raw Normal View History

2015-12-04 19:16:21 -05:00
package outbound
import (
"sync"
"time"
2015-12-04 19:16:21 -05:00
2016-01-21 16:45:44 -05:00
"github.com/v2ray/v2ray-core/common/dice"
2015-12-04 19:16:21 -05:00
v2net "github.com/v2ray/v2ray-core/common/net"
proto "github.com/v2ray/v2ray-core/common/protocol"
2015-12-04 19:16:21 -05:00
)
2015-12-07 14:32:38 -05:00
type Receiver struct {
sync.RWMutex
2015-12-16 17:53:38 -05:00
Destination v2net.Destination
Accounts []*proto.User
2015-12-07 14:32:38 -05:00
}
func NewReceiver(dest v2net.Destination, users ...*proto.User) *Receiver {
return &Receiver{
Destination: dest,
Accounts: users,
}
}
func (this *Receiver) HasUser(user *proto.User) bool {
this.RLock()
defer this.RUnlock()
for _, u := range this.Accounts {
// TODO: handle AlterIds difference.
if u.ID.Equals(user.ID) {
return true
}
}
return false
}
func (this *Receiver) AddUser(user *proto.User) {
if this.HasUser(user) {
return
}
this.Lock()
this.Accounts = append(this.Accounts, user)
this.Unlock()
}
func (this *Receiver) PickUser() *proto.User {
2016-01-21 16:45:44 -05:00
return this.Accounts[dice.Roll(len(this.Accounts))]
}
type ExpiringReceiver struct {
*Receiver
until time.Time
}
func (this *ExpiringReceiver) Expired() bool {
2016-01-21 11:22:56 -05:00
return this.until.Before(time.Now())
}
2015-12-04 19:16:21 -05:00
type ReceiverManager struct {
receivers []*Receiver
detours []*ExpiringReceiver
detourAccess sync.RWMutex
2015-12-04 19:16:21 -05:00
}
2015-12-07 14:32:38 -05:00
func NewReceiverManager(receivers []*Receiver) *ReceiverManager {
2015-12-04 19:16:21 -05:00
return &ReceiverManager{
receivers: receivers,
detours: make([]*ExpiringReceiver, 0, 16),
2015-12-04 19:16:21 -05:00
}
}
func (this *ReceiverManager) AddDetour(rec *Receiver, availableMin byte) {
if availableMin < 2 {
return
}
this.detourAccess.RLock()
destExists := false
for _, r := range this.detours {
if r.Destination == rec.Destination {
destExists = true
// Destination exists, add new user if necessary
for _, u := range rec.Accounts {
r.AddUser(u)
}
2016-01-21 11:22:56 -05:00
break
}
}
this.detourAccess.RUnlock()
if !destExists {
2016-01-21 11:22:56 -05:00
expRec := &ExpiringReceiver{
Receiver: rec,
until: time.Now().Add(time.Duration(availableMin-1) * time.Minute),
}
this.detourAccess.Lock()
this.detours = append(this.detours, expRec)
this.detourAccess.Unlock()
}
}
func (this *ReceiverManager) pickDetour() *Receiver {
if len(this.detours) == 0 {
return nil
}
this.detourAccess.RLock()
2016-01-21 16:45:44 -05:00
idx := dice.Roll(len(this.detours))
rec := this.detours[idx]
this.detourAccess.RUnlock()
if rec.Expired() {
this.detourAccess.Lock()
detourLen := len(this.detours)
if detourLen > idx && this.detours[idx].Expired() {
this.detours[idx] = this.detours[detourLen-1]
this.detours = this.detours[:detourLen-1]
}
this.detourAccess.Unlock()
return nil
}
return rec.Receiver
}
func (this *ReceiverManager) pickStdReceiver() *Receiver {
2016-01-21 16:45:44 -05:00
return this.receivers[dice.Roll(len(this.receivers))]
}
2015-12-04 19:16:21 -05:00
func (this *ReceiverManager) PickReceiver() (v2net.Destination, *proto.User) {
rec := this.pickDetour()
if rec == nil {
rec = this.pickStdReceiver()
2015-12-04 19:16:21 -05:00
}
user := rec.PickUser()
return rec.Destination, user
2015-12-04 19:16:21 -05:00
}