1package dht
2
3import (
4	"context"
5	"time"
6
7	"github.com/libp2p/go-libp2p-core/peer"
8
9	"github.com/multiformats/go-multiaddr"
10)
11
12// DefaultBootstrapPeers is a set of public DHT bootstrap peers provided by libp2p.
13var DefaultBootstrapPeers []multiaddr.Multiaddr
14
15// Minimum number of peers in the routing table. If we drop below this and we
16// see a new peer, we trigger a bootstrap round.
17var minRTRefreshThreshold = 10
18
19const (
20	periodicBootstrapInterval = 2 * time.Minute
21	maxNBoostrappers          = 2
22)
23
24func init() {
25	for _, s := range []string{
26		"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
27		"/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
28		"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
29		"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
30		"/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io
31	} {
32		ma, err := multiaddr.NewMultiaddr(s)
33		if err != nil {
34			panic(err)
35		}
36		DefaultBootstrapPeers = append(DefaultBootstrapPeers, ma)
37	}
38}
39
40// GetDefaultBootstrapPeerAddrInfos returns the peer.AddrInfos for the default
41// bootstrap peers so we can use these for initializing the DHT by passing these to the
42// BootstrapPeers(...) option.
43func GetDefaultBootstrapPeerAddrInfos() []peer.AddrInfo {
44	ds := make([]peer.AddrInfo, 0, len(DefaultBootstrapPeers))
45
46	for i := range DefaultBootstrapPeers {
47		info, err := peer.AddrInfoFromP2pAddr(DefaultBootstrapPeers[i])
48		if err != nil {
49			logger.Errorw("failed to convert bootstrapper address to peer addr info", "address",
50				DefaultBootstrapPeers[i].String(), err, "err")
51			continue
52		}
53		ds = append(ds, *info)
54	}
55	return ds
56}
57
58// Bootstrap tells the DHT to get into a bootstrapped state satisfying the
59// IpfsRouter interface.
60func (dht *IpfsDHT) Bootstrap(ctx context.Context) error {
61	dht.fixRTIfNeeded()
62	dht.rtRefreshManager.RefreshNoWait()
63	return nil
64}
65
66// RefreshRoutingTable tells the DHT to refresh it's routing tables.
67//
68// The returned channel will block until the refresh finishes, then yield the
69// error and close. The channel is buffered and safe to ignore.
70func (dht *IpfsDHT) RefreshRoutingTable() <-chan error {
71	return dht.rtRefreshManager.Refresh(false)
72}
73
74// ForceRefresh acts like RefreshRoutingTable but forces the DHT to refresh all
75// buckets in the Routing Table irrespective of when they were last refreshed.
76//
77// The returned channel will block until the refresh finishes, then yield the
78// error and close. The channel is buffered and safe to ignore.
79func (dht *IpfsDHT) ForceRefresh() <-chan error {
80	return dht.rtRefreshManager.Refresh(true)
81}
82