userset.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package core
  2. import (
  3. "time"
  4. "github.com/v2ray/v2ray-core/log"
  5. )
  6. const (
  7. updateIntervalSec = 10
  8. cacheDurationSec = 120
  9. )
  10. type UserSet interface {
  11. AddUser(user User) error
  12. GetUser(timeHash []byte) (*ID, bool)
  13. }
  14. type TimedUserSet struct {
  15. validUserIds []ID
  16. userHashes map[string]int
  17. }
  18. type hashEntry struct {
  19. hash string
  20. timeSec int64
  21. }
  22. func NewTimedUserSet() UserSet {
  23. vuSet := new(TimedUserSet)
  24. vuSet.validUserIds = make([]ID, 0, 16)
  25. vuSet.userHashes = make(map[string]int)
  26. go vuSet.updateUserHash(time.Tick(updateIntervalSec * time.Second))
  27. return vuSet
  28. }
  29. func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
  30. now := time.Now().UTC()
  31. lastSec := now.Unix() - cacheDurationSec
  32. hash2Remove := make(chan hashEntry, cacheDurationSec*2*len(us.validUserIds))
  33. lastSec2Remove := now.Unix()
  34. log.Debug("Start updating")
  35. for {
  36. now := <-tick
  37. nowSec := now.UTC().Unix()
  38. remove2Sec := nowSec - cacheDurationSec
  39. log.Debug("remove2Sec %d, to %d", lastSec2Remove, remove2Sec)
  40. if remove2Sec > lastSec2Remove {
  41. for lastSec2Remove+1 < remove2Sec {
  42. entry := <-hash2Remove
  43. lastSec2Remove = entry.timeSec
  44. delete(us.userHashes, entry.hash)
  45. }
  46. }
  47. log.Debug("LastSec %d, to %d", lastSec, nowSec + updateIntervalSec)
  48. for lastSec < nowSec + cacheDurationSec {
  49. for idx, id := range us.validUserIds {
  50. idHash := id.TimeHash(lastSec)
  51. hash2Remove <- hashEntry{string(idHash), lastSec}
  52. log.Debug("Hash: %v", idHash)
  53. us.userHashes[string(idHash)] = idx
  54. }
  55. lastSec ++
  56. }
  57. }
  58. }
  59. func (us *TimedUserSet) AddUser(user User) error {
  60. id := user.Id
  61. us.validUserIds = append(us.validUserIds, id)
  62. return nil
  63. }
  64. func (us TimedUserSet) GetUser(userHash []byte) (*ID, bool) {
  65. idIndex, found := us.userHashes[string(userHash)]
  66. if found {
  67. return &us.validUserIds[idIndex], true
  68. }
  69. return nil, false
  70. }