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.

142 lines
3.5 KiB

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. Attempts int32 `json:"attempts"`
  12. LastAttempt time.Time `json:"last_attempt"`
  13. LastSuccess time.Time `json:"last_success"`
  14. BucketType byte `json:"bucket_type"`
  15. Buckets []int `json:"buckets"`
  16. }
  17. func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
  18. return &knownAddress{
  19. Addr: addr,
  20. Src: src,
  21. Attempts: 0,
  22. LastAttempt: time.Now(),
  23. BucketType: bucketTypeNew,
  24. Buckets: nil,
  25. }
  26. }
  27. func (ka *knownAddress) ID() p2p.ID {
  28. return ka.Addr.ID
  29. }
  30. func (ka *knownAddress) copy() *knownAddress {
  31. return &knownAddress{
  32. Addr: ka.Addr,
  33. Src: ka.Src,
  34. Attempts: ka.Attempts,
  35. LastAttempt: ka.LastAttempt,
  36. LastSuccess: ka.LastSuccess,
  37. BucketType: ka.BucketType,
  38. Buckets: ka.Buckets,
  39. }
  40. }
  41. func (ka *knownAddress) isOld() bool {
  42. return ka.BucketType == bucketTypeOld
  43. }
  44. func (ka *knownAddress) isNew() bool {
  45. return ka.BucketType == bucketTypeNew
  46. }
  47. func (ka *knownAddress) markAttempt() {
  48. now := time.Now()
  49. ka.LastAttempt = now
  50. ka.Attempts += 1
  51. }
  52. func (ka *knownAddress) markGood() {
  53. now := time.Now()
  54. ka.LastAttempt = now
  55. ka.Attempts = 0
  56. ka.LastSuccess = now
  57. }
  58. func (ka *knownAddress) addBucketRef(bucketIdx int) int {
  59. for _, bucket := range ka.Buckets {
  60. if bucket == bucketIdx {
  61. // TODO refactor to return error?
  62. // log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
  63. return -1
  64. }
  65. }
  66. ka.Buckets = append(ka.Buckets, bucketIdx)
  67. return len(ka.Buckets)
  68. }
  69. func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
  70. buckets := []int{}
  71. for _, bucket := range ka.Buckets {
  72. if bucket != bucketIdx {
  73. buckets = append(buckets, bucket)
  74. }
  75. }
  76. if len(buckets) != len(ka.Buckets)-1 {
  77. // TODO refactor to return error?
  78. // log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
  79. return -1
  80. }
  81. ka.Buckets = buckets
  82. return len(ka.Buckets)
  83. }
  84. /*
  85. An address is bad if the address in question is a New address, has not been tried in the last
  86. minute, and meets one of the following criteria:
  87. 1) It claims to be from the future
  88. 2) It hasn't been seen in over a week
  89. 3) It has failed at least three times and never succeeded
  90. 4) It has failed ten times in the last week
  91. All addresses that meet these criteria are assumed to be worthless and not
  92. worth keeping hold of.
  93. XXX: so a good peer needs us to call MarkGood before the conditions above are reached!
  94. */
  95. func (ka *knownAddress) isBad() bool {
  96. // Is Old --> good
  97. if ka.BucketType == bucketTypeOld {
  98. return false
  99. }
  100. // Has been attempted in the last minute --> good
  101. if ka.LastAttempt.Before(time.Now().Add(-1 * time.Minute)) {
  102. return false
  103. }
  104. // Too old?
  105. // XXX: does this mean if we've kept a connection up for this long we'll disconnect?!
  106. // and shouldn't it be .Before ?
  107. if ka.LastAttempt.After(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
  108. return true
  109. }
  110. // Never succeeded?
  111. if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
  112. return true
  113. }
  114. // Hasn't succeeded in too long?
  115. // XXX: does this mean if we've kept a connection up for this long we'll disconnect?!
  116. if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
  117. ka.Attempts >= maxFailures {
  118. return true
  119. }
  120. return false
  121. }