forked from libp2p/go-libp2p-routing-helpers
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomposed.go
124 lines (110 loc) · 3.83 KB
/
composed.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package routinghelpers
import (
"context"
"github.com/hashicorp/go-multierror"
"github.com/ipfs/go-cid"
ci "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
)
// Compose composes the components into a single router. Not specifying a
// component (leaving it nil) is equivalent to specifying the Null router.
//
// It also implements Bootstrap. All *distinct* components implementing
// Bootstrap will be bootstrapped in parallel. Identical components will not be
// bootstrapped twice.
type Compose struct {
ValueStore routing.ValueStore
PeerRouting routing.PeerRouting
ContentRouting routing.ContentRouting
}
// note: we implement these methods explicitly to avoid having to manually
// specify the Null router everywhere we don't want to implement some
// functionality.
// PutValue adds value corresponding to given Key.
func (cr *Compose) PutValue(ctx context.Context, key string, value []byte, opts ...routing.Option) error {
if cr.ValueStore == nil {
return routing.ErrNotSupported
}
return cr.ValueStore.PutValue(ctx, key, value, opts...)
}
// GetValue searches for the value corresponding to given Key.
func (cr *Compose) GetValue(ctx context.Context, key string, opts ...routing.Option) ([]byte, error) {
if cr.ValueStore == nil {
return nil, routing.ErrNotFound
}
return cr.ValueStore.GetValue(ctx, key, opts...)
}
// SearchValue searches for the value corresponding to given Key.
func (cr *Compose) SearchValue(ctx context.Context, key string, opts ...routing.Option) (<-chan []byte, error) {
if cr.ValueStore == nil {
out := make(chan []byte)
close(out)
return out, nil
}
return cr.ValueStore.SearchValue(ctx, key, opts...)
}
// Provide adds the given cid to the content routing system. If 'true' is
// passed, it also announces it, otherwise it is just kept in the local
// accounting of which objects are being provided.
func (cr *Compose) Provide(ctx context.Context, c cid.Cid, local bool) error {
if cr.ContentRouting == nil {
return routing.ErrNotSupported
}
return cr.ContentRouting.Provide(ctx, c, local)
}
// FindProvidersAsync searches for peers who are able to provide a given key.
//
// If count > 0, it returns at most count providers. If count == 0, it returns
// an unbounded number of providers.
func (cr *Compose) FindProvidersAsync(ctx context.Context, c cid.Cid, count int) <-chan peer.AddrInfo {
if cr.ContentRouting == nil {
ch := make(chan peer.AddrInfo)
close(ch)
return ch
}
return cr.ContentRouting.FindProvidersAsync(ctx, c, count)
}
// FindPeer searches for a peer with given ID, returns a peer.AddrInfo
// with relevant addresses.
func (cr *Compose) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
if cr.PeerRouting == nil {
return peer.AddrInfo{}, routing.ErrNotFound
}
return cr.PeerRouting.FindPeer(ctx, p)
}
// GetPublicKey returns the public key for the given peer.
func (cr *Compose) GetPublicKey(ctx context.Context, p peer.ID) (ci.PubKey, error) {
if cr.ValueStore == nil {
return nil, routing.ErrNotFound
}
return routing.GetPublicKey(cr.ValueStore, ctx, p)
}
// Bootstrap the router.
func (cr *Compose) Bootstrap(ctx context.Context) error {
// Deduplicate. Technically, calling bootstrap multiple times shouldn't
// be an issue but using the same router for multiple fields of Compose
// is common.
routers := make(map[Bootstrap]struct{}, 3)
for _, value := range [...]interface{}{
cr.ValueStore,
cr.ContentRouting,
cr.PeerRouting,
} {
switch b := value.(type) {
case nil:
case Null:
case Bootstrap:
routers[b] = struct{}{}
}
}
var me multierror.Error
for b := range routers {
if err := b.Bootstrap(ctx); err != nil {
me.Errors = append(me.Errors, err)
}
}
return me.ErrorOrNil()
}
var _ routing.Routing = (*Compose)(nil)
var _ routing.PubKeyFetcher = (*Compose)(nil)