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