userset.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package protocol
  2. import (
  3. "container/heap"
  4. "time"
  5. "github.com/v2ray/v2ray-core/log"
  6. )
  7. const (
  8. updateIntervalSec = 10
  9. cacheDurationSec = 120
  10. )
  11. type UserSet interface {
  12. AddUser(user User) error
  13. GetUser(timeHash []byte) (*ID, int64, bool)
  14. }
  15. type TimedUserSet struct {
  16. validUserIds []ID
  17. userHashes map[string]indexTimePair
  18. hash2Remove hashEntrySet
  19. }
  20. type indexTimePair struct {
  21. index int
  22. timeSec int64
  23. }
  24. type hashEntry struct {
  25. hash string
  26. timeSec int64
  27. }
  28. type hashEntrySet []*hashEntry
  29. func (set hashEntrySet) Len() int {
  30. return len(set)
  31. }
  32. func (set hashEntrySet) Less(i, j int) bool {
  33. return set[i].timeSec < set[j].timeSec
  34. }
  35. func (set hashEntrySet) Swap(i, j int) {
  36. tmp := set[i]
  37. set[i] = set[j]
  38. set[j] = tmp
  39. }
  40. func (set *hashEntrySet) Push(value interface{}) {
  41. entry := value.(*hashEntry)
  42. *set = append(*set, entry)
  43. }
  44. func (set *hashEntrySet) Pop() interface{} {
  45. old := *set
  46. n := len(old)
  47. v := old[n-1]
  48. *set = old[:n-1]
  49. return v
  50. }
  51. func NewTimedUserSet() UserSet {
  52. vuSet := new(TimedUserSet)
  53. vuSet.validUserIds = make([]ID, 0, 16)
  54. vuSet.userHashes = make(map[string]indexTimePair)
  55. vuSet.hash2Remove = make(hashEntrySet, 0, cacheDurationSec*10)
  56. go vuSet.updateUserHash(time.Tick(updateIntervalSec * time.Second))
  57. return vuSet
  58. }
  59. func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id ID) {
  60. idHash := NewTimeHash(HMACHash{})
  61. for lastSec < nowSec+cacheDurationSec {
  62. idHash := idHash.Hash(id.Bytes, lastSec)
  63. log.Debug("Valid User Hash: %v", idHash)
  64. heap.Push(&us.hash2Remove, &hashEntry{string(idHash), lastSec})
  65. us.userHashes[string(idHash)] = indexTimePair{idx, lastSec}
  66. lastSec++
  67. }
  68. }
  69. func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
  70. now := time.Now().UTC()
  71. lastSec := now.Unix()
  72. lastSec2Remove := now.Unix()
  73. for {
  74. now := <-tick
  75. nowSec := now.UTC().Unix()
  76. remove2Sec := nowSec - cacheDurationSec
  77. if remove2Sec > lastSec2Remove {
  78. for lastSec2Remove+1 < remove2Sec {
  79. front := heap.Pop(&us.hash2Remove)
  80. entry := front.(*hashEntry)
  81. lastSec2Remove = entry.timeSec
  82. delete(us.userHashes, entry.hash)
  83. }
  84. }
  85. for idx, id := range us.validUserIds {
  86. us.generateNewHashes(lastSec, nowSec, idx, id)
  87. }
  88. }
  89. }
  90. func (us *TimedUserSet) AddUser(user User) error {
  91. id := user.Id
  92. idx := len(us.validUserIds)
  93. us.validUserIds = append(us.validUserIds, id)
  94. nowSec := time.Now().UTC().Unix()
  95. lastSec := nowSec - cacheDurationSec
  96. us.generateNewHashes(lastSec, nowSec, idx, id)
  97. return nil
  98. }
  99. func (us TimedUserSet) GetUser(userHash []byte) (*ID, int64, bool) {
  100. pair, found := us.userHashes[string(userHash)]
  101. if found {
  102. return &us.validUserIds[pair.index], pair.timeSec, true
  103. }
  104. return nil, 0, false
  105. }