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