knownaddress.go raw

   1  package addrmgr
   2  
   3  import (
   4  	"time"
   5  	
   6  	"github.com/p9c/p9/pkg/wire"
   7  )
   8  
   9  // KnownAddress tracks information about a known network address that is used to determine how viable an address is.
  10  type KnownAddress struct {
  11  	na          *wire.NetAddress
  12  	srcAddr     *wire.NetAddress
  13  	attempts    int
  14  	lastattempt time.Time
  15  	lastsuccess time.Time
  16  	tried       bool
  17  	refs        int // reference count of new buckets
  18  }
  19  
  20  // NetAddress returns the underlying wire.NetAddress associated with the known address.
  21  func (ka *KnownAddress) NetAddress() *wire.NetAddress {
  22  	return ka.na
  23  }
  24  
  25  // LastAttempt returns the last time the known address was attempted.
  26  func (ka *KnownAddress) LastAttempt() time.Time {
  27  	return ka.lastattempt
  28  }
  29  
  30  // chance returns the selection probability for a known address. The priority depends upon how recently the address has
  31  // been seen, how recently it was last attempted and how often attempts to connect to it have failed.
  32  func (ka *KnownAddress) chance() float64 {
  33  	now := time.Now()
  34  	lastAttempt := now.Sub(ka.lastattempt)
  35  	if lastAttempt < 0 {
  36  		lastAttempt = 0
  37  	}
  38  	c := 1.0
  39  	// Very recent attempts are less likely to be retried.
  40  	if lastAttempt < 10*time.Minute {
  41  		c *= 0.01
  42  	}
  43  	// Failed attempts deprioritise.
  44  	for i := ka.attempts; i > 0; i-- {
  45  		c /= 1.5
  46  	}
  47  	return c
  48  }
  49  
  50  // isBad returns true if the address in question has not been tried in the last minute and meets one of the following
  51  // criteria:
  52  //
  53  // 1) It claims to be from the future
  54  //
  55  // 2) It hasn't been seen in over a month
  56  //
  57  // 3) It has failed at least three times and never succeeded
  58  //
  59  // 4) It has failed ten times in the last week
  60  //
  61  // All addresses that meet these criteria are assumed to be worthless and not worth keeping hold of.
  62  func (ka *KnownAddress) isBad() bool {
  63  	if ka.lastattempt.After(time.Now().Add(-1 * time.Minute)) {
  64  		return false
  65  	}
  66  	// From the future?
  67  	if ka.na.Timestamp.After(time.Now().Add(10 * time.Minute)) {
  68  		return true
  69  	}
  70  	// Over a month old?
  71  	if ka.na.Timestamp.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
  72  		return true
  73  	}
  74  	// Never succeeded?
  75  	if ka.lastsuccess.IsZero() && ka.attempts >= numRetries {
  76  		return true
  77  	}
  78  	// Hasn't succeeded in too long?
  79  	if !ka.lastsuccess.After(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
  80  		ka.attempts >= maxFailures {
  81  		return true
  82  	}
  83  	return false
  84  }
  85