You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.3 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. package pex
  2. import (
  3. "time"
  4. "github.com/tendermint/tendermint/p2p"
  5. )
  6. // knownAddress tracks information about a known network address
  7. // that is used to determine how viable an address is.
  8. type knownAddress struct {
  9. Addr *p2p.NetAddress `json:"addr"`
  10. Src *p2p.NetAddress `json:"src"`
  11. Buckets []int `json:"buckets"`
  12. Attempts int32 `json:"attempts"`
  13. BucketType byte `json:"bucket_type"`
  14. LastAttempt time.Time `json:"last_attempt"`
  15. LastSuccess time.Time `json:"last_success"`
  16. LastBanTime time.Time `json:"last_ban_time"`
  17. }
  18. func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
  19. return &knownAddress{
  20. Addr: addr,
  21. Src: src,
  22. Attempts: 0,
  23. LastAttempt: time.Now(),
  24. BucketType: bucketTypeNew,
  25. Buckets: nil,
  26. }
  27. }
  28. func (ka *knownAddress) ID() p2p.ID {
  29. return ka.Addr.ID
  30. }
  31. func (ka *knownAddress) isOld() bool {
  32. return ka.BucketType == bucketTypeOld
  33. }
  34. func (ka *knownAddress) isNew() bool {
  35. return ka.BucketType == bucketTypeNew
  36. }
  37. func (ka *knownAddress) markAttempt() {
  38. now := time.Now()
  39. ka.LastAttempt = now
  40. ka.Attempts++
  41. }
  42. func (ka *knownAddress) markGood() {
  43. now := time.Now()
  44. ka.LastAttempt = now
  45. ka.Attempts = 0
  46. ka.LastSuccess = now
  47. }
  48. func (ka *knownAddress) ban() {
  49. ka.LastBanTime = time.Now()
  50. }
  51. func (ka *knownAddress) isBanned(banTime time.Duration) bool {
  52. if ka.LastBanTime.Add(banTime).Before(time.Now()) {
  53. return false
  54. }
  55. return true
  56. }
  57. func (ka *knownAddress) addBucketRef(bucketIdx int) int {
  58. for _, bucket := range ka.Buckets {
  59. if bucket == bucketIdx {
  60. // TODO refactor to return error?
  61. // log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
  62. return -1
  63. }
  64. }
  65. ka.Buckets = append(ka.Buckets, bucketIdx)
  66. return len(ka.Buckets)
  67. }
  68. func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
  69. buckets := []int{}
  70. for _, bucket := range ka.Buckets {
  71. if bucket != bucketIdx {
  72. buckets = append(buckets, bucket)
  73. }
  74. }
  75. if len(buckets) != len(ka.Buckets)-1 {
  76. // TODO refactor to return error?
  77. // log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
  78. return -1
  79. }
  80. ka.Buckets = buckets
  81. return len(ka.Buckets)
  82. }
  83. /*
  84. An address is bad if the address in question is a New address, has not been tried in the last
  85. minute, and meets one of the following criteria:
  86. 1) It claims to be from the future
  87. 2) It hasn't been seen in over a week
  88. 3) It has failed at least three times and never succeeded
  89. 4) It has failed ten times in the last week
  90. All addresses that meet these criteria are assumed to be worthless and not
  91. worth keeping hold of.
  92. */
  93. func (ka *knownAddress) isBad() bool {
  94. // Is Old --> good
  95. if ka.BucketType == bucketTypeOld {
  96. return false
  97. }
  98. // Has been attempted in the last minute --> good
  99. if ka.LastAttempt.After(time.Now().Add(-1 * time.Minute)) {
  100. return false
  101. }
  102. // TODO: From the future?
  103. // Too old?
  104. // TODO: should be a timestamp of last seen, not just last attempt
  105. if ka.LastAttempt.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
  106. return true
  107. }
  108. // Never succeeded?
  109. if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
  110. return true
  111. }
  112. // Hasn't succeeded in too long?
  113. if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
  114. ka.Attempts >= maxFailures {
  115. return true
  116. }
  117. return false
  118. }