|
|
- package pex
-
- import (
- "time"
-
- "github.com/tendermint/tendermint/p2p"
- )
-
- // knownAddress tracks information about a known network address
- // that is used to determine how viable an address is.
- type knownAddress struct {
- Addr *p2p.NetAddress `json:"addr"`
- Src *p2p.NetAddress `json:"src"`
- Attempts int32 `json:"attempts"`
- LastAttempt time.Time `json:"last_attempt"`
- LastSuccess time.Time `json:"last_success"`
- BucketType byte `json:"bucket_type"`
- Buckets []int `json:"buckets"`
- }
-
- func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
- return &knownAddress{
- Addr: addr,
- Src: src,
- Attempts: 0,
- LastAttempt: time.Now(),
- BucketType: bucketTypeNew,
- Buckets: nil,
- }
- }
-
- func (ka *knownAddress) ID() p2p.ID {
- return ka.Addr.ID
- }
-
- func (ka *knownAddress) copy() *knownAddress {
- return &knownAddress{
- Addr: ka.Addr,
- Src: ka.Src,
- Attempts: ka.Attempts,
- LastAttempt: ka.LastAttempt,
- LastSuccess: ka.LastSuccess,
- BucketType: ka.BucketType,
- Buckets: ka.Buckets,
- }
- }
-
- func (ka *knownAddress) isOld() bool {
- return ka.BucketType == bucketTypeOld
- }
-
- func (ka *knownAddress) isNew() bool {
- return ka.BucketType == bucketTypeNew
- }
-
- func (ka *knownAddress) markAttempt() {
- now := time.Now()
- ka.LastAttempt = now
- ka.Attempts++
- }
-
- func (ka *knownAddress) markGood() {
- now := time.Now()
- ka.LastAttempt = now
- ka.Attempts = 0
- ka.LastSuccess = now
- }
-
- func (ka *knownAddress) addBucketRef(bucketIdx int) int {
- for _, bucket := range ka.Buckets {
- if bucket == bucketIdx {
- // TODO refactor to return error?
- // log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
- return -1
- }
- }
- ka.Buckets = append(ka.Buckets, bucketIdx)
- return len(ka.Buckets)
- }
-
- func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
- buckets := []int{}
- for _, bucket := range ka.Buckets {
- if bucket != bucketIdx {
- buckets = append(buckets, bucket)
- }
- }
- if len(buckets) != len(ka.Buckets)-1 {
- // TODO refactor to return error?
- // log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
- return -1
- }
- ka.Buckets = buckets
- return len(ka.Buckets)
- }
-
- /*
- An address is bad if the address in question is a New address, has not been tried in the last
- minute, and meets one of the following criteria:
-
- 1) It claims to be from the future
- 2) It hasn't been seen in over a week
- 3) It has failed at least three times and never succeeded
- 4) It has failed ten times in the last week
-
- All addresses that meet these criteria are assumed to be worthless and not
- worth keeping hold of.
-
- XXX: so a good peer needs us to call MarkGood before the conditions above are reached!
- */
- func (ka *knownAddress) isBad() bool {
- // Is Old --> good
- if ka.BucketType == bucketTypeOld {
- return false
- }
-
- // Has been attempted in the last minute --> good
- if ka.LastAttempt.Before(time.Now().Add(-1 * time.Minute)) {
- return false
- }
-
- // Too old?
- // XXX: does this mean if we've kept a connection up for this long we'll disconnect?!
- // and shouldn't it be .Before ?
- if ka.LastAttempt.After(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
- return true
- }
-
- // Never succeeded?
- if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
- return true
- }
-
- // Hasn't succeeded in too long?
- // XXX: does this mean if we've kept a connection up for this long we'll disconnect?!
- if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
- ka.Attempts >= maxFailures {
- return true
- }
-
- return false
- }
|