diff options
Diffstat (limited to 'p2p/dial.go')
-rw-r--r-- | p2p/dial.go | 28 |
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 |