vmess.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Package vmess contains the implementation of VMess protocol and transportation.
  2. //
  3. // VMess contains both inbound and outbound connections. VMess inbound is usually used on servers
  4. // together with 'freedom' to talk to final destination, while VMess outbound is usually used on
  5. // clients with 'socks' for proxying.
  6. package vmess
  7. import (
  8. "context"
  9. "sync"
  10. "time"
  11. "v2ray.com/core/common/protocol"
  12. )
  13. const (
  14. updateIntervalSec = 10
  15. cacheDurationSec = 120
  16. )
  17. type idEntry struct {
  18. id *protocol.ID
  19. userIdx int
  20. lastSec protocol.Timestamp
  21. lastSecRemoval protocol.Timestamp
  22. }
  23. type TimedUserValidator struct {
  24. sync.RWMutex
  25. ctx context.Context
  26. validUsers []*protocol.User
  27. userHash map[[16]byte]*indexTimePair
  28. ids []*idEntry
  29. hasher protocol.IDHash
  30. }
  31. type indexTimePair struct {
  32. index int
  33. timeSec protocol.Timestamp
  34. }
  35. func NewTimedUserValidator(ctx context.Context, hasher protocol.IDHash) protocol.UserValidator {
  36. tus := &TimedUserValidator{
  37. ctx: ctx,
  38. validUsers: make([]*protocol.User, 0, 16),
  39. userHash: make(map[[16]byte]*indexTimePair, 512),
  40. ids: make([]*idEntry, 0, 512),
  41. hasher: hasher,
  42. }
  43. go tus.updateUserHash(updateIntervalSec * time.Second)
  44. return tus
  45. }
  46. func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx int, entry *idEntry) {
  47. var hashValue [16]byte
  48. var hashValueRemoval [16]byte
  49. idHash := v.hasher(entry.id.Bytes())
  50. for entry.lastSec <= nowSec {
  51. idHash.Write(entry.lastSec.Bytes(nil))
  52. idHash.Sum(hashValue[:0])
  53. idHash.Reset()
  54. idHash.Write(entry.lastSecRemoval.Bytes(nil))
  55. idHash.Sum(hashValueRemoval[:0])
  56. idHash.Reset()
  57. v.userHash[hashValue] = &indexTimePair{idx, entry.lastSec}
  58. delete(v.userHash, hashValueRemoval)
  59. entry.lastSec++
  60. entry.lastSecRemoval++
  61. }
  62. }
  63. func (v *TimedUserValidator) updateUserHash(interval time.Duration) {
  64. for {
  65. select {
  66. case now := <-time.After(interval):
  67. nowSec := protocol.Timestamp(now.Unix() + cacheDurationSec)
  68. v.Lock()
  69. for _, entry := range v.ids {
  70. v.generateNewHashes(nowSec, entry.userIdx, entry)
  71. }
  72. v.Unlock()
  73. case <-v.ctx.Done():
  74. return
  75. }
  76. }
  77. }
  78. func (v *TimedUserValidator) Add(user *protocol.User) error {
  79. v.Lock()
  80. defer v.Unlock()
  81. idx := len(v.validUsers)
  82. v.validUsers = append(v.validUsers, user)
  83. rawAccount, err := user.GetTypedAccount()
  84. if err != nil {
  85. return err
  86. }
  87. account := rawAccount.(*InternalAccount)
  88. nowSec := time.Now().Unix()
  89. entry := &idEntry{
  90. id: account.ID,
  91. userIdx: idx,
  92. lastSec: protocol.Timestamp(nowSec - cacheDurationSec),
  93. lastSecRemoval: protocol.Timestamp(nowSec - cacheDurationSec*3),
  94. }
  95. v.generateNewHashes(protocol.Timestamp(nowSec+cacheDurationSec), idx, entry)
  96. v.ids = append(v.ids, entry)
  97. for _, alterid := range account.AlterIDs {
  98. entry := &idEntry{
  99. id: alterid,
  100. userIdx: idx,
  101. lastSec: protocol.Timestamp(nowSec - cacheDurationSec),
  102. lastSecRemoval: protocol.Timestamp(nowSec - cacheDurationSec*3),
  103. }
  104. v.generateNewHashes(protocol.Timestamp(nowSec+cacheDurationSec), idx, entry)
  105. v.ids = append(v.ids, entry)
  106. }
  107. return nil
  108. }
  109. func (v *TimedUserValidator) Get(userHash []byte) (*protocol.User, protocol.Timestamp, bool) {
  110. defer v.RUnlock()
  111. v.RLock()
  112. var fixedSizeHash [16]byte
  113. copy(fixedSizeHash[:], userHash)
  114. pair, found := v.userHash[fixedSizeHash]
  115. if found {
  116. return v.validUsers[pair.index], pair.timeSec, true
  117. }
  118. return nil, 0, false
  119. }