| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- // Package vmess contains the implementation of VMess protocol and transportation.
- //
- // VMess contains both inbound and outbound connections. VMess inbound is usually used on servers
- // together with 'freedom' to talk to final destination, while VMess outbound is usually used on
- // clients with 'socks' for proxying.
- package vmess // import "github.com/v2ray/v2ray-core/proxy/vmess"
- import (
- "sync"
- "time"
- "github.com/v2ray/v2ray-core/common/dice"
- "github.com/v2ray/v2ray-core/common/protocol"
- "github.com/v2ray/v2ray-core/common/signal"
- )
- type Account struct {
- ID *protocol.ID
- AlterIDs []*protocol.ID
- }
- func (this *Account) AnyValidID() *protocol.ID {
- if len(this.AlterIDs) == 0 {
- return this.ID
- }
- return this.AlterIDs[dice.Roll(len(this.AlterIDs))]
- }
- func (this *Account) Equals(account protocol.Account) bool {
- vmessAccount, ok := account.(*Account)
- if !ok {
- return false
- }
- // TODO: handle AlterIds difference
- return this.ID.Equals(vmessAccount.ID)
- }
- const (
- updateIntervalSec = 10
- cacheDurationSec = 120
- )
- type idEntry struct {
- id *protocol.ID
- userIdx int
- lastSec protocol.Timestamp
- lastSecRemoval protocol.Timestamp
- }
- type TimedUserValidator struct {
- sync.RWMutex
- running bool
- validUsers []*protocol.User
- userHash map[[16]byte]*indexTimePair
- ids []*idEntry
- hasher protocol.IDHash
- cancel *signal.CancelSignal
- }
- type indexTimePair struct {
- index int
- timeSec protocol.Timestamp
- }
- func NewTimedUserValidator(hasher protocol.IDHash) protocol.UserValidator {
- tus := &TimedUserValidator{
- validUsers: make([]*protocol.User, 0, 16),
- userHash: make(map[[16]byte]*indexTimePair, 512),
- ids: make([]*idEntry, 0, 512),
- hasher: hasher,
- running: true,
- cancel: signal.NewCloseSignal(),
- }
- go tus.updateUserHash(updateIntervalSec * time.Second)
- return tus
- }
- func (this *TimedUserValidator) Release() {
- if !this.running {
- return
- }
- this.cancel.Cancel()
- <-this.cancel.WaitForDone()
- this.Lock()
- defer this.Unlock()
- if !this.running {
- return
- }
- this.running = false
- this.validUsers = nil
- this.userHash = nil
- this.ids = nil
- this.hasher = nil
- this.cancel = nil
- }
- func (this *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx int, entry *idEntry) {
- var hashValue [16]byte
- var hashValueRemoval [16]byte
- idHash := this.hasher(entry.id.Bytes())
- for entry.lastSec <= nowSec {
- idHash.Write(entry.lastSec.Bytes(nil))
- idHash.Sum(hashValue[:0])
- idHash.Reset()
- idHash.Write(entry.lastSecRemoval.Bytes(nil))
- idHash.Sum(hashValueRemoval[:0])
- idHash.Reset()
- this.Lock()
- this.userHash[hashValue] = &indexTimePair{idx, entry.lastSec}
- delete(this.userHash, hashValueRemoval)
- this.Unlock()
- entry.lastSec++
- entry.lastSecRemoval++
- }
- }
- func (this *TimedUserValidator) updateUserHash(interval time.Duration) {
- L:
- for {
- select {
- case now := <-time.After(interval):
- nowSec := protocol.Timestamp(now.Unix() + cacheDurationSec)
- for _, entry := range this.ids {
- this.generateNewHashes(nowSec, entry.userIdx, entry)
- }
- case <-this.cancel.WaitForCancel():
- break L
- }
- }
- this.cancel.Done()
- }
- func (this *TimedUserValidator) Add(user *protocol.User) error {
- idx := len(this.validUsers)
- this.validUsers = append(this.validUsers, user)
- account := user.Account.(*Account)
- nowSec := time.Now().Unix()
- entry := &idEntry{
- id: account.ID,
- userIdx: idx,
- lastSec: protocol.Timestamp(nowSec - cacheDurationSec),
- lastSecRemoval: protocol.Timestamp(nowSec - cacheDurationSec*3),
- }
- this.generateNewHashes(protocol.Timestamp(nowSec+cacheDurationSec), idx, entry)
- this.ids = append(this.ids, entry)
- for _, alterid := range account.AlterIDs {
- entry := &idEntry{
- id: alterid,
- userIdx: idx,
- lastSec: protocol.Timestamp(nowSec - cacheDurationSec),
- lastSecRemoval: protocol.Timestamp(nowSec - cacheDurationSec*3),
- }
- this.generateNewHashes(protocol.Timestamp(nowSec+cacheDurationSec), idx, entry)
- this.ids = append(this.ids, entry)
- }
- return nil
- }
- func (this *TimedUserValidator) Get(userHash []byte) (*protocol.User, protocol.Timestamp, bool) {
- defer this.RUnlock()
- this.RLock()
- if !this.running {
- return nil, 0, false
- }
- var fixedSizeHash [16]byte
- copy(fixedSizeHash[:], userHash)
- pair, found := this.userHash[fixedSizeHash]
- if found {
- return this.validUsers[pair.index], pair.timeSec, true
- }
- return nil, 0, false
- }
|