aboutsummaryrefslogtreecommitdiffstats
path: root/p2p/dial.go
diff options
context:
space:
mode:
Diffstat (limited to 'p2p/dial.go')
-rw-r--r--p2p/dial.go28
1 files changed, 26 insertions, 2 deletions
diff --git a/p2p/dial.go b/p2p/dial.go
index bb3befab2..b77971396 100644
--- a/p2p/dial.go
+++ b/p2p/dial.go
@@ -38,6 +38,10 @@ const (
// once every few seconds.
lookupInterval = 4 * time.Second
+ // If no peers are found for this amount of time, the initial bootnodes are
+ // attempted to be connected.
+ fallbackInterval = 20 * time.Second
+
// Endpoint resolution is throttled with bounded backoff.
initialResolveDelay = 60 * time.Second
maxResolveDelay = time.Hour
@@ -57,6 +61,9 @@ type dialstate struct {
randomNodes []*discover.Node // filled from Table
static map[discover.NodeID]*dialTask
hist *dialHistory
+
+ start time.Time // time when the dialer was first used
+ bootnodes []*discover.Node // default dials when there are no peers
}
type discoverTable interface {
@@ -102,16 +109,18 @@ type waitExpireTask struct {
time.Duration
}
-func newDialState(static []*discover.Node, ntab discoverTable, maxdyn int, netrestrict *netutil.Netlist) *dialstate {
+func newDialState(static []*discover.Node, bootnodes []*discover.Node, ntab discoverTable, maxdyn int, netrestrict *netutil.Netlist) *dialstate {
s := &dialstate{
maxDynDials: maxdyn,
ntab: ntab,
netrestrict: netrestrict,
static: make(map[discover.NodeID]*dialTask),
dialing: make(map[discover.NodeID]connFlag),
+ bootnodes: make([]*discover.Node, len(bootnodes)),
randomNodes: make([]*discover.Node, maxdyn/2),
hist: new(dialHistory),
}
+ copy(s.bootnodes, bootnodes)
for _, n := range static {
s.addStatic(n)
}
@@ -130,6 +139,10 @@ func (s *dialstate) removeStatic(n *discover.Node) {
}
func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now time.Time) []task {
+ if s.start == (time.Time{}) {
+ s.start = now
+ }
+
var newtasks []task
addDial := func(flag connFlag, n *discover.Node) bool {
if err := s.checkDial(n, peers); err != nil {
@@ -169,7 +182,18 @@ func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now
newtasks = append(newtasks, t)
}
}
-
+ // If we don't have any peers whatsoever, try to dial a random bootnode. This
+ // scenario is useful for the testnet (and private networks) where the discovery
+ // table might be full of mostly bad peers, making it hard to find good ones.
+ if len(peers) == 0 && len(s.bootnodes) > 0 && needDynDials > 0 && now.Sub(s.start) > fallbackInterval {
+ bootnode := s.bootnodes[0]
+ s.bootnodes = append(s.bootnodes[:0], s.bootnodes[1:]...)
+ s.bootnodes = append(s.bootnodes, bootnode)
+
+ if addDial(dynDialedConn, bootnode) {
+ needDynDials--
+ }
+ }
// Use random nodes from the table for half of the necessary
// dynamic dials.
randomCandidates := needDynDials / 2