1+ package nesting
2+
3+ import (
4+ "context"
5+ "fmt"
6+ "github.com/hashicorp/go-multierror"
7+ "github.com/ipfs/go-cid"
8+ ci "github.com/libp2p/go-libp2p-core/crypto"
9+ "github.com/libp2p/go-libp2p-core/routing"
10+ "github.com/pkg/errors"
11+
12+ "github.com/libp2p/go-libp2p-core/host"
13+ "github.com/libp2p/go-libp2p-core/peer"
14+
15+ "github.com/libp2p/go-libp2p-kad-dht"
16+ )
17+
18+ // DHT implements the routing interface to
19+ type DHT struct {
20+ Inner , Outer * dht.IpfsDHT
21+ }
22+
23+ // Assert that IPFS assumptions about interfaces aren't broken. These aren't a
24+ // guarantee, but we can use them to aid refactoring.
25+ var (
26+ _ routing.ContentRouting = (* DHT )(nil )
27+ _ routing.Routing = (* DHT )(nil )
28+ _ routing.PeerRouting = (* DHT )(nil )
29+ _ routing.PubKeyFetcher = (* DHT )(nil )
30+ _ routing.ValueStore = (* DHT )(nil )
31+ )
32+
33+ func New (ctx context.Context , h host.Host , innerOptions []dht.Option , outerOptions []dht.Option ) (* DHT , error ) {
34+ inner , err := dht .New (ctx , h , innerOptions ... )
35+ if err != nil {
36+ return nil , err
37+ }
38+
39+ outer , err := dht .New (ctx , h , outerOptions ... )
40+ if err != nil {
41+ return nil , err
42+ }
43+
44+ d := & DHT {
45+ Inner : inner ,
46+ Outer : outer ,
47+ }
48+
49+ return d , nil
50+ }
51+
52+ func (dht * DHT ) GetClosestPeers (ctx context.Context , key string ) ([]peer.ID , error ) {
53+ var innerResult []peer.ID
54+ peerCh , err := dht .Inner .GetClosestPeersSeeded (ctx , key , nil )
55+ if err == nil {
56+ innerResult = getPeersFromCh (peerCh )
57+ }
58+
59+ outerResultCh , err := dht .Outer .GetClosestPeersSeeded (ctx , key , innerResult )
60+ if err != nil {
61+ return nil , err
62+ }
63+
64+ return getPeersFromCh (outerResultCh ), nil
65+ }
66+
67+ func getPeersFromCh (peerCh <- chan peer.ID ) []peer.ID {
68+ var peers []peer.ID
69+ for p := range peerCh {
70+ peers = append (peers , p )
71+ }
72+ return peers
73+ }
74+
75+ func (dht * DHT ) GetPublicKey (ctx context.Context , id peer.ID ) (ci.PubKey , error ) {
76+ panic ("implement me" )
77+ }
78+
79+ func (dht * DHT ) Provide (ctx context.Context , cid cid.Cid , b bool ) error {
80+ panic ("implement me" )
81+ }
82+
83+ func (dht * DHT ) FindProvidersAsync (ctx context.Context , cid cid.Cid , i int ) <- chan peer.AddrInfo {
84+ panic ("implement me" )
85+ }
86+
87+ func (dht * DHT ) FindPeer (ctx context.Context , id peer.ID ) (peer.AddrInfo , error ) {
88+ panic ("implement me" )
89+ }
90+
91+ func (dht * DHT ) PutValue (ctx context.Context , s string , bytes []byte , option ... routing.Option ) error {
92+ panic ("implement me" )
93+ }
94+
95+ func (dht * DHT ) GetValue (ctx context.Context , s string , option ... routing.Option ) ([]byte , error ) {
96+ panic ("implement me" )
97+ }
98+
99+ func (dht * DHT ) SearchValue (ctx context.Context , s string , option ... routing.Option ) (<- chan []byte , error ) {
100+ panic ("implement me" )
101+ }
102+
103+ func (dht * DHT ) Bootstrap (ctx context.Context ) error {
104+ errI := dht .Inner .Bootstrap (ctx )
105+ errO := dht .Outer .Bootstrap (ctx )
106+
107+ errs := make ([]error , 0 , 2 )
108+ if errI != nil {
109+ errs = append (errs , errors .Wrap (errI , fmt .Sprintf ("failed to bootstrap inner dht" )))
110+ }
111+ if errO != nil {
112+ errs = append (errs , errors .Wrap (errI , fmt .Sprintf ("failed to bootstrap outer dht" )))
113+ }
114+
115+ switch len (errs ) {
116+ case 0 :
117+ return nil
118+ case 1 :
119+ return errs [0 ]
120+ default :
121+ return multierror .Append (errs [0 ], errs [1 :]... )
122+ }
123+ }
0 commit comments