github.com/btcsuite/btcd@v0.24.0/addrmgr/knownaddress.go (about) 1 // Copyright (c) 2013-2014 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package addrmgr 6 7 import ( 8 "sync" 9 "time" 10 11 "github.com/btcsuite/btcd/wire" 12 ) 13 14 // KnownAddress tracks information about a known network address that is used 15 // to determine how viable an address is. 16 type KnownAddress struct { 17 mtx sync.RWMutex // na and lastattempt 18 na *wire.NetAddressV2 19 srcAddr *wire.NetAddressV2 20 attempts int 21 lastattempt time.Time 22 lastsuccess time.Time 23 tried bool 24 refs int // reference count of new buckets 25 } 26 27 // NetAddress returns the underlying wire.NetAddressV2 associated with the 28 // known address. 29 func (ka *KnownAddress) NetAddress() *wire.NetAddressV2 { 30 ka.mtx.RLock() 31 defer ka.mtx.RUnlock() 32 return ka.na 33 } 34 35 // LastAttempt returns the last time the known address was attempted. 36 func (ka *KnownAddress) LastAttempt() time.Time { 37 ka.mtx.RLock() 38 defer ka.mtx.RUnlock() 39 return ka.lastattempt 40 } 41 42 // Services returns the services supported by the peer with the known address. 43 func (ka *KnownAddress) Services() wire.ServiceFlag { 44 ka.mtx.RLock() 45 defer ka.mtx.RUnlock() 46 return ka.na.Services 47 } 48 49 // The unexported methods, chance and isBad, are used from within AddrManager 50 // where KnownAddress field access is synchronized via it's own Mutex. 51 52 // chance returns the selection probability for a known address. The priority 53 // depends upon how recently the address has been seen, how recently it was last 54 // attempted and how often attempts to connect to it have failed. 55 func (ka *KnownAddress) chance() float64 { 56 now := time.Now() 57 lastAttempt := now.Sub(ka.lastattempt) 58 59 if lastAttempt < 0 { 60 lastAttempt = 0 61 } 62 63 c := 1.0 64 65 // Very recent attempts are less likely to be retried. 66 if lastAttempt < 10*time.Minute { 67 c *= 0.01 68 } 69 70 // Failed attempts deprioritise. 71 for i := ka.attempts; i > 0; i-- { 72 c /= 1.5 73 } 74 75 return c 76 } 77 78 // isBad returns true if the address in question has not been tried in the last 79 // minute and meets one of the following criteria: 80 // 1) It claims to be from the future 81 // 2) It hasn't been seen in over a month 82 // 3) It has failed at least three times and never succeeded 83 // 4) It has failed ten times in the last week 84 // All addresses that meet these criteria are assumed to be worthless and not 85 // worth keeping hold of. 86 func (ka *KnownAddress) isBad() bool { 87 if ka.lastattempt.After(time.Now().Add(-1 * time.Minute)) { 88 return false 89 } 90 91 // From the future? 92 if ka.na.Timestamp.After(time.Now().Add(10 * time.Minute)) { 93 return true 94 } 95 96 // Over a month old? 97 if ka.na.Timestamp.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) { 98 return true 99 } 100 101 // Never succeeded? 102 if ka.lastsuccess.IsZero() && ka.attempts >= numRetries { 103 return true 104 } 105 106 // Hasn't succeeded in too long? 107 if !ka.lastsuccess.After(time.Now().Add(-1*minBadDays*time.Hour*24)) && 108 ka.attempts >= maxFailures { 109 return true 110 } 111 112 return false 113 }