From 36e8b4c82ed686d2e57ae39f74e71459c5114a63 Mon Sep 17 00:00:00 2001
From: David Hill <dhill@conformal.com>
Date: Thu, 10 Jul 2014 19:03:34 -0500
Subject: [PATCH] organize.

no objections from @davecgh
---
 addrmgr/addrmanager.go  | 230 ++++++++++++----------------------------
 addrmgr/knownaddress.go | 101 ++++++++++++++++++
 2 files changed, 171 insertions(+), 160 deletions(-)
 create mode 100644 addrmgr/knownaddress.go

diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go
index 1c19b476..16b026bd 100644
--- a/addrmgr/addrmanager.go
+++ b/addrmgr/addrmanager.go
@@ -26,6 +26,71 @@ import (
 	"github.com/conformal/btcwire"
 )
 
+// AddrManager provides a concurrency safe address manager for caching potential
+// peers on the bitcoin network.
+type AddrManager struct {
+	mtx            sync.Mutex
+	dataDir        string
+	lookupFunc     func(string) ([]net.IP, error)
+	rand           *rand.Rand
+	key            [32]byte
+	addrIndex      map[string]*knownAddress // address key to ka for all addrs.
+	addrNew        [newBucketCount]map[string]*knownAddress
+	addrTried      [triedBucketCount]*list.List
+	started        int32
+	shutdown       int32
+	wg             sync.WaitGroup
+	quit           chan struct{}
+	nTried         int
+	nNew           int
+	lamtx          sync.Mutex
+	localAddresses map[string]*localAddress
+}
+
+type serializedKnownAddress struct {
+	Addr        string
+	Src         string
+	Attempts    int
+	TimeStamp   int64
+	LastAttempt int64
+	LastSuccess int64
+	// no refcount or tried, that is available from context.
+}
+
+type serializedAddrManager struct {
+	Version      int
+	Key          [32]byte
+	Addresses    []*serializedKnownAddress
+	NewBuckets   [newBucketCount][]string // string is NetAddressKey
+	TriedBuckets [triedBucketCount][]string
+}
+
+type localAddress struct {
+	na    *btcwire.NetAddress
+	score AddressPriority
+}
+
+// AddressPriority type is used to describe the heirarchy of local address
+// discovery methods.
+type AddressPriority int
+
+const (
+	// InterfacePrio signifies the address is on a local interface
+	InterfacePrio AddressPriority = iota
+
+	// BoundPrio signifies the address has been explicity bounded to.
+	BoundPrio
+
+	// UpnpPrio signifies the address was obtained from UPnP.
+	UpnpPrio
+
+	// HTTPPrio signifies the address was obtained from an external HTTP service.
+	HTTPPrio
+
+	// ManualPrio signifies the address was provided by --externalip.
+	ManualPrio
+)
+
 const (
 	// needAddressThreshold is the number of addresses under which the
 	// address manager will claim to need more addresses.
@@ -94,117 +159,6 @@ const (
 	serialisationVersion = 1
 )
 
-// knownAddress tracks information about a known network address that is used
-// to determine how viable an address is.
-type knownAddress struct {
-	na          *btcwire.NetAddress
-	srcAddr     *btcwire.NetAddress
-	attempts    int
-	lastattempt time.Time
-	lastsuccess time.Time
-	tried       bool
-	refs        int // reference count of new buckets
-}
-
-// NetAddress returns the underlying btcwire.NetAddress associated with the
-// known address.
-func (ka *knownAddress) NetAddress() *btcwire.NetAddress {
-	return ka.na
-}
-
-// LastAttempt returns the last time the known address was attempted.
-func (ka *knownAddress) LastAttempt() time.Time {
-	return ka.lastattempt
-}
-
-// bad returns true if the address in question 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 month
-// 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.
-func bad(ka *knownAddress) bool {
-	if ka.lastattempt.After(time.Now().Add(-1 * time.Minute)) {
-		return false
-	}
-
-	// From the future?
-	if ka.na.Timestamp.After(time.Now().Add(10 * time.Minute)) {
-		return true
-	}
-
-	// Over a month old?
-	if ka.na.Timestamp.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?
-	if !ka.lastsuccess.After(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
-		ka.attempts >= maxFailures {
-		return true
-	}
-
-	return false
-}
-
-// chance returns the selection probability for a known address.  The priority
-// depends upon how recently the address has been seen, how recently it was last
-// attempted and how often attempts to connect to it have failed.
-func chance(ka *knownAddress) float64 {
-	now := time.Now()
-	lastSeen := now.Sub(ka.na.Timestamp)
-	lastAttempt := now.Sub(ka.lastattempt)
-
-	if lastSeen < 0 {
-		lastSeen = 0
-	}
-	if lastAttempt < 0 {
-		lastAttempt = 0
-	}
-
-	c := 600.0 / (600.0 + lastSeen.Seconds())
-
-	// Very recent attempts are less likely to be retried.
-	if lastAttempt > 10*time.Minute {
-		c *= 0.01
-	}
-
-	// Failed attempts deprioritise.
-	for i := ka.attempts; i < 0; i++ {
-		c /= 1.5
-	}
-
-	return c
-}
-
-// AddrManager provides a concurrency safe address manager for caching potential
-// peers on the bitcoin network.
-type AddrManager struct {
-	mtx            sync.Mutex
-	dataDir        string
-	lookupFunc     func(string) ([]net.IP, error)
-	rand           *rand.Rand
-	key            [32]byte
-	addrIndex      map[string]*knownAddress // address key to ka for all addrs.
-	addrNew        [newBucketCount]map[string]*knownAddress
-	addrTried      [triedBucketCount]*list.List
-	started        int32
-	shutdown       int32
-	wg             sync.WaitGroup
-	quit           chan struct{}
-	nTried         int
-	nNew           int
-	lamtx          sync.Mutex
-	localAddresses map[string]*localAddress
-}
-
 // updateAddress is a helper function to either update an address already known
 // to the address manager, or to add the address if not already known.
 func (a *AddrManager) updateAddress(netAddr, srcAddr *btcwire.NetAddress) {
@@ -273,7 +227,7 @@ func (a *AddrManager) updateAddress(netAddr, srcAddr *btcwire.NetAddress) {
 
 	// Enforce max addresses.
 	if len(a.addrNew[bucket]) > newBucketSize {
-		log.Tracef("new bucket is full, expiring old ")
+		log.Tracef("new bucket is full, expiring old")
 		a.expireNew(bucket)
 	}
 
@@ -295,7 +249,7 @@ func (a *AddrManager) expireNew(bucket int) {
 	// use that information instead.
 	var oldest *knownAddress
 	for k, v := range a.addrNew[bucket] {
-		if bad(v) {
+		if v.isBad() {
 			log.Tracef("expiring bad address %v", k)
 			delete(a.addrNew[bucket], k)
 			v.refs--
@@ -303,7 +257,7 @@ func (a *AddrManager) expireNew(bucket int) {
 				a.nNew--
 				delete(a.addrIndex, k)
 			}
-			return
+			continue
 		}
 		if oldest == nil {
 			oldest = v
@@ -404,24 +358,6 @@ out:
 	log.Trace("Address handler done")
 }
 
-type serializedKnownAddress struct {
-	Addr        string
-	Src         string
-	Attempts    int
-	TimeStamp   int64
-	LastAttempt int64
-	LastSuccess int64
-	// no refcount or tried, that is available from context.
-}
-
-type serializedAddrManager struct {
-	Version      int
-	Key          [32]byte
-	Addresses    []*serializedKnownAddress
-	NewBuckets   [newBucketCount][]string // string is NetAddressKey
-	TriedBuckets [triedBucketCount][]string
-}
-
 // savePeers saves all the known addresses to a file so they can be read back
 // in at next run.
 func (a *AddrManager) savePeers() {
@@ -846,7 +782,7 @@ func (a *AddrManager) GetAddress(class string, newBias int) *knownAddress {
 			}
 			ka := e.Value.(*knownAddress)
 			randval := a.rand.Intn(large)
-			if float64(randval) < (factor * chance(ka) * float64(large)) {
+			if float64(randval) < (factor * ka.chance() * float64(large)) {
 				log.Tracef("Selected %v from tried bucket",
 					NetAddressKey(ka.na))
 				return ka
@@ -874,7 +810,7 @@ func (a *AddrManager) GetAddress(class string, newBias int) *knownAddress {
 				nth--
 			}
 			randval := a.rand.Intn(large)
-			if float64(randval) < (factor * chance(ka) * float64(large)) {
+			if float64(randval) < (factor * ka.chance() * float64(large)) {
 				log.Tracef("Selected %v from new bucket",
 					NetAddressKey(ka.na))
 				return ka
@@ -1017,32 +953,6 @@ func (a *AddrManager) Good(addr *btcwire.NetAddress) {
 	a.addrNew[newBucket][rmkey] = rmka
 }
 
-// AddressPriority type is used to describe the heirarchy of local address
-// discovery methods.
-type AddressPriority int
-
-const (
-	// InterfacePrio signifies the address is on a local interface
-	InterfacePrio AddressPriority = iota
-
-	// BoundPrio signifies the address has been explicity bounded to.
-	BoundPrio
-
-	// UpnpPrio signifies the address was obtained from UPnP.
-	UpnpPrio
-
-	// HTTPPrio signifies the address was obtained from an external HTTP service.
-	HTTPPrio
-
-	// ManualPrio signifies the address was provided by --externalip.
-	ManualPrio
-)
-
-type localAddress struct {
-	na    *btcwire.NetAddress
-	score AddressPriority
-}
-
 // AddLocalAddress adds na to the list of known local addresses to advertise
 // with the given priority.
 func (a *AddrManager) AddLocalAddress(na *btcwire.NetAddress, priority AddressPriority) error {
diff --git a/addrmgr/knownaddress.go b/addrmgr/knownaddress.go
new file mode 100644
index 00000000..f027fc17
--- /dev/null
+++ b/addrmgr/knownaddress.go
@@ -0,0 +1,101 @@
+// Copyright (c) 2013-2014 Conformal Systems LLC.
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package addrmgr
+
+import (
+	"time"
+
+	"github.com/conformal/btcwire"
+)
+
+// knownAddress tracks information about a known network address that is used
+// to determine how viable an address is.
+type knownAddress struct {
+	na          *btcwire.NetAddress
+	srcAddr     *btcwire.NetAddress
+	attempts    int
+	lastattempt time.Time
+	lastsuccess time.Time
+	tried       bool
+	refs        int // reference count of new buckets
+}
+
+// NetAddress returns the underlying btcwire.NetAddress associated with the
+// known address.
+func (ka *knownAddress) NetAddress() *btcwire.NetAddress {
+	return ka.na
+}
+
+// LastAttempt returns the last time the known address was attempted.
+func (ka *knownAddress) LastAttempt() time.Time {
+	return ka.lastattempt
+}
+
+// chance returns the selection probability for a known address.  The priority
+// depends upon how recently the address has been seen, how recently it was last
+// attempted and how often attempts to connect to it have failed.
+func (ka *knownAddress) chance() float64 {
+	now := time.Now()
+	lastSeen := now.Sub(ka.na.Timestamp)
+	lastAttempt := now.Sub(ka.lastattempt)
+
+	if lastSeen < 0 {
+		lastSeen = 0
+	}
+	if lastAttempt < 0 {
+		lastAttempt = 0
+	}
+
+	c := 600.0 / (600.0 + lastSeen.Seconds())
+
+	// Very recent attempts are less likely to be retried.
+	if lastAttempt > 10*time.Minute {
+		c *= 0.01
+	}
+
+	// Failed attempts deprioritise.
+	for i := ka.attempts; i < 0; i++ {
+		c /= 1.5
+	}
+
+	return c
+}
+
+// isBad returns true if the address in question 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 month
+// 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.
+func (ka *knownAddress) isBad() bool {
+	if ka.lastattempt.After(time.Now().Add(-1 * time.Minute)) {
+		return false
+	}
+
+	// From the future?
+	if ka.na.Timestamp.After(time.Now().Add(10 * time.Minute)) {
+		return true
+	}
+
+	// Over a month old?
+	if ka.na.Timestamp.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?
+	if !ka.lastsuccess.After(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
+		ka.attempts >= maxFailures {
+		return true
+	}
+
+	return false
+}